Skip to content

Commit 5fcd1f1

Browse files
author
Eugene Cheung
authored
feat(cloudfront): allow disabling dashboard widgets based on additional metrics (#163)
As pointed out by a user, these metrics are not available by default, so it won't always be relevant. This is kept as enabled by default to preserve the existing behaviour. --- _By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license_
1 parent 4b8bf03 commit 5fcd1f1

File tree

6 files changed

+1512
-76
lines changed

6 files changed

+1512
-76
lines changed

API.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8125,6 +8125,7 @@ const cloudFrontDistributionMetricFactoryProps: CloudFrontDistributionMetricFact
81258125
| **Name** | **Type** | **Description** |
81268126
| --- | --- | --- |
81278127
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMetricFactoryProps.property.distribution">distribution</a></code> | <code>aws-cdk-lib.aws_cloudfront.IDistribution</code> | *No description.* |
8128+
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMetricFactoryProps.property.additionalMetricsEnabled">additionalMetricsEnabled</a></code> | <code>boolean</code> | Generate dashboard charts for additional CloudFront distribution metrics. |
81288129
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMetricFactoryProps.property.fillTpsWithZeroes">fillTpsWithZeroes</a></code> | <code>boolean</code> | *No description.* |
81298130
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMetricFactoryProps.property.rateComputationMethod">rateComputationMethod</a></code> | <code><a href="#cdk-monitoring-constructs.RateComputationMethod">RateComputationMethod</a></code> | *No description.* |
81308131

@@ -8140,6 +8141,22 @@ public readonly distribution: IDistribution;
81408141

81418142
---
81428143

8144+
##### `additionalMetricsEnabled`<sup>Optional</sup> <a name="additionalMetricsEnabled" id="cdk-monitoring-constructs.CloudFrontDistributionMetricFactoryProps.property.additionalMetricsEnabled"></a>
8145+
8146+
```typescript
8147+
public readonly additionalMetricsEnabled: boolean;
8148+
```
8149+
8150+
- *Type:* boolean
8151+
- *Default:* true
8152+
8153+
Generate dashboard charts for additional CloudFront distribution metrics.
8154+
8155+
To enable additional metrics on your CloudFront distribution, see
8156+
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/viewing-cloudfront-metrics.html#monitoring-console.distributions-additional
8157+
8158+
---
8159+
81438160
##### `fillTpsWithZeroes`<sup>Optional</sup> <a name="fillTpsWithZeroes" id="cdk-monitoring-constructs.CloudFrontDistributionMetricFactoryProps.property.fillTpsWithZeroes"></a>
81448161

81458162
```typescript
@@ -8299,6 +8316,7 @@ const cloudFrontDistributionMonitoringProps: CloudFrontDistributionMonitoringPro
82998316
| **Name** | **Type** | **Description** |
83008317
| --- | --- | --- |
83018318
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMonitoringProps.property.distribution">distribution</a></code> | <code>aws-cdk-lib.aws_cloudfront.IDistribution</code> | *No description.* |
8319+
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMonitoringProps.property.additionalMetricsEnabled">additionalMetricsEnabled</a></code> | <code>boolean</code> | Generate dashboard charts for additional CloudFront distribution metrics. |
83028320
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMonitoringProps.property.fillTpsWithZeroes">fillTpsWithZeroes</a></code> | <code>boolean</code> | *No description.* |
83038321
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMonitoringProps.property.rateComputationMethod">rateComputationMethod</a></code> | <code><a href="#cdk-monitoring-constructs.RateComputationMethod">RateComputationMethod</a></code> | *No description.* |
83048322
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMonitoringProps.property.alarmFriendlyName">alarmFriendlyName</a></code> | <code>string</code> | Plain name, used in naming alarms. |
@@ -8325,6 +8343,22 @@ public readonly distribution: IDistribution;
83258343

83268344
---
83278345

8346+
##### `additionalMetricsEnabled`<sup>Optional</sup> <a name="additionalMetricsEnabled" id="cdk-monitoring-constructs.CloudFrontDistributionMonitoringProps.property.additionalMetricsEnabled"></a>
8347+
8348+
```typescript
8349+
public readonly additionalMetricsEnabled: boolean;
8350+
```
8351+
8352+
- *Type:* boolean
8353+
- *Default:* true
8354+
8355+
Generate dashboard charts for additional CloudFront distribution metrics.
8356+
8357+
To enable additional metrics on your CloudFront distribution, see
8358+
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/viewing-cloudfront-metrics.html#monitoring-console.distributions-additional
8359+
8360+
---
8361+
83288362
##### `fillTpsWithZeroes`<sup>Optional</sup> <a name="fillTpsWithZeroes" id="cdk-monitoring-constructs.CloudFrontDistributionMonitoringProps.property.fillTpsWithZeroes"></a>
83298363

83308364
```typescript
@@ -37336,7 +37370,7 @@ new CloudFrontDistributionMetricFactory(metricFactory: MetricFactory, props: Clo
3733637370
| --- | --- |
3733737371
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMetricFactory.metric4xxErrorRateAverage">metric4xxErrorRateAverage</a></code> | *No description.* |
3733837372
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMetricFactory.metric5xxErrorRateAverage">metric5xxErrorRateAverage</a></code> | *No description.* |
37339-
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMetricFactory.metricCacheHitRateAverageInPercent">metricCacheHitRateAverageInPercent</a></code> | *No description.* |
37373+
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMetricFactory.metricCacheHitRateAverageInPercent">metricCacheHitRateAverageInPercent</a></code> | Cache hit rate metric. |
3734037374
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMetricFactory.metricRequestCount">metricRequestCount</a></code> | *No description.* |
3734137375
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMetricFactory.metricRequestRate">metricRequestRate</a></code> | *No description.* |
3734237376
| <code><a href="#cdk-monitoring-constructs.CloudFrontDistributionMetricFactory.metricRequestTps">metricRequestTps</a></code> | *No description.* |
@@ -37364,6 +37398,12 @@ public metric5xxErrorRateAverage(): Metric | MathExpression
3736437398
public metricCacheHitRateAverageInPercent(): Metric | MathExpression
3736537399
```
3736637400

37401+
Cache hit rate metric.
37402+
37403+
This is an additional metric that needs to be explicitly enabled for an additional cost.
37404+
37405+
> [https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/viewing-cloudfront-metrics.html#monitoring-console.distributions-additional](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/viewing-cloudfront-metrics.html#monitoring-console.distributions-additional)
37406+
3736737407
##### `metricRequestCount` <a name="metricRequestCount" id="cdk-monitoring-constructs.CloudFrontDistributionMetricFactory.metricRequestCount"></a>
3736837408

3736937409
```typescript

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ You can also browse the documentation at https://constructs.dev/packages/cdk-mon
6767
| Item | Monitoring | Alarms | Notes |
6868
| ---- | ---------- | ------ | ----- |
6969
| AWS API Gateway (REST API) (`.monitorApiGateway()`) | TPS, latency, errors | Latency, error count/rate | To see metrics, you have to enable Advanced Monitoring |
70-
| AWS API Gateway V2 (HTTP API) (`.monitorApiGatewayV2HttpApi()`) | TPS, latency, errors | Latency, error count/rate | To see route level metrics, you have to enable Advanced Monitoring|
70+
| AWS API Gateway V2 (HTTP API) (`.monitorApiGatewayV2HttpApi()`) | TPS, latency, errors | Latency, error count/rate | To see route level metrics, you have to enable Advanced Monitoring |
7171
| AWS AppSync (GraphQL API) (`.monitorAppSyncApi()`) | TPS, latency, errors | Latency, error count/rate, low/high TPS | |
7272
| AWS Billing (`.monitorBilling()`) | AWS account cost | | [Requires enabling](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/gs_monitor_estimated_charges_with_cloudwatch.html#gs_turning_on_billing_metrics) the **Receive Billing Alerts** option in AWS Console / Billing Preferences |
7373
| AWS Certificate Manager (`.monitorCertificate()`) | Certificate expiration | Days until expiration | |

lib/monitoring/aws-cloudfront/CloudFrontDistributionMetricFactory.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,26 @@ const CloudFrontDefaultMetricRegion = "us-east-1";
1313

1414
export interface CloudFrontDistributionMetricFactoryProps {
1515
readonly distribution: IDistribution;
16+
1617
/**
1718
* @default true
1819
*/
1920
readonly fillTpsWithZeroes?: boolean;
21+
2022
/**
2123
* @default average
2224
*/
2325
readonly rateComputationMethod?: RateComputationMethod;
26+
27+
/**
28+
* Generate dashboard charts for additional CloudFront distribution metrics.
29+
*
30+
* To enable additional metrics on your CloudFront distribution, see
31+
* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/viewing-cloudfront-metrics.html#monitoring-console.distributions-additional
32+
*
33+
* @default true
34+
*/
35+
readonly additionalMetricsEnabled?: boolean;
2436
}
2537

2638
/**
@@ -109,6 +121,11 @@ export class CloudFrontDistributionMetricFactory {
109121
.with({ region: CloudFrontDefaultMetricRegion });
110122
}
111123

124+
/**
125+
* Cache hit rate metric. This is an additional metric that needs to be explicitly enabled for an additional cost.
126+
*
127+
* @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/viewing-cloudfront-metrics.html#monitoring-console.distributions-additional
128+
*/
112129
metricCacheHitRateAverageInPercent() {
113130
return this.metricFactory
114131
.createMetric(

lib/monitoring/aws-cloudfront/CloudFrontDistributionMonitoring.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
QuarterWidth,
2323
RateAxisFromZero,
2424
SizeAxisBytesFromZero,
25+
ThirdWidth,
2526
TpsAlarmFactory,
2627
} from "../../common";
2728
import {
@@ -60,10 +61,12 @@ export class CloudFrontDistributionMonitoring extends Monitoring {
6061
protected readonly tpsMetric: MetricWithAlarmSupport;
6162
protected readonly downloadedBytesMetric: MetricWithAlarmSupport;
6263
protected readonly uploadedBytesMetric: MetricWithAlarmSupport;
63-
protected readonly cacheHitRate: MetricWithAlarmSupport;
6464
protected readonly error4xxRate: MetricWithAlarmSupport;
6565
protected readonly error5xxRate: MetricWithAlarmSupport;
6666

67+
protected readonly additionalMetricsEnabled: boolean;
68+
protected readonly cacheHitRate: MetricWithAlarmSupport | undefined;
69+
6770
constructor(
6871
scope: MonitoringScope,
6972
props: CloudFrontDistributionMonitoringProps
@@ -99,10 +102,14 @@ export class CloudFrontDistributionMonitoring extends Monitoring {
99102
this.tpsMetric = metricFactory.metricRequestTps();
100103
this.downloadedBytesMetric = metricFactory.metricTotalBytesDownloaded();
101104
this.uploadedBytesMetric = metricFactory.metricTotalBytesUploaded();
102-
this.cacheHitRate = metricFactory.metricCacheHitRateAverageInPercent();
103105
this.error4xxRate = metricFactory.metric4xxErrorRateAverage();
104106
this.error5xxRate = metricFactory.metric5xxErrorRateAverage();
105107

108+
this.additionalMetricsEnabled = props.additionalMetricsEnabled ?? true;
109+
if (this.additionalMetricsEnabled) {
110+
this.cacheHitRate = metricFactory.metricCacheHitRateAverageInPercent();
111+
}
112+
106113
for (const disambiguator in props.addLowTpsAlarm) {
107114
const alarmProps = props.addLowTpsAlarm[disambiguator];
108115
const createdAlarm = this.tpsAlarmFactory.addMinTpsAlarm(
@@ -160,13 +167,22 @@ export class CloudFrontDistributionMonitoring extends Monitoring {
160167
}
161168

162169
widgets(): IWidget[] {
163-
return [
164-
this.createTitleWidget(),
165-
this.createTpsWidget(QuarterWidth, DefaultGraphWidgetHeight),
166-
this.createCacheWidget(QuarterWidth, DefaultGraphWidgetHeight),
167-
this.createTrafficWidget(QuarterWidth, DefaultGraphWidgetHeight),
168-
this.createErrorRateWidget(QuarterWidth, DefaultGraphWidgetHeight),
169-
];
170+
if (this.additionalMetricsEnabled) {
171+
return [
172+
this.createTitleWidget(),
173+
this.createTpsWidget(QuarterWidth, DefaultGraphWidgetHeight),
174+
this.createCacheWidget(QuarterWidth, DefaultGraphWidgetHeight),
175+
this.createTrafficWidget(QuarterWidth, DefaultGraphWidgetHeight),
176+
this.createErrorRateWidget(QuarterWidth, DefaultGraphWidgetHeight),
177+
];
178+
} else {
179+
return [
180+
this.createTitleWidget(),
181+
this.createTpsWidget(ThirdWidth, DefaultGraphWidgetHeight),
182+
this.createTrafficWidget(ThirdWidth, DefaultGraphWidgetHeight),
183+
this.createErrorRateWidget(ThirdWidth, DefaultGraphWidgetHeight),
184+
];
185+
}
170186
}
171187

172188
protected createTitleWidget() {
@@ -193,7 +209,8 @@ export class CloudFrontDistributionMonitoring extends Monitoring {
193209
width,
194210
height,
195211
title: "Hit Rate",
196-
left: [this.cacheHitRate],
212+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
213+
left: [this.cacheHitRate!],
197214
leftYAxis: PercentageAxisFromZeroToHundred,
198215
});
199216
}

test/monitoring/aws-cloudfront/CloudFrontDistribution.test.ts

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -11,68 +11,72 @@ import {
1111
import { addMonitoringDashboardsToStack } from "../../utils/SnapshotUtil";
1212
import { TestMonitoringScope } from "../TestMonitoringScope";
1313

14-
test("snapshot test: no alarms", () => {
15-
const stack = new Stack();
16-
const bucket = new Bucket(stack, "Bucket");
17-
const distribution = new Distribution(stack, "Distribution", {
18-
defaultBehavior: {
19-
origin: new S3Origin(bucket),
20-
},
21-
});
14+
[undefined, true, false].forEach((additionalMetricsEnabled) => {
15+
test(`snapshot test: no alarms with additionalMetricsEnabled=${additionalMetricsEnabled}`, () => {
16+
const stack = new Stack();
17+
const bucket = new Bucket(stack, "Bucket");
18+
const distribution = new Distribution(stack, "Distribution", {
19+
defaultBehavior: {
20+
origin: new S3Origin(bucket),
21+
},
22+
});
2223

23-
const scope = new TestMonitoringScope(stack, "Scope");
24+
const scope = new TestMonitoringScope(stack, "Scope");
2425

25-
const monitoring = new CloudFrontDistributionMonitoring(scope, {
26-
distribution,
27-
});
28-
29-
addMonitoringDashboardsToStack(stack, monitoring);
30-
expect(Template.fromStack(stack)).toMatchSnapshot();
31-
});
26+
const monitoring = new CloudFrontDistributionMonitoring(scope, {
27+
distribution,
28+
additionalMetricsEnabled,
29+
});
3230

33-
test("snapshot test: all alarms", () => {
34-
const stack = new Stack();
35-
const bucket = new Bucket(stack, "Bucket");
36-
const distribution = new Distribution(stack, "Distribution", {
37-
defaultBehavior: {
38-
origin: new S3Origin(bucket),
39-
},
31+
addMonitoringDashboardsToStack(stack, monitoring);
32+
expect(Template.fromStack(stack)).toMatchSnapshot();
4033
});
4134

42-
const scope = new TestMonitoringScope(stack, "Scope");
35+
test(`snapshot test: all alarms with additionalMetricsEnabled=${additionalMetricsEnabled}`, () => {
36+
const stack = new Stack();
37+
const bucket = new Bucket(stack, "Bucket");
38+
const distribution = new Distribution(stack, "Distribution", {
39+
defaultBehavior: {
40+
origin: new S3Origin(bucket),
41+
},
42+
});
43+
44+
const scope = new TestMonitoringScope(stack, "Scope");
4345

44-
let numAlarmsCreated = 0;
46+
let numAlarmsCreated = 0;
4547

46-
const monitoring = new CloudFrontDistributionMonitoring(scope, {
47-
distribution,
48-
addLowTpsAlarm: {
49-
Warning: {
50-
minTps: 10,
48+
const monitoring = new CloudFrontDistributionMonitoring(scope, {
49+
distribution,
50+
additionalMetricsEnabled,
51+
addLowTpsAlarm: {
52+
Warning: {
53+
minTps: 10,
54+
},
5155
},
52-
},
53-
addHighTpsAlarm: {
54-
Warning: {
55-
maxTps: 20,
56+
addHighTpsAlarm: {
57+
Warning: {
58+
maxTps: 20,
59+
},
5660
},
57-
},
58-
addError4xxRate: {
59-
Warning: {
60-
maxErrorRate: 0.5,
61+
addError4xxRate: {
62+
Warning: {
63+
maxErrorRate: 0.5,
64+
},
6165
},
62-
},
63-
addFault5xxRate: {
64-
Warning: {
65-
maxErrorRate: 0.8,
66+
addFault5xxRate: {
67+
Warning: {
68+
maxErrorRate: 0.8,
69+
},
6670
},
67-
},
68-
useCreatedAlarms: {
69-
consume(alarms: AlarmWithAnnotation[]) {
70-
numAlarmsCreated = alarms.length;
71+
useCreatedAlarms: {
72+
consume(alarms: AlarmWithAnnotation[]) {
73+
numAlarmsCreated = alarms.length;
74+
},
7175
},
72-
},
73-
});
76+
});
7477

75-
addMonitoringDashboardsToStack(stack, monitoring);
76-
expect(numAlarmsCreated).toStrictEqual(4);
77-
expect(Template.fromStack(stack)).toMatchSnapshot();
78+
addMonitoringDashboardsToStack(stack, monitoring);
79+
expect(numAlarmsCreated).toStrictEqual(4);
80+
expect(Template.fromStack(stack)).toMatchSnapshot();
81+
});
7882
});

0 commit comments

Comments
 (0)