Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cloudwatch): Additional Properties for Cloudwatch AlarmStatusWidget #19387

Merged
merged 13 commits into from Mar 24, 2022
14 changes: 14 additions & 0 deletions packages/@aws-cdk/aws-cloudwatch/README.md
Expand Up @@ -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:
Expand Down
47 changes: 47 additions & 0 deletions 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
*/
Expand All @@ -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[];
}

/**
Expand Down Expand Up @@ -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,
},
},
];
Expand Down
@@ -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
Expand Down Expand Up @@ -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'],
},
},
]);

});
});
Expand Up @@ -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"
},
Expand All @@ -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"
},
Expand All @@ -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"
},
Expand All @@ -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"
},
Expand Down
Expand Up @@ -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],
Expand Down