From 3c9ea5f31e3113fb0d2ba5c633fcd665294a70eb Mon Sep 17 00:00:00 2001 From: markussiebert Date: Thu, 24 Mar 2022 01:28:06 +0100 Subject: [PATCH] feat(cloudwatch): Additional Properties for Cloudwatch AlarmStatusWidget (#19387) I've added the missing properties from the Alarm Status Widget see: https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/CloudWatch-Dashboard-Body-Structure.html#CloudWatch-Dashboard-Properties-Alarm-Widget-Object fixes: #19386 *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/aws-cloudwatch/README.md | 14 ++++++ .../aws-cloudwatch/lib/alarm-status-widget.ts | 47 +++++++++++++++++++ .../test/alarm-status-widget.test.ts | 33 ++++++++++++- .../integ.alarm-and-dashboard.expected.json | 25 ++++++---- .../test/integ.alarm-and-dashboard.ts | 4 ++ 5 files changed, 113 insertions(+), 10 deletions(-) diff --git a/packages/@aws-cdk/aws-cloudwatch/README.md b/packages/@aws-cdk/aws-cloudwatch/README.md index 37a31f636b3ad..8404c6ce9ad7a 100644 --- a/packages/@aws-cdk/aws-cloudwatch/README.md +++ b/packages/@aws-cdk/aws-cloudwatch/README.md @@ -436,6 +436,20 @@ dashboard.addWidgets( ); ``` +An alarm status widget only showing firing alarms, sorted by state and timestamp: + +```ts +declare const dashboard: cloudwatch.Dashboard; +declare const errorAlarm: cloudwatch.Alarm; + +dashboard.addWidgets(new cloudwatch.AlarmStatusWidget({ + title: "Errors", + alarms: [errorAlarm], + sortBy: cloudwatch.AlarmStatusWidgetSortBy.STATE_UPDATED_TIMESTAMP, + states: [cloudwatch.AlarmState.ALARM], +})); +``` + ### Query results widget A `LogQueryWidget` shows the results of a query from Logs Insights: diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/alarm-status-widget.ts b/packages/@aws-cdk/aws-cloudwatch/lib/alarm-status-widget.ts index 3562a0b9cba6b..852fe4051ac5f 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/alarm-status-widget.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/alarm-status-widget.ts @@ -1,6 +1,33 @@ import { IAlarm } from './alarm-base'; +import { AlarmState } from './alarm-rule'; import { ConcreteWidget } from './widget'; + +/** + * The sort possibilities for AlarmStatusWidgets + */ +export enum AlarmStatusWidgetSortBy { + + /** + * Choose DEFAULT to sort them in alphabetical order by alarm name. + */ + DEFAULT = 'default', + + /** + * Choose STATE_UPDATED_TIMESTAMP to sort them first by alarm state, with alarms in ALARM state first, + * INSUFFICIENT_DATA alarms next, and OK alarms last. + * Within each group, the alarms are sorted by when they last changed state, with more recent state changes listed first. + */ + STATE_UPDATED_TIMESTAMP = 'stateUpdatedTimestamp', + + /** + * Choose TIMESTAMP to sort them by the time when the alarms most recently changed state, + * no matter the current alarm state. + * The alarm that changed state most recently is listed first. + */ + TIMESTAMP = 'timestamp', +} + /** * Properties for an Alarm Status Widget */ @@ -27,6 +54,24 @@ export interface AlarmStatusWidgetProps { * @default 3 */ readonly height?: number; + + /** + * Specifies how to sort the alarms in the widget. + * + * @default - alphabetical order + */ + readonly sortBy?: AlarmStatusWidgetSortBy; + + /** + * Use this field to filter the list of alarms displayed in the widget to only those alarms currently in the specified states. + * You can specify one or more alarm states in the value for this field. + * The alarm states that you can specify are ALARM, INSUFFICIENT_DATA, and OK. + * + * If you omit this field or specify an empty array, all the alarms specifed in alarms are displayed. + * + * @default - all the alarms specified in alarms are displayed. + */ + readonly states?: AlarmState[]; } /** @@ -56,6 +101,8 @@ export class AlarmStatusWidget extends ConcreteWidget { properties: { title: this.props.title ? this.props.title : 'Alarm Status', alarms: this.props.alarms.map((alarm) => alarm.alarmArn), + states: this.props.states, + sortBy: this.props.sortBy, }, }, ]; diff --git a/packages/@aws-cdk/aws-cloudwatch/test/alarm-status-widget.test.ts b/packages/@aws-cdk/aws-cloudwatch/test/alarm-status-widget.test.ts index 3c771ba47ea05..31cb33c724237 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/alarm-status-widget.test.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/alarm-status-widget.test.ts @@ -1,5 +1,5 @@ import { Stack } from '@aws-cdk/core'; -import { Metric, Alarm, AlarmStatusWidget } from '../lib'; +import { Metric, Alarm, AlarmStatusWidget, AlarmStatusWidgetSortBy, AlarmState } from '../lib'; describe('Alarm Status Widget', () => { test('alarm status widget', () => { // GIVEN @@ -28,7 +28,38 @@ describe('Alarm Status Widget', () => { }, }, ]); + }); + test('alarm status widget custom props', () => { + // GIVEN + const stack = new Stack(); + const metric = new Metric({ namespace: 'CDK', metricName: 'Test' }); + const alarm = new Alarm(stack, 'Alarm', { + metric, + threshold: 1, + evaluationPeriods: 1, + }); + + // WHEN + const widget = new AlarmStatusWidget({ + alarms: [alarm], + sortBy: AlarmStatusWidgetSortBy.STATE_UPDATED_TIMESTAMP, + states: [AlarmState.ALARM], + }); + // THEN + expect(stack.resolve(widget.toJson())).toEqual([ + { + type: 'alarm', + width: 6, + height: 3, + properties: { + title: 'Alarm Status', + alarms: [{ 'Fn::GetAtt': ['Alarm7103F465', 'Arn'] }], + sortBy: 'stateUpdatedTimestamp', + states: ['ALARM'], + }, + }, + ]); }); }); diff --git a/packages/@aws-cdk/aws-cloudwatch/test/integ.alarm-and-dashboard.expected.json b/packages/@aws-cdk/aws-cloudwatch/test/integ.alarm-and-dashboard.expected.json index cdd7382b40f17..ab719f5952e61 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/integ.alarm-and-dashboard.expected.json +++ b/packages/@aws-cdk/aws-cloudwatch/test/integ.alarm-and-dashboard.expected.json @@ -45,7 +45,14 @@ "Arn" ] }, - "\"]},\"yAxis\":{}}},{\"type\":\"metric\",\"width\":6,\"height\":6,\"x\":0,\"y\":8,\"properties\":{\"view\":\"timeSeries\",\"title\":\"More messages in queue with alarm annotation\",\"region\":\"", + "\"]},\"yAxis\":{}}},{\"type\":\"alarm\",\"width\":6,\"height\":3,\"x\":0,\"y\":8,\"properties\":{\"title\":\"Firing alarms\",\"alarms\":[\"", + { + "Fn::GetAtt": [ + "Alarm7103F465", + "Arn" + ] + }, + "\"]}},{\"type\":\"metric\",\"width\":6,\"height\":6,\"x\":0,\"y\":11,\"properties\":{\"view\":\"timeSeries\",\"title\":\"More messages in queue with alarm annotation\",\"region\":\"", { "Ref": "AWS::Region" }, @@ -56,7 +63,7 @@ "QueueName" ] }, - "\"]],\"annotations\":{\"horizontal\":[{\"label\":\"ApproximateNumberOfMessagesVisible >= 100 for 2 datapoints within 15 minutes\",\"value\":100,\"yAxis\":\"left\"}]},\"yAxis\":{}}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":14,\"properties\":{\"view\":\"singleValue\",\"title\":\"Current messages in queue\",\"region\":\"", + "\"]],\"annotations\":{\"horizontal\":[{\"label\":\"ApproximateNumberOfMessagesVisible >= 100 for 2 datapoints within 15 minutes\",\"value\":100,\"yAxis\":\"left\"}]},\"yAxis\":{}}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":17,\"properties\":{\"view\":\"singleValue\",\"title\":\"Current messages in queue\",\"region\":\"", { "Ref": "AWS::Region" }, @@ -67,27 +74,27 @@ "QueueName" ] }, - "\"]]}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":17,\"properties\":{\"view\":\"table\",\"title\":\"Errors in my log group\",\"region\":\"", + "\"]]}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":20,\"properties\":{\"view\":\"table\",\"title\":\"Errors in my log group\",\"region\":\"", { "Ref": "AWS::Region" }, - "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":23,\"properties\":{\"view\":\"bar\",\"title\":\"Errors in my log group - bar\",\"region\":\"", + "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":26,\"properties\":{\"view\":\"bar\",\"title\":\"Errors in my log group - bar\",\"region\":\"", { "Ref": "AWS::Region" }, - "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":29,\"properties\":{\"view\":\"timeSeries\",\"title\":\"Errors in my log group - line\",\"region\":\"", + "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":32,\"properties\":{\"view\":\"timeSeries\",\"title\":\"Errors in my log group - line\",\"region\":\"", { "Ref": "AWS::Region" }, - "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\",\"stacked\":false}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":35,\"properties\":{\"view\":\"timeSeries\",\"title\":\"Errors in my log group - stacked\",\"region\":\"", + "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\",\"stacked\":false}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":38,\"properties\":{\"view\":\"timeSeries\",\"title\":\"Errors in my log group - stacked\",\"region\":\"", { "Ref": "AWS::Region" }, - "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\",\"stacked\":true}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":41,\"properties\":{\"view\":\"pie\",\"title\":\"Errors in my log group - pie\",\"region\":\"", + "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\",\"stacked\":true}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":44,\"properties\":{\"view\":\"pie\",\"title\":\"Errors in my log group - pie\",\"region\":\"", { "Ref": "AWS::Region" }, - "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":47,\"properties\":{\"view\":\"singleValue\",\"title\":\"Sent message size\",\"region\":\"", + "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":50,\"properties\":{\"view\":\"singleValue\",\"title\":\"Sent message size\",\"region\":\"", { "Ref": "AWS::Region" }, @@ -98,7 +105,7 @@ "QueueName" ] }, - "\"]],\"singleValueFullPrecision\":false}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":50,\"properties\":{\"view\":\"singleValue\",\"title\":\"Sent message size with full precision\",\"region\":\"", + "\"]],\"singleValueFullPrecision\":false}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":53,\"properties\":{\"view\":\"singleValue\",\"title\":\"Sent message size with full precision\",\"region\":\"", { "Ref": "AWS::Region" }, diff --git a/packages/@aws-cdk/aws-cloudwatch/test/integ.alarm-and-dashboard.ts b/packages/@aws-cdk/aws-cloudwatch/test/integ.alarm-and-dashboard.ts index 799dad893e227..d76f441d3c28c 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/integ.alarm-and-dashboard.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/integ.alarm-and-dashboard.ts @@ -45,6 +45,10 @@ dashboard.addWidgets(new cloudwatch.AlarmWidget({ title: 'Messages in queue', alarm, })); +dashboard.addWidgets(new cloudwatch.AlarmStatusWidget({ + title: 'Firing alarms', + alarms: [alarm], +})); dashboard.addWidgets(new cloudwatch.GraphWidget({ title: 'More messages in queue with alarm annotation', left: [numberOfMessagesVisibleMetric],