Skip to content

AWS CDK - Cloudwatch - IWidget - Position

0

Hello,

Hope you're all doing well. Reaching out because I do not think the 'position' method in the IWidget interface works correctly and I wanted to reach out on here to confirm whether or not other people had experienced the same issue.

documentation on IWidget

I'm implementing a fairly standard dashboard; setting up the dashboard, generating the metrics, generating the 'widgets' and adding the metrics to the widgets, and then attaching the widgets to the dashboard.

After instantiating the dashboard with all the widgets, per the documentation I'm then subsequently arranging the spacing of the dashboard. As you'll see, the spatial arrangement is a fairly standard cartesian coordinate based system.

The 7th widget in the code is not being placed properly. It is being one "slot" to the right effectively.

        //Row #1

        //    Widget #1: All Calls
        const callsPerIntervalMetric = new Metric({
            namespace: 'AWS/Connect',
            metricName: 'CallsPerInterval',
            dimensionsMap: {
                InstanceId: awsVariables.AmazonConnect.ConnectInstanceId,
                MetricGroup: 'VoiceCalls'
            },
            label: 'Calls',
            statistic: 'Sum',
            period: Duration.minutes(5),
            region: awsVariables.Region
        });

        const singleWidget = new SingleValueWidget({
            metrics: [callsPerIntervalMetric],
            width: 3,
            height: 3,
            title: "All Calls",
            sparkline: false
        })

        //      Widget #2: Missed Calls:
        const missedCallsMetric = new Metric({
            namespace: 'AWS/Connect',
            metricName: 'MissedCalls',
            dimensionsMap: {
                InstanceId: awsVariables.AmazonConnect.ConnectInstanceId,
                MetricGroup: 'VoiceCalls'
            },
            statistic: 'Sum',
            period: Duration.minutes(5),
            color: '#d62728',
            region: awsVariables.Region
        });

        const missedCallsWidget = new SingleValueWidget({
            metrics: [missedCallsMetric],
            width: 3,
            height: 3,
            title: "Missed Calls",
            sparkline: false
        });

        //      Widget #3:
        const throttledCallsMetric = new Metric({
            namespace: 'AWS/Connect',
            metricName: 'ThrottledCalls',
            dimensionsMap: {
                InstanceId: awsVariables.AmazonConnect.ConnectInstanceId
            },
            statistic: 'Average',
            period: Duration.minutes(5),
            region: awsVariables.Region
        })

        const throttledGraphWidget = new GraphWidget({
            height: 6,
            width: 6,
            title: 'Throttled Calls',
            leftYAxis: {
                showUnits: false,
                min: 0,
                label: "Number Of Throttled Calls"
            },
            stacked: false,
            region: awsVariables.Region
        })
        //attaching metric to widget
        throttledGraphWidget.addLeftMetric(throttledCallsMetric)

        //      Widget #4: IMetric already instantiated. Re-using - See Widget #2.
        const missedCallsGraphWidget = new GraphWidget({
            height: 6,
            width: 6,
            title: "Missed Calls - Over time",
            leftYAxis: {
                showUnits: false,
                min: 0,
                label: "Calls"
            },
            rightYAxis: {
                label: "Time",
                showUnits: false
            }
        })
        
        missedCallsGraphWidget.addLeftMetric(missedCallsMetric)

        //      Widget #5: Concurrent Calls
        const concurrentCallsMetric = new Metric({
            namespace: 'AWS/Connect',
            metricName: 'ConcurrentCalls',
            dimensionsMap: {
                InstanceId: awsVariables.AmazonConnect.ConnectInstanceId
            },
            statistic: 'Sum',
            period: Duration.minutes(5),
            region: awsVariables.Region
        })

        const concurrentCallsWidget = new GraphWidget({
            height: 6,
            width: 6,
            title: 'Concurrent Calls',
            leftYAxis: {
                label: "Calls",
                showUnits: false
            },
            rightYAxis: {
                label: "Time",
                showUnits: false
            }
        })

        concurrentCallsWidget.addLeftMetric(concurrentCallsMetric)

        // Widget #6
        const lambdaErrorMetric = new Metric({
            namespace: 'AWS/Lambda',
            metricName: 'Errors',
            dimensionsMap: {
                InstanceId: awsVariables.AmazonConnect.ConnectInstanceId
            },
            statistic: 'Sum',
            region: awsVariables.Region,
            period: Duration.minutes(5),
            color: '#d62728'
        })

        const lambdaErrorsWidget = new SingleValueWidget({
            metrics: [lambdaErrorMetric],
            width: 6,
            height: 2,
            title: 'Lambda Errors',
            sparkline: false
        })

        //      Widget #7:

        const lambdaErrorsWidgetGraph = new GraphWidget({
            height: 6,
            width: 6,
            title: 'Lambda Errors - Overall',
            leftYAxis: {
                label: "Errors",
                showUnits: false
            },
            rightYAxis: {
                label: "Time",
                showUnits: false
            },
            period: Duration.minutes(5),
            statistic: 'Sum',
            region: awsVariables.Region
        })
        
        lambdaErrorsWidgetGraph.addLeftMetric(lambdaErrorMetric)

        // Add widgets with their positions
        dashboard.addWidgets(singleWidget,missedCallsWidget,throttledGraphWidget,missedCallsGraphWidget, concurrentCallsWidget,lambdaErrorsWidget,lambdaErrorsWidgetGraph);
        //Row #1
        singleWidget.position(0,0); 
        missedCallsWidget.position(3,0)
        throttledGraphWidget.position(6,0)
        missedCallsGraphWidget.position(12,0)
        concurrentCallsWidget.position(18,0)
        //Be careful about the 'position' on this one. Not clear to me that the position function works as intended in certain cases.
        lambdaErrorsWidget.position(0,3)
        //Row #2
        lambdaErrorsWidgetGraph.position(0,6)
        
    } // Constructor

