diff --git a/packages/@aws-cdk/aws-cloudwatch/README.md b/packages/@aws-cdk/aws-cloudwatch/README.md index 8404c6ce9ad7a..af3aaf7c5a765 100644 --- a/packages/@aws-cdk/aws-cloudwatch/README.md +++ b/packages/@aws-cdk/aws-cloudwatch/README.md @@ -104,7 +104,13 @@ graph showing the Average statistic with an aggregation period of 5 minutes: ```ts const cpuUtilization = new cloudwatch.MathExpression({ - expression: "SEARCH('{AWS/EC2,InstanceId} MetricName=\"CPUUtilization\"', 'Average', 300)" + expression: "SEARCH('{AWS/EC2,InstanceId} MetricName=\"CPUUtilization\"', 'Average', 300)", + + // Specifying '' as the label suppresses the default behavior + // of using the expression as metric label. This is especially appropriate + // when using expressions that return multiple time series (like SEARCH() + // or METRICS()), to show the labels of the retrieved metrics only. + label: '', }); ``` @@ -157,6 +163,33 @@ useful when embedding them in graphs, see below). > happen to know the Metric you want to alarm on makes sense as a rate > (`Average`) you can always choose to change the statistic. +### Labels + +Metric labels are displayed in the legend of graphs that include the metrics. + +You can use [dynamic labels](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/graph-dynamic-labels.html) +to show summary information about the displayed time series +in the legend. For example, if you use: + +```ts +declare const fn: lambda.Function; + +const minuteErrorRate = fn.metricErrors({ + statistic: 'sum', + period: Duration.hours(1), + + // Show the maximum hourly error count in the legend + label: '[max: ${MAX}] Lambda failure rate', +}); +``` + +As the metric label, the maximum value in the visible range will +be shown next to the time series name in the graph's legend. + +If the metric is a math expression producing more than one time series, the +maximum will be individually calculated and shown for each time series produce +by the math expression. + ## Alarms Alarms can be created on metrics in one of two ways. Either create an `Alarm` @@ -308,7 +341,7 @@ dashboard.addWidgets(new cloudwatch.GraphWidget({ right: [errorCountMetric.with({ statistic: "average", label: "Error rate", - color: cloudwatch.Color.GREEN + color: cloudwatch.Color.GREEN, })] })); ``` diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts index 03d9e4fe5ca7d..28868b33d9883 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts @@ -75,6 +75,18 @@ export interface CommonMetricOptions { /** * Label for this metric when added to a Graph in a Dashboard + * + * You can use [dynamic labels](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/graph-dynamic-labels.html) + * to show summary information about the entire displayed time series + * in the legend. For example, if you use: + * + * ``` + * [max: ${MAX}] MyMetric + * ``` + * + * As the metric label, the maximum value in the visible range will + * be shown next to the time series name in the graph's legend. + * * @default - No label */ readonly label?: string; @@ -127,7 +139,28 @@ export interface MetricOptions extends CommonMetricOptions { */ export interface MathExpressionOptions { /** - * Label for this metric when added to a Graph in a Dashboard + * Label for this expression when added to a Graph in a Dashboard + * + * If this expression evaluates to more than one time series (for + * example, through the use of `METRICS()` or `SEARCH()` expressions), + * each time series will appear in the graph using a combination of the + * expression label and the individual metric label. Specify the empty + * string (`''`) to suppress the expression label and only keep the + * metric label. + * + * You can use [dynamic labels](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/graph-dynamic-labels.html) + * to show summary information about the displayed time series + * in the legend. For example, if you use: + * + * ``` + * [max: ${MAX}] MyMetric + * ``` + * + * As the metric label, the maximum value in the visible range will + * be shown next to the time series name in the graph's legend. If the + * math expression produces more than one time series, the maximum + * will be shown for each individual time series produce by this + * math expression. * * @default - Expression value is used as label */ diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/private/rendering.ts b/packages/@aws-cdk/aws-cloudwatch/lib/private/rendering.ts index 9223695a96c67..13a6440f8946c 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/private/rendering.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/private/rendering.ts @@ -66,11 +66,17 @@ function metricGraphJson(metric: IMetric, yAxis?: string, id?: string) { if (yAxis !== 'left') { options.yAxis = yAxis; } if (id) { options.id = id; } - // If math expressions don't have a label (or an ID), they'll render with an unelegant - // autogenerated id ("metric_alias0"). Our ids may in the future also be autogenerated, - // so if an ME doesn't have a label, use its toString() as the label (renders the expression). if (options.visible !== false && options.expression && !options.label) { - options.label = metric.toString(); + // Label may be '' or undefined. + // + // If undefined, we'll render the expression as the label, to suppress + // the default behavior of CW where it would render the metric + // id as label, which we (inelegantly) generate to be something like "metric_alias0". + // + // For array expressions (returning more than 1 TS) users may sometimes want to + // suppress the label completely. For those cases, we'll accept the empty string, + // and not render a label at all. + options.label = options.label === '' ? undefined : metric.toString(); } const renderedOpts = dropUndefined(options); diff --git a/packages/@aws-cdk/aws-cloudwatch/test/metric-math.test.ts b/packages/@aws-cdk/aws-cloudwatch/test/metric-math.test.ts index 5f244f3b11352..d4220f83d1b50 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/metric-math.test.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/metric-math.test.ts @@ -145,6 +145,27 @@ describe('Metric Math', () => { ]); + }); + + test('passing an empty string as the label of a MathExpressions does not emit a label', () => { + const graph = new GraphWidget({ + left: [ + new MathExpression({ + expression: 'a + e', + label: '', + usingMetrics: { + a, + }, + }), + ], + }); + + graphMetricsAre(graph, [ + [{ expression: 'a + e' }], + ['Test', 'ACount', { visible: false, id: 'a' }], + ]); + + }); test('can reuse identifiers in MathExpressions if metrics are the same', () => {