def create_cw_dashboard()

in resources/code/Monitoring/create-cw-dashboard.py [0:0]


def create_cw_dashboard(ec2_list, networklimit):
    widgets = {"widgets": []}
    number = 1
    # EBS to the EC2
    for ec2instance in ec2_list:
        instance_name = get_instance_name(ec2instance)
        ec2instance_type = ec2.Instance(ec2instance)
        ec2_details = ec2client.describe_instance_types(InstanceTypes=[ec2instance_type.instance_type])
        ebs_volumes = get_ebs(ec2instance) ## get all EBS volumes per instance

        ## New instance Header
        new_widget = {
            "type": "text",
            "width": 24,
            "height": 4,
            "properties": {
                "markdown": f'\n# Report #{number}\
                            \n\n**Instance ID:** {ec2instance} \
                            \n\n**Tag:Name:** {instance_name} \
                            \n\n**InstanceType:** {ec2instance_type.instance_type} \
                            \n\n**Attached Volumes:** {ebs_volumes}'
            }
        }
        widgets['widgets'].append(new_widget)

        ## Instance -> Internet Gateway
        new_widget = {
            "type": "text",
            "width": 24,
            "height": 2,
            "properties": {
                "markdown": "\n## " + "EC2 (" + ec2instance_type.instance_type + ") --> " + "Network" +"\n"
            }
        }
        widgets['widgets'].append(new_widget)
        ec2_NetworkInfo = ec2_details['InstanceTypes'][0]['NetworkInfo']
        # Extract the number
        numbers = []
        for word in ec2_NetworkInfo['NetworkPerformance'].split():
            if word.isdigit():
                numbers.append(int(word))
        
        if(len(numbers) == 0):
            numbers.append(5)

        # EC2 Metrics 
        new_widget = {
            "type": "metric",
            "width": 24,
            "properties": {
                "metrics": [
                    [ { "expression": "SUM(METRICS('network'))/PERIOD(networkOut)", "label": "Bandwidth (Bytes)", "id": "bandwidthBytes", "visible": False , "period": 300} ], 
                    [ { "expression": "bandwidthBytes*0.000008", "label": "Bandwidth (Mbps - Megabits)", "id": "bandwidthMbps" , "period": 300} ], # Convert Bytes to Megabits -> 1 B = 0.000008 Mb
                    [ "AWS/EC2", "NetworkIn", "InstanceId", ec2instance, { "visible": False, "id": "networkIn", "period": 300 } ],
                    [ "AWS/EC2", "NetworkOut", "InstanceId", ec2instance, { "visible": False, "id": "networkOut" , "period": 300} ]
                ],
                "view": "timeSeries",
                "stacked": False,
                "region": region,
                "stat": "Sum",
                "period": 300,
                "title": ec2instance + " --> Network",
                "annotations": {
                    "horizontal": [
                        {
                            "label": "Maximum Throughput (Mbps)",
                            "value": numbers[0]*1000
                        }
                    ]
                }
            }
        }
        widgets['widgets'].append(new_widget)


        ## Instance -> EBS
        new_widget = {
            "type": "text",
            "width": 24,
            "height": 2,
            "properties": {
                "markdown": "\n## " + "Amazon EC2" + " --> " + "Amazon EBS" +"\n"
            }
        }
        widgets['widgets'].append(new_widget)
        if(networklimit['InstanceTypes'][ec2instance_type.instance_type]['EbsInfo']['EbsOptimizedSupport'] != 'unsupported'):
            network_to_ebs = networklimit['InstanceTypes'][ec2instance_type.instance_type]['EbsInfo']['EbsOptimizedInfo']['MaximumBandwidthInMbps']
            network_to_ebs_half = network_to_ebs*0.5
            network_to_ebs_iops = networklimit['InstanceTypes'][ec2instance_type.instance_type]['EbsInfo']['EbsOptimizedInfo']['MaximumIops']
            network_to_ebs_iops_half = network_to_ebs_iops*0.5
        else:
            network_to_ebs = 0
            network_to_ebs_half = 0
            network_to_ebs_iops = 0
            network_to_ebs_iops_half = 0
        new_widget = {
            "type": "metric",
            "width": 12,
            "properties": {
                "metrics": [
                    [ { "expression": "SUM(METRICS('ebs'))/PERIOD(ebsReadBytes)", "label": "Total IO In Bytes", "id": "totalIOBytes", "visible": False , "period": 300 } ], # (ebsReadBytes + ebsWriteBytes) / Period
                    [ { "expression": "totalIOBytes*0.000008", "label": "Bandwidth (Mbps - Megabits)", "id": "bandwidthMbps" , "period": 300} ], # Convert Bytes to Megabits -> 1 B = 0.000008 Mb
                    [ "AWS/EC2", "EBSReadBytes", "InstanceId", ec2instance, { "visible": False, "id": "ebsReadBytes", "period": 300 } ],
                    [ ".", "EBSWriteBytes", ".", ".", { "visible": False, "id": "ebsWriteBytes", "period": 300 } ]
                ],
                "view": "timeSeries",
                "stacked": False,
                "region": region,
                "stat": "Sum",
                "period": 300,
                "title": ec2instance + " -> EBS (Throughput)",
                "annotations": {
                    "horizontal": [
                        {
                            "label": "Maximum Throughput (Mbps)",
                            "value": network_to_ebs
                        },
                        {
                            "label": "50% Throughput (Mbps)",
                            "value": network_to_ebs_half
                        }
                    ]
                }
            }
        }
        widgets['widgets'].append(new_widget)

        new_widget = {
            "type": "metric",
            "width": 12,
            "properties": {
                "metrics": [
                    [ { "expression": "SUM(METRICS('ebs'))/PERIOD(ebsWriteOps)", "label": "Total IOPS", "id": "totalIOPS", "visible": True , "period": 300 } ], 
                    [ "AWS/EC2", "EBSWriteOps", "InstanceId", ec2instance, { "visible": False, "id": "ebsReadOps", "period": 300 } ],
                    [ ".", "EBSReadOps", ".", ".", { "visible": False, "id": "ebsWriteOps", "period": 300 } ]
                ],
                "view": "timeSeries",
                "stacked": False,
                "region": region,
                "stat": "Sum",
                "period": 300,
                "title": ec2instance + " -> Amazon EBS (IOPS)",
                "annotations": {
                    "horizontal": [
                        {
                            "label": "Maximum IOPS",
                            "value": network_to_ebs_iops
                        },
                        {
                            "label": "50% IOPS",
                            "value": network_to_ebs_iops_half
                        }
                    ]
                }
            }
        }
        widgets['widgets'].append(new_widget)

        ## EBS -> Instance
        new_widget = {
            "type": "text",
            "width": 24,
            "height": 2,
            "properties": {
                "markdown": "\n## Amazon EBS --> Amazon EC2 \n"
            }
        }
        widgets['widgets'].append(new_widget)

        for volume in ebs_volumes:
            volume_speed = ec2.Volume(volume)
            new_widget = {
                "type": "text",
                "width": 24,
                "height": 2,
                "properties": {
                    "markdown": "\n### InstanceID: " +ec2instance + " Volume: "+ volume +" ("+volume_speed.volume_type +")\n"
                }
            }
            widgets['widgets'].append(new_widget)
            ## Volume Throughput
            new_widget = {
                "type": "metric",
                "width": 12,
                "properties": {
                    "metrics": [
                        [ { "expression": "SUM(METRICS('volume'))/PERIOD(volumeReadBytes)", "label": "Total IO (Bytes)", "id": "volumeThroughputBytes", "visible": False, "stat": "Sum", "period": 300 } ],
                        [ { "expression": "volumeThroughputBytes/1024/1024", "label": "Total Throughput (MB/s - MegaBytes per second)", "id": "volumeThroughputMBps", "stat": "Sum", "period": 300 } ], 
                        [ "AWS/EBS", "VolumeWriteBytes", "VolumeId", volume, { "visible": False, "id": "volumeWriteBytes", "period": 300 } ],
                        [ "AWS/EBS", "VolumeReadBytes", "VolumeId", volume, { "visible": False, "id": "volumeReadBytes", "period": 300 } ]
                    ],
                    "view": "timeSeries",
                    "stacked": False,
                    "region": region,
                    "stat": "Sum",
                    "period": 300,
                    "yAxis": {
                        "left": {
                            "showUnits": False,
                            "label": "MiB/s"
                        },
                        "right": {
                            "showUnits": False
                        }
                    },
                    "title": "Throughput" + "(" + volume +")"
                }
            }

            # Add space for annotations
            new_widget['properties'].update({'annotations': {'horizontal': []}})
            flagForIOPS = True

            if volume_speed.volume_type == "gp2":
                if (volume_speed.size < 170):
                    new_widget['properties']['annotations']['horizontal'].append({"label": "Maximum Throughput (MBps)","value": 128})
                if (volume_speed.size > 170 and volume_speed.size < 334):
                    new_widget['properties']['annotations']['horizontal'].append({"label": "Maximum Throughput (MBps) ** (if burst credits are available)","value": 250})
                if (volume_speed.size > 334):
                    new_widget['properties']['annotations']['horizontal'].append({"label": "Maximum Throughput (MBps)","value": 250})
            if volume_speed.volume_type == "io2" or volume_speed.volume_type == "io1":
                new_widget['properties']['annotations']['horizontal'].append({"label": "Maximum Throughput (MBps)","value": 1000})
            if volume_speed.volume_type == "st1":
                new_widget['properties']['annotations']['horizontal'].append({"label": "Maximum Throughput (MBps)","value": 500})
                flagForIOPS = False
            if volume_speed.volume_type == "sc1":
                new_widget['properties']['annotations']['horizontal'].append({"label": "Maximum Throughput (MBps)","value": 250})
                flagForIOPS = False
            if  volume_speed.volume_type == "gp3":
                try:
                    throughput = volume_speed.throughput
                except AttributeError:
                    throughput = 125
                new_widget['properties']['annotations']['horizontal'].append({"label": "Baseline Throughput (MBps)","value": throughput})
            widgets['widgets'].append(new_widget)
            iopsValue = 0

            if bool(flagForIOPS):
                if(volume_speed.iops is not None):
                    iopsValue = volume_speed.iops
                else:
                    iopsValue = 0
            else:
                iopsValue = 0

            # Volume IOPS
            new_widget = {
                "type": "metric",
                "width": 12,
                "properties": {
                    "metrics": [
                        [ { "expression": "SUM(METRICS('volume'))/PERIOD(volumeReadOps)", "label": "Total IOPS (Operations Per Second)", "id": "totalIOPS", "stat": "Sum", "period": 300 } ],
                        [ "AWS/EBS", "VolumeWriteOps", "VolumeId", volume, { "visible": False, "id": "volumeWriteOps", "period": 300 } ],
                        [ "AWS/EBS", "VolumeReadOps", "VolumeId", volume, { "visible": False, "id": "volumeReadOps" , "period": 300} ]
                    ],
                    "view": "timeSeries",
                    "stacked": False,
                    "region": region,
                    "stat": "Sum",
                    "period": 300,
                    "yAxis": {
                        "left": {
                            "showUnits": False,
                            "label": "IOPS"
                        },
                        "right": {
                            "showUnits": False
                        }
                    },
                    "title": "IOPS" + "(" + volume +")",
                    "annotations": {
                    "horizontal": [
                        {
                            "label": "Baseline performance - IOPS",
                            "value": iopsValue
                        }
                    ]
                }
                }
            }
            if volume_speed.volume_type == "gp2":
                new_widget['properties']['annotations']['horizontal'].append({"label": "Burst IOPS","value": 3000})
            if volume_speed.volume_type == "gp3" and iopsValue != 3000:
                new_widget['properties']['annotations']['horizontal'].append({"label": "Burst IOPS","value": 3000})
            widgets['widgets'].append(new_widget)
        number += 1

    dashboard = {"periodOverride": "inherit", "widgets": widgets['widgets']}
    result = cw.put_dashboard(DashboardName=CloudWatch_DashboardName,DashboardBody=json.dumps(dashboard))
    if 'ResponseMetadata' in result:
        if 'HTTPStatusCode' in result['ResponseMetadata']:
            if result['ResponseMetadata']['HTTPStatusCode'] == 200:
                print(f'Dashboard successfully created. \nLink to the dashboard: https://console.aws.amazon.com/cloudwatch/home?region={region}#dashboards:name={CloudWatch_DashboardName}')
    else:
        print("error with request")