As you can see, the last widget is being "forced" out of the proper location.

As you can see, the last widget is being forced into the second column. I presume there is something about the widget above it that is causing this. But this is confusing, at one point I even tried to deploy it (the 'widget' above the one on the second row) with a height of '2' instead of '3' so it wouldn't occupy the entire slot to see if that would stop it from bumping the 'first widget' on the second row over.

Anyone have any experience with this?

asked 2 years ago495 views

1 Answer
0

Thank you for sharing your experience with the CloudWatch dashboard widget positioning in AWS CDK. The issue you're encountering with the positioning of the 7th widget (lambdaErrorsWidgetGraph) is not uncommon when working with CloudWatch dashboard layouts.

The positioning of widgets in CloudWatch dashboards is based on a grid system, where each widget occupies a certain number of grid units in width and height. The position method you're using should theoretically place the widgets at the specified coordinates, but there are some nuances to consider:

  1. Widget sizes: Each widget has a defined width and height. If a widget's dimensions overlap with another widget's position, CloudWatch may automatically adjust the layout to prevent overlapping.

  2. Grid constraints: The dashboard has a maximum width (usually 24 grid units). If a widget would extend beyond this width, it may be pushed to the next row.

  3. Automatic layout adjustments: CloudWatch sometimes makes automatic adjustments to optimize the layout, which can result in widgets not appearing exactly where specified.

In your specific case, the issue might be related to the cumulative width of the widgets in the first row. Let's break it down:

  • singleWidget and missedCallsWidget: 3 units each (0-3, 3-6)
  • throttledGraphWidget: 6 units (6-12)
  • missedCallsGraphWidget: 6 units (12-18)
  • concurrentCallsWidget: 6 units (18-24)

This totals 24 units, which is typically the maximum width of a CloudWatch dashboard. The lambdaErrorsWidget with a width of 6 units might be getting pushed to the next available space, which is the second column of the second row.

To resolve this, you could try the following:

  1. Adjust the widths of your widgets to ensure they fit within the 24-unit constraint.
  2. Experiment with different positioning values, perhaps starting the second row at a lower y-coordinate.
  3. Consider using a different layout approach, such as creating row objects and adding widgets to specific rows.

If the issue persists, it might be worth reporting it to AWS support or the CDK GitHub repository as a potential bug in the position method implementation.
Sources
Using widgets on CloudWatch dashboards - Amazon CloudWatch
Creating a custom widget for a CloudWatch dashboard - Amazon CloudWatch

answered 2 years ago

  • This is made up. Your answer is wrong.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.