1 | # Amazon CloudWatch Construct Library
|
2 |
|
3 |
|
4 | ---
|
5 |
|
6 | 
|
7 |
|
8 | 
|
9 |
|
10 | ---
|
11 |
|
12 |
|
13 |
|
14 | ## Metric objects
|
15 |
|
16 | Metric objects represent a metric that is emitted by AWS services or your own
|
17 | application, such as `CPUUsage`, `FailureCount` or `Bandwidth`.
|
18 |
|
19 | Metric objects can be constructed directly or are exposed by resources as
|
20 | attributes. Resources that expose metrics will have functions that look
|
21 | like `metricXxx()` which will return a Metric object, initialized with defaults
|
22 | that make sense.
|
23 |
|
24 | For example, `lambda.Function` objects have the `fn.metricErrors()` method, which
|
25 | represents the amount of errors reported by that Lambda function:
|
26 |
|
27 | ```ts
|
28 | declare const fn: lambda.Function;
|
29 |
|
30 | const errors = fn.metricErrors();
|
31 | ```
|
32 |
|
33 | `Metric` objects can be account and region aware. You can specify `account` and `region` as properties of the metric, or use the `metric.attachTo(Construct)` method. `metric.attachTo()` will automatically copy the `region` and `account` fields of the `Construct`, which can come from anywhere in the Construct tree.
|
34 |
|
35 | You can also instantiate `Metric` objects to reference any
|
36 | [published metric](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html)
|
37 | that's not exposed using a convenience method on the CDK construct.
|
38 | For example:
|
39 |
|
40 | ```ts
|
41 | const hostedZone = new route53.HostedZone(this, 'MyHostedZone', { zoneName: "example.org" });
|
42 | const metric = new cloudwatch.Metric({
|
43 | namespace: 'AWS/Route53',
|
44 | metricName: 'DNSQueries',
|
45 | dimensionsMap: {
|
46 | HostedZoneId: hostedZone.hostedZoneId
|
47 | }
|
48 | });
|
49 | ```
|
50 |
|
51 | ### Instantiating a new Metric object
|
52 |
|
53 | If you want to reference a metric that is not yet exposed by an existing construct,
|
54 | you can instantiate a `Metric` object to represent it. For example:
|
55 |
|
56 | ```ts
|
57 | const metric = new cloudwatch.Metric({
|
58 | namespace: 'MyNamespace',
|
59 | metricName: 'MyMetric',
|
60 | dimensionsMap: {
|
61 | ProcessingStep: 'Download'
|
62 | }
|
63 | });
|
64 | ```
|
65 |
|
66 | ### Metric Math
|
67 |
|
68 | Math expressions are supported by instantiating the `MathExpression` class.
|
69 | For example, a math expression that sums two other metrics looks like this:
|
70 |
|
71 | ```ts
|
72 | declare const fn: lambda.Function;
|
73 |
|
74 | const allProblems = new cloudwatch.MathExpression({
|
75 | expression: "errors + throttles",
|
76 | usingMetrics: {
|
77 | errors: fn.metricErrors(),
|
78 | faults: fn.metricThrottles(),
|
79 | }
|
80 | });
|
81 | ```
|
82 |
|
83 | You can use `MathExpression` objects like any other metric, including using
|
84 | them in other math expressions:
|
85 |
|
86 | ```ts
|
87 | declare const fn: lambda.Function;
|
88 | declare const allProblems: cloudwatch.MathExpression;
|
89 |
|
90 | const problemPercentage = new cloudwatch.MathExpression({
|
91 | expression: "(problems / invocations) * 100",
|
92 | usingMetrics: {
|
93 | problems: allProblems,
|
94 | invocations: fn.metricInvocations()
|
95 | }
|
96 | });
|
97 | ```
|
98 |
|
99 | ### Search Expressions
|
100 |
|
101 | Math expressions also support search expressions. For example, the following
|
102 | search expression returns all CPUUtilization metrics that it finds, with the
|
103 | graph showing the Average statistic with an aggregation period of 5 minutes:
|
104 |
|
105 | ```ts
|
106 | const cpuUtilization = new cloudwatch.MathExpression({
|
107 | expression: "SEARCH('{AWS/EC2,InstanceId} MetricName=\"CPUUtilization\"', 'Average', 300)",
|
108 |
|
109 | // Specifying '' as the label suppresses the default behavior
|
110 | // of using the expression as metric label. This is especially appropriate
|
111 | // when using expressions that return multiple time series (like SEARCH()
|
112 | // or METRICS()), to show the labels of the retrieved metrics only.
|
113 | label: '',
|
114 | });
|
115 | ```
|
116 |
|
117 | Cross-account and cross-region search expressions are also supported. Use
|
118 | the `searchAccount` and `searchRegion` properties to specify the account
|
119 | and/or region to evaluate the search expression against.
|
120 |
|
121 | ### Aggregation
|
122 |
|
123 | To graph or alarm on metrics you must aggregate them first, using a function
|
124 | like `Average` or a percentile function like `P99`. By default, most Metric objects
|
125 | returned by CDK libraries will be configured as `Average` over `300 seconds` (5 minutes).
|
126 | The exception is if the metric represents a count of discrete events, such as
|
127 | failures. In that case, the Metric object will be configured as `Sum` over `300
|
128 | seconds`, i.e. it represents the number of times that event occurred over the
|
129 | time period.
|
130 |
|
131 | If you want to change the default aggregation of the Metric object (for example,
|
132 | the function or the period), you can do so by passing additional parameters
|
133 | to the metric function call:
|
134 |
|
135 | ```ts
|
136 | declare const fn: lambda.Function;
|
137 |
|
138 | const minuteErrorRate = fn.metricErrors({
|
139 | statistic: 'avg',
|
140 | period: Duration.minutes(1),
|
141 | label: 'Lambda failure rate'
|
142 | });
|
143 | ```
|
144 |
|
145 | This function also allows changing the metric label or color (which will be
|
146 | useful when embedding them in graphs, see below).
|
147 |
|
148 | > Rates versus Sums
|
149 | >
|
150 | > The reason for using `Sum` to count discrete events is that *some* events are
|
151 | > emitted as either `0` or `1` (for example `Errors` for a Lambda) and some are
|
152 | > only emitted as `1` (for example `NumberOfMessagesPublished` for an SNS
|
153 | > topic).
|
154 | >
|
155 | > In case `0`-metrics are emitted, it makes sense to take the `Average` of this
|
156 | > metric: the result will be the fraction of errors over all executions.
|
157 | >
|
158 | > If `0`-metrics are not emitted, the `Average` will always be equal to `1`,
|
159 | > and not be very useful.
|
160 | >
|
161 | > In order to simplify the mental model of `Metric` objects, we default to
|
162 | > aggregating using `Sum`, which will be the same for both metrics types. If you
|
163 | > happen to know the Metric you want to alarm on makes sense as a rate
|
164 | > (`Average`) you can always choose to change the statistic.
|
165 |
|
166 | ### Labels
|
167 |
|
168 | Metric labels are displayed in the legend of graphs that include the metrics.
|
169 |
|
170 | You can use [dynamic labels](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/graph-dynamic-labels.html)
|
171 | to show summary information about the displayed time series
|
172 | in the legend. For example, if you use:
|
173 |
|
174 | ```ts
|
175 | declare const fn: lambda.Function;
|
176 |
|
177 | const minuteErrorRate = fn.metricErrors({
|
178 | statistic: 'sum',
|
179 | period: Duration.hours(1),
|
180 |
|
181 | // Show the maximum hourly error count in the legend
|
182 | label: '[max: ${MAX}] Lambda failure rate',
|
183 | });
|
184 | ```
|
185 |
|
186 | As the metric label, the maximum value in the visible range will
|
187 | be shown next to the time series name in the graph's legend.
|
188 |
|
189 | If the metric is a math expression producing more than one time series, the
|
190 | maximum will be individually calculated and shown for each time series produce
|
191 | by the math expression.
|
192 |
|
193 | ## Alarms
|
194 |
|
195 | Alarms can be created on metrics in one of two ways. Either create an `Alarm`
|
196 | object, passing the `Metric` object to set the alarm on:
|
197 |
|
198 | ```ts
|
199 | declare const fn: lambda.Function;
|
200 |
|
201 | new cloudwatch.Alarm(this, 'Alarm', {
|
202 | metric: fn.metricErrors(),
|
203 | threshold: 100,
|
204 | evaluationPeriods: 2,
|
205 | });
|
206 | ```
|
207 |
|
208 | Alternatively, you can call `metric.createAlarm()`:
|
209 |
|
210 | ```ts
|
211 | declare const fn: lambda.Function;
|
212 |
|
213 | fn.metricErrors().createAlarm(this, 'Alarm', {
|
214 | threshold: 100,
|
215 | evaluationPeriods: 2,
|
216 | });
|
217 | ```
|
218 |
|
219 | The most important properties to set while creating an Alarms are:
|
220 |
|
221 | - `threshold`: the value to compare the metric against.
|
222 | - `comparisonOperator`: the comparison operation to use, defaults to `metric >= threshold`.
|
223 | - `evaluationPeriods`: how many consecutive periods the metric has to be
|
224 | breaching the the threshold for the alarm to trigger.
|
225 |
|
226 | To create a cross-account alarm, make sure you have enabled [cross-account functionality](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Cross-Account-Cross-Region.html) in CloudWatch. Then, set the `account` property in the `Metric` object either manually or via the `metric.attachTo()` method.
|
227 |
|
228 | ### Alarm Actions
|
229 |
|
230 | To add actions to an alarm, use the integration classes from the
|
231 | `@aws-cdk/aws-cloudwatch-actions` package. For example, to post a message to
|
232 | an SNS topic when an alarm breaches, do the following:
|
233 |
|
234 | ```ts
|
235 | import * as cw_actions from '@aws-cdk/aws-cloudwatch-actions';
|
236 | declare const alarm: cloudwatch.Alarm;
|
237 |
|
238 | const topic = new sns.Topic(this, 'Topic');
|
239 | alarm.addAlarmAction(new cw_actions.SnsAction(topic));
|
240 | ```
|
241 |
|
242 | #### Notification formats
|
243 |
|
244 | Alarms can be created in one of two "formats":
|
245 |
|
246 | - With "top-level parameters" (these are the classic style of CloudWatch Alarms).
|
247 | - With a list of metrics specifications (these are the modern style of CloudWatch Alarms).
|
248 |
|
249 | For backwards compatibility, CDK will try to create classic, top-level CloudWatch alarms
|
250 | as much as possible, unless you are using features that cannot be expressed in that format.
|
251 | Features that require the new-style alarm format are:
|
252 |
|
253 | - Metric math
|
254 | - Cross-account metrics
|
255 | - Labels
|
256 |
|
257 | The difference between these two does not impact the functionality of the alarm
|
258 | in any way, *except* that the format of the notifications the Alarm generates is
|
259 | different between them. This affects both the notifications sent out over SNS,
|
260 | as well as the EventBridge events generated by this Alarm. If you are writing
|
261 | code to consume these notifications, be sure to handle both formats.
|
262 |
|
263 | ### Composite Alarms
|
264 |
|
265 | [Composite Alarms](https://aws.amazon.com/about-aws/whats-new/2020/03/amazon-cloudwatch-now-allows-you-to-combine-multiple-alarms/)
|
266 | can be created from existing Alarm resources.
|
267 |
|
268 | ```ts
|
269 | declare const alarm1: cloudwatch.Alarm;
|
270 | declare const alarm2: cloudwatch.Alarm;
|
271 | declare const alarm3: cloudwatch.Alarm;
|
272 | declare const alarm4: cloudwatch.Alarm;
|
273 |
|
274 | const alarmRule = cloudwatch.AlarmRule.anyOf(
|
275 | cloudwatch.AlarmRule.allOf(
|
276 | cloudwatch.AlarmRule.anyOf(
|
277 | alarm1,
|
278 | cloudwatch.AlarmRule.fromAlarm(alarm2, cloudwatch.AlarmState.OK),
|
279 | alarm3,
|
280 | ),
|
281 | cloudwatch.AlarmRule.not(cloudwatch.AlarmRule.fromAlarm(alarm4, cloudwatch.AlarmState.INSUFFICIENT_DATA)),
|
282 | ),
|
283 | cloudwatch.AlarmRule.fromBoolean(false),
|
284 | );
|
285 |
|
286 | new cloudwatch.CompositeAlarm(this, 'MyAwesomeCompositeAlarm', {
|
287 | alarmRule,
|
288 | });
|
289 | ```
|
290 |
|
291 | ### A note on units
|
292 |
|
293 | In CloudWatch, Metrics datums are emitted with units, such as `seconds` or
|
294 | `bytes`. When `Metric` objects are given a `unit` attribute, it will be used to
|
295 | *filter* the stream of metric datums for datums emitted using the same `unit`
|
296 | attribute.
|
297 |
|
298 | In particular, the `unit` field is *not* used to rescale datums or alarm threshold
|
299 | values (for example, it cannot be used to specify an alarm threshold in
|
300 | *Megabytes* if the metric stream is being emitted as *bytes*).
|
301 |
|
302 | You almost certainly don't want to specify the `unit` property when creating
|
303 | `Metric` objects (which will retrieve all datums regardless of their unit),
|
304 | unless you have very specific requirements. Note that in any case, CloudWatch
|
305 | only supports filtering by `unit` for Alarms, not in Dashboard graphs.
|
306 |
|
307 | Please see the following GitHub issue for a discussion on real unit
|
308 | calculations in CDK: https://github.com/aws/aws-cdk/issues/5595
|
309 |
|
310 | ## Dashboards
|
311 |
|
312 | Dashboards are set of Widgets stored server-side which can be accessed quickly
|
313 | from the AWS console. Available widgets are graphs of a metric over time, the
|
314 | current value of a metric, or a static piece of Markdown which explains what the
|
315 | graphs mean.
|
316 |
|
317 | The following widgets are available:
|
318 |
|
319 | - `GraphWidget` -- shows any number of metrics on both the left and right
|
320 | vertical axes.
|
321 | - `AlarmWidget` -- shows the graph and alarm line for a single alarm.
|
322 | - `SingleValueWidget` -- shows the current value of a set of metrics.
|
323 | - `TextWidget` -- shows some static Markdown.
|
324 | - `AlarmStatusWidget` -- shows the status of your alarms in a grid view.
|
325 |
|
326 | ### Graph widget
|
327 |
|
328 | A graph widget can display any number of metrics on either the `left` or
|
329 | `right` vertical axis:
|
330 |
|
331 | ```ts
|
332 | declare const dashboard: cloudwatch.Dashboard;
|
333 | declare const executionCountMetric: cloudwatch.Metric;
|
334 | declare const errorCountMetric: cloudwatch.Metric;
|
335 |
|
336 | dashboard.addWidgets(new cloudwatch.GraphWidget({
|
337 | title: "Executions vs error rate",
|
338 |
|
339 | left: [executionCountMetric],
|
340 |
|
341 | right: [errorCountMetric.with({
|
342 | statistic: "average",
|
343 | label: "Error rate",
|
344 | color: cloudwatch.Color.GREEN,
|
345 | })]
|
346 | }));
|
347 | ```
|
348 |
|
349 | Using the methods `addLeftMetric()` and `addRightMetric()` you can add metrics to a graph widget later on.
|
350 |
|
351 | Graph widgets can also display annotations attached to the left or the right y-axis.
|
352 |
|
353 | ```ts
|
354 | declare const dashboard: cloudwatch.Dashboard;
|
355 |
|
356 | dashboard.addWidgets(new cloudwatch.GraphWidget({
|
357 | // ...
|
358 |
|
359 | leftAnnotations: [
|
360 | { value: 1800, label: Duration.minutes(30).toHumanString(), color: cloudwatch.Color.RED, },
|
361 | { value: 3600, label: '1 hour', color: '#2ca02c', }
|
362 | ],
|
363 | }));
|
364 | ```
|
365 |
|
366 | The graph legend can be adjusted from the default position at bottom of the widget.
|
367 |
|
368 | ```ts
|
369 | declare const dashboard: cloudwatch.Dashboard;
|
370 |
|
371 | dashboard.addWidgets(new cloudwatch.GraphWidget({
|
372 | // ...
|
373 |
|
374 | legendPosition: cloudwatch.LegendPosition.RIGHT,
|
375 | }));
|
376 | ```
|
377 |
|
378 | The graph can publish live data within the last minute that has not been fully aggregated.
|
379 |
|
380 | ```ts
|
381 | declare const dashboard: cloudwatch.Dashboard;
|
382 |
|
383 | dashboard.addWidgets(new cloudwatch.GraphWidget({
|
384 | // ...
|
385 |
|
386 | liveData: true,
|
387 | }));
|
388 | ```
|
389 |
|
390 | The graph view can be changed from default 'timeSeries' to 'bar' or 'pie'.
|
391 |
|
392 | ```ts
|
393 | declare const dashboard: cloudwatch.Dashboard;
|
394 |
|
395 | dashboard.addWidgets(new cloudwatch.GraphWidget({
|
396 | // ...
|
397 |
|
398 | view: cloudwatch.GraphWidgetView.BAR,
|
399 | }));
|
400 | ```
|
401 |
|
402 | ### Alarm widget
|
403 |
|
404 | An alarm widget shows the graph and the alarm line of a single alarm:
|
405 |
|
406 | ```ts
|
407 | declare const dashboard: cloudwatch.Dashboard;
|
408 | declare const errorAlarm: cloudwatch.Alarm;
|
409 |
|
410 | dashboard.addWidgets(new cloudwatch.AlarmWidget({
|
411 | title: "Errors",
|
412 | alarm: errorAlarm,
|
413 | }));
|
414 | ```
|
415 |
|
416 | ### Single value widget
|
417 |
|
418 | A single-value widget shows the latest value of a set of metrics (as opposed
|
419 | to a graph of the value over time):
|
420 |
|
421 | ```ts
|
422 | declare const dashboard: cloudwatch.Dashboard;
|
423 | declare const visitorCount: cloudwatch.Metric;
|
424 | declare const purchaseCount: cloudwatch.Metric;
|
425 |
|
426 | dashboard.addWidgets(new cloudwatch.SingleValueWidget({
|
427 | metrics: [visitorCount, purchaseCount],
|
428 | }));
|
429 | ```
|
430 |
|
431 | Show as many digits as can fit, before rounding.
|
432 |
|
433 | ```ts
|
434 | declare const dashboard: cloudwatch.Dashboard;
|
435 |
|
436 | dashboard.addWidgets(new cloudwatch.SingleValueWidget({
|
437 | metrics: [ /* ... */ ],
|
438 |
|
439 | fullPrecision: true,
|
440 | }));
|
441 | ```
|
442 |
|
443 | ### Text widget
|
444 |
|
445 | A text widget shows an arbitrary piece of MarkDown. Use this to add explanations
|
446 | to your dashboard:
|
447 |
|
448 | ```ts
|
449 | declare const dashboard: cloudwatch.Dashboard;
|
450 |
|
451 | dashboard.addWidgets(new cloudwatch.TextWidget({
|
452 | markdown: '# Key Performance Indicators'
|
453 | }));
|
454 | ```
|
455 |
|
456 | ### Alarm Status widget
|
457 |
|
458 | An alarm status widget displays instantly the status of any type of alarms and gives the
|
459 | ability to aggregate one or more alarms together in a small surface.
|
460 |
|
461 | ```ts
|
462 | declare const dashboard: cloudwatch.Dashboard;
|
463 | declare const errorAlarm: cloudwatch.Alarm;
|
464 |
|
465 | dashboard.addWidgets(
|
466 | new cloudwatch.AlarmStatusWidget({
|
467 | alarms: [errorAlarm],
|
468 | })
|
469 | );
|
470 | ```
|
471 |
|
472 | An alarm status widget only showing firing alarms, sorted by state and timestamp:
|
473 |
|
474 | ```ts
|
475 | declare const dashboard: cloudwatch.Dashboard;
|
476 | declare const errorAlarm: cloudwatch.Alarm;
|
477 |
|
478 | dashboard.addWidgets(new cloudwatch.AlarmStatusWidget({
|
479 | title: "Errors",
|
480 | alarms: [errorAlarm],
|
481 | sortBy: cloudwatch.AlarmStatusWidgetSortBy.STATE_UPDATED_TIMESTAMP,
|
482 | states: [cloudwatch.AlarmState.ALARM],
|
483 | }));
|
484 | ```
|
485 |
|
486 | ### Query results widget
|
487 |
|
488 | A `LogQueryWidget` shows the results of a query from Logs Insights:
|
489 |
|
490 | ```ts
|
491 | declare const dashboard: cloudwatch.Dashboard;
|
492 |
|
493 | dashboard.addWidgets(new cloudwatch.LogQueryWidget({
|
494 | logGroupNames: ['my-log-group'],
|
495 | view: cloudwatch.LogQueryVisualizationType.TABLE,
|
496 | // The lines will be automatically combined using '\n|'.
|
497 | queryLines: [
|
498 | 'fields @message',
|
499 | 'filter @message like /Error/',
|
500 | ]
|
501 | }));
|
502 | ```
|
503 |
|
504 | ### Custom widget
|
505 |
|
506 | A `CustomWidget` shows the result of an AWS Lambda function:
|
507 |
|
508 | ```ts
|
509 | declare const dashboard: cloudwatch.Dashboard;
|
510 |
|
511 | // Import or create a lambda function
|
512 | const fn = lambda.Function.fromFunctionArn(
|
513 | dashboard,
|
514 | 'Function',
|
515 | 'arn:aws:lambda:us-east-1:123456789012:function:MyFn',
|
516 | );
|
517 |
|
518 | dashboard.addWidgets(new cloudwatch.CustomWidget({
|
519 | functionArn: fn.functionArn,
|
520 | title: 'My lambda baked widget',
|
521 | }));
|
522 | ```
|
523 |
|
524 | You can learn more about custom widgets in the [Amazon Cloudwatch User Guide](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/add_custom_widget_dashboard.html).
|
525 |
|
526 | ### Dashboard Layout
|
527 |
|
528 | The widgets on a dashboard are visually laid out in a grid that is 24 columns
|
529 | wide. Normally you specify X and Y coordinates for the widgets on a Dashboard,
|
530 | but because this is inconvenient to do manually, the library contains a simple
|
531 | layout system to help you lay out your dashboards the way you want them to.
|
532 |
|
533 | Widgets have a `width` and `height` property, and they will be automatically
|
534 | laid out either horizontally or vertically stacked to fill out the available
|
535 | space.
|
536 |
|
537 | Widgets are added to a Dashboard by calling `add(widget1, widget2, ...)`.
|
538 | Widgets given in the same call will be laid out horizontally. Widgets given
|
539 | in different calls will be laid out vertically. To make more complex layouts,
|
540 | you can use the following widgets to pack widgets together in different ways:
|
541 |
|
542 | - `Column`: stack two or more widgets vertically.
|
543 | - `Row`: lay out two or more widgets horizontally.
|
544 | - `Spacer`: take up empty space
|