Skip to content

Commit b59aed0

Browse files
authored
fix(cloudwatch): Alarm can't use MathExpression without submetrics
`MathExpression`s without submetrics (like for example, `INSIGHT_RULE_METRIC`) will end up without a `period`, which is not allowed. Add a `period` field to the schema (it's not in the upstream schema yet), and render it out when submetrics are missing. Fixes #7155.
1 parent aa9dd83 commit b59aed0

File tree

6 files changed

+55
-2
lines changed

6 files changed

+55
-2
lines changed

packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { IAlarmAction } from './alarm-action';
33
import { CfnAlarm, CfnAlarmProps } from './cloudwatch.generated';
44
import { HorizontalAnnotation } from './graph';
55
import { CreateAlarmOptions } from './metric';
6-
import { IMetric, MetricStatConfig } from './metric-types';
6+
import { IMetric, MetricExpressionConfig, MetricStatConfig } from './metric-types';
77
import { dispatchMetric, metricPeriod } from './private/metric-util';
88
import { dropUndefined } from './private/object';
99
import { MetricSet } from './private/rendering';
@@ -326,6 +326,7 @@ export class Alarm extends Resource implements IAlarm {
326326
expression: expr.expression,
327327
id: entry.id || uniqueMetricId(),
328328
label: conf.renderingProperties?.label,
329+
period: mathExprHasSubmetrics(expr) ? undefined : expr.period,
329330
returnData: entry.tag ? undefined : false, // Tag stores "primary" attribute, default is "true"
330331
};
331332
},
@@ -388,4 +389,8 @@ function renderIfExtendedStatistic(statistic?: string): string | undefined {
388389
return undefined;
389390
}
390391

392+
function mathExprHasSubmetrics(expr: MetricExpressionConfig) {
393+
return Object.keys(expr.usingMetrics).length > 0;
394+
}
395+
391396
type Writeable<T> = { -readonly [P in keyof T]: T[P] };

packages/@aws-cdk/aws-cloudwatch/lib/metric-types.ts

+5
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,11 @@ export interface MetricExpressionConfig {
315315
* Metrics used in the math expression
316316
*/
317317
readonly usingMetrics: Record<string, IMetric>;
318+
319+
/**
320+
* How many seconds to aggregate over
321+
*/
322+
readonly period: number;
318323
}
319324

320325
/**

packages/@aws-cdk/aws-cloudwatch/lib/metric.ts

+1
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ export class MathExpression implements IMetric {
485485
public toMetricConfig(): MetricConfig {
486486
return {
487487
mathExpression: {
488+
period: this.period.toSeconds(),
488489
expression: this.expression,
489490
usingMetrics: this.usingMetrics,
490491
},

packages/@aws-cdk/aws-cloudwatch/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@
9898
"props-default-doc:@aws-cdk/aws-cloudwatch.MetricGraphConfig.unit",
9999
"props-default-doc:@aws-cdk/aws-cloudwatch.MetricRenderingProperties.color",
100100
"props-default-doc:@aws-cdk/aws-cloudwatch.MetricRenderingProperties.label",
101-
"props-default-doc:@aws-cdk/aws-cloudwatch.MetricRenderingProperties.stat"
101+
"props-default-doc:@aws-cdk/aws-cloudwatch.MetricRenderingProperties.stat",
102+
"duration-prop-type:@aws-cdk/aws-cloudwatch.MetricExpressionConfig.period"
102103
]
103104
},
104105
"engines": {

packages/@aws-cdk/aws-cloudwatch/test/test.metric-math.ts

+22
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,28 @@ export = {
507507
test.done();
508508
},
509509

510+
'MathExpression without inner metrics emits its own period'(test: Test) {
511+
// WHEN
512+
new Alarm(stack, 'Alarm', {
513+
threshold: 1, evaluationPeriods: 1,
514+
metric: new MathExpression({
515+
expression: 'INSIGHT_RULE_METRIC("SomeId", UniqueContributors)',
516+
usingMetrics: {},
517+
}),
518+
});
519+
520+
// THEN
521+
alarmMetricsAre([
522+
{
523+
Expression: 'INSIGHT_RULE_METRIC("SomeId", UniqueContributors)',
524+
Id: 'expr_1',
525+
Period: 300,
526+
},
527+
]);
528+
529+
test.done();
530+
},
531+
510532
'annotation for a mathexpression alarm is calculated based upon constituent metrics'(test: Test) {
511533
// GIVEN
512534
const alarm = new Alarm(stack, 'Alarm', {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"PropertyTypes": {
3+
"AWS::CloudWatch::Alarm.MetricDataQuery": {
4+
"patch": {
5+
"description": "Add Period to AWS::CloudWatch::Alarm.MetricDataQuery (#7155)",
6+
"operations": [
7+
{
8+
"op": "add",
9+
"path": "/Properties/Period",
10+
"value": {
11+
"PrimitiveType": "Integer",
12+
"UpdateType": "Mutable"
13+
}
14+
}
15+
]
16+
}
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)