@composurecdk/cloudfront 0.4.3 → 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +53 -0
  2. package/dist/alarm-config.d.ts +56 -3
  3. package/dist/alarm-config.d.ts.map +1 -1
  4. package/dist/alarm-defaults.d.ts +14 -0
  5. package/dist/alarm-defaults.d.ts.map +1 -1
  6. package/dist/alarm-defaults.js +31 -0
  7. package/dist/alarm-defaults.js.map +1 -1
  8. package/dist/behavior-function-alarms.d.ts +44 -0
  9. package/dist/behavior-function-alarms.d.ts.map +1 -0
  10. package/dist/behavior-function-alarms.js +136 -0
  11. package/dist/behavior-function-alarms.js.map +1 -0
  12. package/dist/cloudfront-alarm-builder.d.ts +133 -0
  13. package/dist/cloudfront-alarm-builder.d.ts.map +1 -0
  14. package/dist/cloudfront-alarm-builder.js +131 -0
  15. package/dist/cloudfront-alarm-builder.js.map +1 -0
  16. package/dist/defaults.d.ts +6 -1
  17. package/dist/defaults.d.ts.map +1 -1
  18. package/dist/defaults.js +13 -1
  19. package/dist/defaults.js.map +1 -1
  20. package/dist/distribution-alarms.d.ts +0 -17
  21. package/dist/distribution-alarms.d.ts.map +1 -1
  22. package/dist/distribution-alarms.js +1 -24
  23. package/dist/distribution-alarms.js.map +1 -1
  24. package/dist/distribution-builder.d.ts +224 -62
  25. package/dist/distribution-builder.d.ts.map +1 -1
  26. package/dist/distribution-builder.js +61 -21
  27. package/dist/distribution-builder.js.map +1 -1
  28. package/dist/index.d.ts +5 -4
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +3 -2
  31. package/dist/index.js.map +1 -1
  32. package/dist/resolve-behaviors.d.ts +56 -0
  33. package/dist/resolve-behaviors.d.ts.map +1 -0
  34. package/dist/resolve-behaviors.js +98 -0
  35. package/dist/resolve-behaviors.js.map +1 -0
  36. package/package.json +1 -1
package/README.md CHANGED
@@ -177,6 +177,59 @@ for (const alarm of Object.values(result.alarms)) {
177
177
  }
178
178
  ```
179
179
 
180
+ ## Cross-region alarm builder
181
+
182
+ CloudFront emits all metrics to `us-east-1` only. CloudWatch alarms are regional, so alarms created in any other region never fire — they exist but receive no data. When the distribution lives in a stack outside `us-east-1`, use `createCloudFrontAlarmBuilder` to put the alarms in a separate `us-east-1` stack.
183
+
184
+ The standalone builder reads the distribution's result (including the inline-function entries) and produces the same alarm surface — distribution-level recommended alarms, per-function recommended alarms, and any custom `addAlarm` alarms.
185
+
186
+ ```ts
187
+ import { compose, ref } from "@composurecdk/core";
188
+ import {
189
+ createDistributionBuilder,
190
+ createCloudFrontAlarmBuilder,
191
+ type DistributionBuilderResult,
192
+ } from "@composurecdk/cloudfront";
193
+
194
+ compose(
195
+ {
196
+ cdn: createDistributionBuilder()
197
+ .origin(siteOrigin)
198
+ .defaultBehavior({
199
+ functions: [{ eventType: FunctionEventType.VIEWER_REQUEST, code }],
200
+ })
201
+ .recommendedAlarms(false), // suppress all alarms in the dist's own stack
202
+
203
+ cdnAlarms: createCloudFrontAlarmBuilder()
204
+ .distribution(ref<DistributionBuilderResult>("cdn"))
205
+ .recommendedAlarms({ errorRate: { threshold: 2 } })
206
+ .addAlarm("custom4xx", (a) =>
207
+ a
208
+ .metric(
209
+ () =>
210
+ new Metric({
211
+ namespace: "AWS/CloudFront",
212
+ metricName: "4xxErrorRate",
213
+ statistic: "Average",
214
+ }),
215
+ )
216
+ .threshold(5)
217
+ .greaterThan(),
218
+ ),
219
+ },
220
+ { cdn: [], cdnAlarms: ["cdn"] },
221
+ )
222
+ .withStacks({
223
+ cdn: siteStack, // e.g. eu-west-2
224
+ cdnAlarms: usEast1Stack, // typically your existing certStack
225
+ })
226
+ .build(app, "App");
227
+ ```
228
+
229
+ Set `crossRegionReferences: true` on both stacks so CDK can export `DistributionId` from the site stack and import it in the alarm stack.
230
+
231
+ `recommendedAlarms: false` on `createDistributionBuilder` is the master kill switch for both distribution-level and per-function recommended alarms. Custom alarms added via `addAlarm` are unaffected — call `.addAlarm()` on the standalone alarm builder if you want those to live in the us-east-1 stack too.
232
+
180
233
  ## Examples
181
234
 
182
235
  - [StaticWebsiteStack](../examples/src/static-website/app.ts) — S3 + CloudFront static website with OAC, error pages, and content deployment
@@ -5,9 +5,8 @@ import type { AlarmConfig } from "@composurecdk/cloudwatch";
5
5
  * Set individual alarms to `false` to disable them, or provide an
6
6
  * {@link AlarmConfig} to tune thresholds.
7
7
  *
8
- * Function-level alarms (FunctionValidationErrors, FunctionExecutionErrors,
9
- * FunctionThrottles) require per-function dimensions and are not created
10
- * automatically. Use {@link IDistributionBuilder.addAlarm} to add them.
8
+ * Function-level alarms are created automatically for every inline function
9
+ * declared on a behavior see {@link FunctionAlarmConfig} to tune them.
11
10
  *
12
11
  * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#CloudFront
13
12
  */
@@ -42,4 +41,58 @@ export interface DistributionAlarmConfig {
42
41
  */
43
42
  originLatency?: AlarmConfig | false;
44
43
  }
44
+ /**
45
+ * Controls which recommended alarms are created for a CloudFront Function
46
+ * declared inline on a cache behavior. All alarms are enabled by default
47
+ * with AWS-recommended thresholds. Set individual alarms to `false` to
48
+ * disable them, or provide an {@link AlarmConfig} to tune thresholds.
49
+ *
50
+ * CloudFront Function metrics are emitted in the `us-east-1` region only
51
+ * (CloudFront is a global service). The alarms live in the stack's region —
52
+ * if that is not `us-east-1`, the alarms will not receive data.
53
+ *
54
+ * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/monitoring-functions.html
55
+ */
56
+ export interface FunctionAlarmConfig {
57
+ /**
58
+ * Per-function switch: set to `false` to disable all recommended alarms
59
+ * for this one function. Individual alarms can also be disabled via their
60
+ * own entry. The global kill switch is
61
+ * {@link DistributionBuilderProps.recommendedAlarms} `: false` on the
62
+ * surrounding distribution builder, which suppresses every recommended
63
+ * alarm regardless of per-function settings.
64
+ * @default true
65
+ */
66
+ enabled?: boolean;
67
+ /**
68
+ * Alarm when the function raises runtime exceptions while processing a
69
+ * viewer request or response.
70
+ *
71
+ * Metric: `AWS/CloudFront FunctionExecutionErrors`, statistic Sum,
72
+ * period 1 minute. Default threshold: > 0 errors.
73
+ *
74
+ * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/monitoring-functions.html
75
+ */
76
+ executionErrors?: AlarmConfig | false;
77
+ /**
78
+ * Alarm when the function returns an event object that fails validation
79
+ * (e.g. malformed headers, unsupported response shape).
80
+ *
81
+ * Metric: `AWS/CloudFront FunctionValidationErrors`, statistic Sum,
82
+ * period 1 minute. Default threshold: > 0 errors.
83
+ *
84
+ * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/monitoring-functions.html
85
+ */
86
+ validationErrors?: AlarmConfig | false;
87
+ /**
88
+ * Alarm when the function is throttled — typically because it exceeded
89
+ * the 1ms compute-utilization budget.
90
+ *
91
+ * Metric: `AWS/CloudFront FunctionThrottles`, statistic Sum,
92
+ * period 1 minute. Default threshold: > 0 throttles.
93
+ *
94
+ * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-function-restrictions.html
95
+ */
96
+ throttles?: AlarmConfig | false;
97
+ }
45
98
  //# sourceMappingURL=alarm-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"alarm-config.d.ts","sourceRoot":"","sources":["../src/alarm-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAEhC;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;CACrC"}
1
+ {"version":3,"file":"alarm-config.d.ts","sourceRoot":"","sources":["../src/alarm-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;;;;;;;GAUG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAEhC;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;CACrC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAEtC;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAEvC;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;CACjC"}
@@ -4,11 +4,25 @@ interface DistributionAlarmDefaults {
4
4
  errorRate: Required<AlarmConfig>;
5
5
  originLatency: Required<AlarmConfig>;
6
6
  }
7
+ interface FunctionAlarmDefaults {
8
+ enabled: true;
9
+ executionErrors: Required<AlarmConfig>;
10
+ validationErrors: Required<AlarmConfig>;
11
+ throttles: Required<AlarmConfig>;
12
+ }
7
13
  /**
8
14
  * AWS-recommended default alarm configuration for CloudFront distributions.
9
15
  *
10
16
  * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#CloudFront
11
17
  */
12
18
  export declare const DISTRIBUTION_ALARM_DEFAULTS: DistributionAlarmDefaults;
19
+ /**
20
+ * Default alarm configuration for CloudFront Functions declared inline on
21
+ * a cache behavior. Any non-zero count of errors or throttles is worth
22
+ * investigating since a function executes on every viewer request/response.
23
+ *
24
+ * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/monitoring-functions.html
25
+ */
26
+ export declare const FUNCTION_ALARM_DEFAULTS: FunctionAlarmDefaults;
13
27
  export {};
14
28
  //# sourceMappingURL=alarm-defaults.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"alarm-defaults.d.ts","sourceRoot":"","sources":["../src/alarm-defaults.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,UAAU,yBAAyB;IACjC,OAAO,EAAE,IAAI,CAAC;IACd,SAAS,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IACjC,aAAa,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;CACtC;AAED;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,EAAE,yBAyBzC,CAAC"}
1
+ {"version":3,"file":"alarm-defaults.d.ts","sourceRoot":"","sources":["../src/alarm-defaults.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,UAAU,yBAAyB;IACjC,OAAO,EAAE,IAAI,CAAC;IACd,SAAS,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IACjC,aAAa,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;CACtC;AAED,UAAU,qBAAqB;IAC7B,OAAO,EAAE,IAAI,CAAC;IACd,eAAe,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IACvC,gBAAgB,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IACxC,SAAS,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;CAClC;AAED;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,EAAE,yBAyBzC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,EAAE,qBA0BrC,CAAC"}
@@ -28,4 +28,35 @@ export const DISTRIBUTION_ALARM_DEFAULTS = {
28
28
  treatMissingData: TreatMissingData.NOT_BREACHING,
29
29
  },
30
30
  };
31
+ /**
32
+ * Default alarm configuration for CloudFront Functions declared inline on
33
+ * a cache behavior. Any non-zero count of errors or throttles is worth
34
+ * investigating since a function executes on every viewer request/response.
35
+ *
36
+ * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/monitoring-functions.html
37
+ */
38
+ export const FUNCTION_ALARM_DEFAULTS = {
39
+ enabled: true,
40
+ /** Any execution error indicates a runtime fault on the edge; threshold 0. */
41
+ executionErrors: {
42
+ threshold: 0,
43
+ evaluationPeriods: 1,
44
+ datapointsToAlarm: 1,
45
+ treatMissingData: TreatMissingData.NOT_BREACHING,
46
+ },
47
+ /** Any validation error indicates the function returned a bad event; threshold 0. */
48
+ validationErrors: {
49
+ threshold: 0,
50
+ evaluationPeriods: 1,
51
+ datapointsToAlarm: 1,
52
+ treatMissingData: TreatMissingData.NOT_BREACHING,
53
+ },
54
+ /** Any throttle indicates the function exceeded its 1ms compute budget; threshold 0. */
55
+ throttles: {
56
+ threshold: 0,
57
+ evaluationPeriods: 1,
58
+ datapointsToAlarm: 1,
59
+ treatMissingData: TreatMissingData.NOT_BREACHING,
60
+ },
61
+ };
31
62
  //# sourceMappingURL=alarm-defaults.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"alarm-defaults.js","sourceRoot":"","sources":["../src/alarm-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAS9D;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAA8B;IACpE,OAAO,EAAE,IAAI;IAEb;;;OAGG;IACH,SAAS,EAAE;QACT,SAAS,EAAE,CAAC;QACZ,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;IAED;;;;OAIG;IACH,aAAa,EAAE;QACb,SAAS,EAAE,IAAI;QACf,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;CACF,CAAC"}
1
+ {"version":3,"file":"alarm-defaults.js","sourceRoot":"","sources":["../src/alarm-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAgB9D;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAA8B;IACpE,OAAO,EAAE,IAAI;IAEb;;;OAGG;IACH,SAAS,EAAE;QACT,SAAS,EAAE,CAAC;QACZ,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;IAED;;;;OAIG;IACH,aAAa,EAAE;QACb,SAAS,EAAE,IAAI;QACf,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;CACF,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAA0B;IAC5D,OAAO,EAAE,IAAI;IAEb,8EAA8E;IAC9E,eAAe,EAAE;QACf,SAAS,EAAE,CAAC;QACZ,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;IAED,qFAAqF;IACrF,gBAAgB,EAAE;QAChB,SAAS,EAAE,CAAC;QACZ,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;IAED,wFAAwF;IACxF,SAAS,EAAE;QACT,SAAS,EAAE,CAAC;QACZ,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;CACF,CAAC"}
@@ -0,0 +1,44 @@
1
+ import type { Function as CfFunction, FunctionEventType } from "aws-cdk-lib/aws-cloudfront";
2
+ import type { AlarmDefinition } from "@composurecdk/cloudwatch";
3
+ import type { FunctionAlarmConfig } from "./alarm-config.js";
4
+ /**
5
+ * Converts a CloudFront cache-behavior path pattern into a PascalCase slug
6
+ * suitable for alarm keys and CDK construct ids. A single leading `/` is
7
+ * dropped (the common case), interior `/` becomes `Slash` so sibling patterns
8
+ * don't collide, `*` becomes `Star`, and `?` becomes `Q`. Other
9
+ * non-alphanumeric characters are stripped.
10
+ *
11
+ * Examples:
12
+ * - `/api/*` → `ApiSlashStar`
13
+ * - `/api*` → `ApiStar` (distinct from `/api/*`)
14
+ * - `*.html` → `StarHtml`
15
+ * - `images/*` → `ImagesSlashStar`
16
+ *
17
+ * @internal
18
+ */
19
+ export declare function pathPatternSlug(pattern: string): string;
20
+ /**
21
+ * Converts a {@link FunctionEventType} value (e.g. `"viewer-request"`) into
22
+ * PascalCase (e.g. `"ViewerRequest"`) for use in alarm keys and construct ids.
23
+ *
24
+ * @internal
25
+ */
26
+ export declare function eventTypePascal(eventType: FunctionEventType): string;
27
+ /**
28
+ * Builds the prefix used for every alarm key produced for a given inline
29
+ * function — e.g. `defaultBehaviorViewerRequest` or `behaviorApiStarViewerRequest`.
30
+ * Pass `null` for the default behavior.
31
+ *
32
+ * @internal
33
+ */
34
+ export declare function behaviorFunctionKeyPrefix(pathPattern: string | null, eventType: FunctionEventType): string;
35
+ /**
36
+ * Produces fully-resolved {@link AlarmDefinition}s for the three AWS-recommended
37
+ * CloudFront Function alarms — execution errors, validation errors, throttles —
38
+ * scoped to a single behavior + event type so the keys and descriptions stay
39
+ * actionable when the same underlying function is used on multiple behaviors.
40
+ *
41
+ * @internal
42
+ */
43
+ export declare function resolveBehaviorFunctionAlarmDefinitions(pathPattern: string | null, eventType: FunctionEventType, fn: CfFunction, config: FunctionAlarmConfig | false | undefined): AlarmDefinition[];
44
+ //# sourceMappingURL=behavior-function-alarms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavior-function-alarms.d.ts","sourceRoot":"","sources":["../src/behavior-function-alarms.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,IAAI,UAAU,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC5F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AA0B7D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUvD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,iBAAiB,GAAG,MAAM,CAKpE;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,SAAS,EAAE,iBAAiB,GAC3B,MAAM,CAIR;AAUD;;;;;;;GAOG;AACH,wBAAgB,uCAAuC,CACrD,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,SAAS,EAAE,iBAAiB,EAC5B,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,mBAAmB,GAAG,KAAK,GAAG,SAAS,GAC9C,eAAe,EAAE,CAyDnB"}
@@ -0,0 +1,136 @@
1
+ import { Duration } from "aws-cdk-lib";
2
+ import { ComparisonOperator, Metric, Stats } from "aws-cdk-lib/aws-cloudwatch";
3
+ import { resolveAlarmConfig } from "@composurecdk/cloudwatch";
4
+ import { FUNCTION_ALARM_DEFAULTS } from "./alarm-defaults.js";
5
+ const METRIC_PERIOD = Duration.minutes(1);
6
+ const METRIC_PERIOD_LABEL = `${String(METRIC_PERIOD.toMinutes())} minute`;
7
+ /**
8
+ * CloudFront Function metrics are emitted in the `us-east-1` region only
9
+ * (CloudFront is a global service). Metric dimensions are
10
+ * `FunctionName` + `Region=Global`.
11
+ *
12
+ * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/monitoring-functions.html
13
+ */
14
+ function functionMetric(fn, metricName) {
15
+ return new Metric({
16
+ namespace: "AWS/CloudFront",
17
+ metricName,
18
+ dimensionsMap: {
19
+ FunctionName: fn.functionName,
20
+ Region: "Global",
21
+ },
22
+ statistic: Stats.SUM,
23
+ period: METRIC_PERIOD,
24
+ });
25
+ }
26
+ /**
27
+ * Converts a CloudFront cache-behavior path pattern into a PascalCase slug
28
+ * suitable for alarm keys and CDK construct ids. A single leading `/` is
29
+ * dropped (the common case), interior `/` becomes `Slash` so sibling patterns
30
+ * don't collide, `*` becomes `Star`, and `?` becomes `Q`. Other
31
+ * non-alphanumeric characters are stripped.
32
+ *
33
+ * Examples:
34
+ * - `/api/*` → `ApiSlashStar`
35
+ * - `/api*` → `ApiStar` (distinct from `/api/*`)
36
+ * - `*.html` → `StarHtml`
37
+ * - `images/*` → `ImagesSlashStar`
38
+ *
39
+ * @internal
40
+ */
41
+ export function pathPatternSlug(pattern) {
42
+ const stripped = pattern.startsWith("/") ? pattern.slice(1) : pattern;
43
+ return stripped
44
+ .replace(/\//g, " Slash ")
45
+ .replace(/\*/g, " Star ")
46
+ .replace(/\?/g, " Q ")
47
+ .split(/[^A-Za-z0-9]+/)
48
+ .filter(Boolean)
49
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
50
+ .join("");
51
+ }
52
+ /**
53
+ * Converts a {@link FunctionEventType} value (e.g. `"viewer-request"`) into
54
+ * PascalCase (e.g. `"ViewerRequest"`) for use in alarm keys and construct ids.
55
+ *
56
+ * @internal
57
+ */
58
+ export function eventTypePascal(eventType) {
59
+ return eventType
60
+ .split("-")
61
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
62
+ .join("");
63
+ }
64
+ /**
65
+ * Builds the prefix used for every alarm key produced for a given inline
66
+ * function — e.g. `defaultBehaviorViewerRequest` or `behaviorApiStarViewerRequest`.
67
+ * Pass `null` for the default behavior.
68
+ *
69
+ * @internal
70
+ */
71
+ export function behaviorFunctionKeyPrefix(pathPattern, eventType) {
72
+ const scope = pathPattern === null ? "defaultBehavior" : `behavior${pathPatternSlug(pathPattern)}`;
73
+ return `${scope}${eventTypePascal(eventType)}`;
74
+ }
75
+ function behaviorFunctionScopeLabel(pathPattern, eventType) {
76
+ const scope = pathPattern === null ? "default behavior" : `behavior "${pathPattern}"`;
77
+ return `${scope} (${eventType})`;
78
+ }
79
+ /**
80
+ * Produces fully-resolved {@link AlarmDefinition}s for the three AWS-recommended
81
+ * CloudFront Function alarms — execution errors, validation errors, throttles —
82
+ * scoped to a single behavior + event type so the keys and descriptions stay
83
+ * actionable when the same underlying function is used on multiple behaviors.
84
+ *
85
+ * @internal
86
+ */
87
+ export function resolveBehaviorFunctionAlarmDefinitions(pathPattern, eventType, fn, config) {
88
+ if (config === false)
89
+ return [];
90
+ if (config?.enabled === false)
91
+ return [];
92
+ const keyPrefix = behaviorFunctionKeyPrefix(pathPattern, eventType);
93
+ const scopeLabel = behaviorFunctionScopeLabel(pathPattern, eventType);
94
+ const definitions = [];
95
+ if (config?.executionErrors !== false) {
96
+ const cfg = resolveAlarmConfig(config?.executionErrors, FUNCTION_ALARM_DEFAULTS.executionErrors);
97
+ definitions.push({
98
+ key: `${keyPrefix}ExecutionErrors`,
99
+ metric: functionMetric(fn, "FunctionExecutionErrors"),
100
+ threshold: cfg.threshold,
101
+ comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
102
+ evaluationPeriods: cfg.evaluationPeriods,
103
+ datapointsToAlarm: cfg.datapointsToAlarm,
104
+ treatMissingData: cfg.treatMissingData,
105
+ description: `CloudFront Function on ${scopeLabel} is raising execution errors. Threshold: > ${String(cfg.threshold)} errors in ${METRIC_PERIOD_LABEL}.`,
106
+ });
107
+ }
108
+ if (config?.validationErrors !== false) {
109
+ const cfg = resolveAlarmConfig(config?.validationErrors, FUNCTION_ALARM_DEFAULTS.validationErrors);
110
+ definitions.push({
111
+ key: `${keyPrefix}ValidationErrors`,
112
+ metric: functionMetric(fn, "FunctionValidationErrors"),
113
+ threshold: cfg.threshold,
114
+ comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
115
+ evaluationPeriods: cfg.evaluationPeriods,
116
+ datapointsToAlarm: cfg.datapointsToAlarm,
117
+ treatMissingData: cfg.treatMissingData,
118
+ description: `CloudFront Function on ${scopeLabel} is producing validation errors. Threshold: > ${String(cfg.threshold)} errors in ${METRIC_PERIOD_LABEL}.`,
119
+ });
120
+ }
121
+ if (config?.throttles !== false) {
122
+ const cfg = resolveAlarmConfig(config?.throttles, FUNCTION_ALARM_DEFAULTS.throttles);
123
+ definitions.push({
124
+ key: `${keyPrefix}Throttles`,
125
+ metric: functionMetric(fn, "FunctionThrottles"),
126
+ threshold: cfg.threshold,
127
+ comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
128
+ evaluationPeriods: cfg.evaluationPeriods,
129
+ datapointsToAlarm: cfg.datapointsToAlarm,
130
+ treatMissingData: cfg.treatMissingData,
131
+ description: `CloudFront Function on ${scopeLabel} is being throttled — likely exceeding its 1ms compute budget. Threshold: > ${String(cfg.threshold)} throttles in ${METRIC_PERIOD_LABEL}.`,
132
+ });
133
+ }
134
+ return definitions;
135
+ }
136
+ //# sourceMappingURL=behavior-function-alarms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavior-function-alarms.js","sourceRoot":"","sources":["../src/behavior-function-alarms.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,133 @@
1
+ import { type Distribution } from "aws-cdk-lib/aws-cloudfront";
2
+ import { type Alarm } from "aws-cdk-lib/aws-cloudwatch";
3
+ import { type IConstruct } from "constructs";
4
+ import { type IBuilder, type Lifecycle, type Resolvable } from "@composurecdk/core";
5
+ import { AlarmDefinitionBuilder } from "@composurecdk/cloudwatch";
6
+ import type { DistributionAlarmConfig } from "./alarm-config.js";
7
+ import type { DistributionBuilderResult } from "./distribution-builder.js";
8
+ /**
9
+ * Configuration properties for {@link createCloudFrontAlarmBuilder}.
10
+ *
11
+ * The standalone alarm builder mirrors the alarm surface that
12
+ * {@link createDistributionBuilder} creates by default. It exists so that
13
+ * alarms can be created in a different stack from the distribution itself —
14
+ * specifically a `us-east-1` stack, since CloudFront emits all metrics there
15
+ * regardless of the distribution's stack region.
16
+ */
17
+ export interface CloudFrontAlarmBuilderProps {
18
+ /**
19
+ * Configuration for AWS-recommended CloudWatch alarms — distribution-level
20
+ * (5xx error rate, origin latency) and per-function (execution errors,
21
+ * validation errors, throttles).
22
+ *
23
+ * Mirrors {@link DistributionBuilderProps.recommendedAlarms}. Set to
24
+ * `false` to disable all recommended alarms; per-function alarms further
25
+ * respect each function's own {@link InlineFunctionDefinition.recommendedAlarms}
26
+ * value. Custom alarms added via {@link ICloudFrontAlarmBuilder.addAlarm}
27
+ * are unaffected.
28
+ *
29
+ * No alarm actions are configured by default. Use `alarmActionsPolicy` (or
30
+ * an `afterBuild` hook) to wire SNS or other actions onto the resulting
31
+ * alarms.
32
+ *
33
+ * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#CloudFront
34
+ */
35
+ recommendedAlarms?: DistributionAlarmConfig | false;
36
+ }
37
+ /**
38
+ * The build output of an {@link ICloudFrontAlarmBuilder}.
39
+ */
40
+ export interface CloudFrontAlarmBuilderResult {
41
+ /**
42
+ * The CloudWatch alarms created by this builder, keyed by alarm name. Uses
43
+ * the same key scheme as {@link DistributionBuilderResult.alarms}.
44
+ */
45
+ alarms: Record<string, Alarm>;
46
+ }
47
+ /**
48
+ * A fluent builder for CloudFront-related CloudWatch alarms, decoupled from
49
+ * the distribution itself. Use this when the distribution lives in a stack
50
+ * outside `us-east-1` — route this builder's component into a us-east-1
51
+ * stack via `compose().withStacks()` so the alarms land where CloudFront
52
+ * actually emits metrics.
53
+ *
54
+ * @see {@link createCloudFrontAlarmBuilder}
55
+ */
56
+ export type ICloudFrontAlarmBuilder = IBuilder<CloudFrontAlarmBuilderProps, CloudFrontAlarmBuilder>;
57
+ /**
58
+ * Shared alarm-assembly used by both {@link createDistributionBuilder} (in its
59
+ * own stack) and {@link createCloudFrontAlarmBuilder} (typically in a separate
60
+ * `us-east-1` stack). Materializes the recommended distribution-level alarms,
61
+ * the recommended per-function alarms, and any user-supplied custom alarms,
62
+ * emits the region warning if the resulting scope is not in `us-east-1`, and
63
+ * creates the alarm constructs.
64
+ *
65
+ * @internal
66
+ */
67
+ export declare function buildCloudFrontAlarms(scope: IConstruct, id: string, target: Pick<DistributionBuilderResult, "distribution" | "functions">, options?: {
68
+ recommendedAlarms?: DistributionAlarmConfig | false;
69
+ customAlarms?: AlarmDefinitionBuilder<Distribution>[];
70
+ }): Record<string, Alarm>;
71
+ declare class CloudFrontAlarmBuilder implements Lifecycle<CloudFrontAlarmBuilderResult> {
72
+ #private;
73
+ props: Partial<CloudFrontAlarmBuilderProps>;
74
+ /**
75
+ * Sets the distribution to alarm on. Pass the result of
76
+ * {@link createDistributionBuilder} (or a {@link Ref} to it). The builder
77
+ * reads the distribution and any inline-function metadata from the result.
78
+ *
79
+ * Pair with `compose().withStacks()` to route this component into a
80
+ * `us-east-1` stack while the distribution itself lives elsewhere — set
81
+ * `crossRegionReferences: true` on both stacks so CDK can wire the
82
+ * `DistributionId` reference automatically.
83
+ */
84
+ distribution(distribution: Resolvable<DistributionBuilderResult>): this;
85
+ /**
86
+ * Adds a custom alarm against the distribution. The configure callback
87
+ * receives a fresh {@link AlarmDefinitionBuilder} pre-set with the alarm's
88
+ * key; configure metric, threshold, comparison and any other options.
89
+ *
90
+ * The created alarm is materialized in this builder's stack — useful for
91
+ * cross-region setups where you want all CloudFront alarms to live with the
92
+ * recommended ones.
93
+ */
94
+ addAlarm(key: string, configure: (alarm: AlarmDefinitionBuilder<Distribution>) => AlarmDefinitionBuilder<Distribution>): this;
95
+ build(scope: IConstruct, id: string, context?: Record<string, object>): CloudFrontAlarmBuilderResult;
96
+ }
97
+ /**
98
+ * Creates a new {@link ICloudFrontAlarmBuilder} for materializing CloudFront
99
+ * alarms in a stack separate from the distribution itself.
100
+ *
101
+ * The recommended use is multi-region deployments: the distribution lives in
102
+ * the site's stack (often outside `us-east-1` for latency or compliance
103
+ * reasons), and CloudFront alarms must live in a `us-east-1` stack so they
104
+ * can read the metrics CloudFront emits there.
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * compose(
109
+ * {
110
+ * cdn: createDistributionBuilder()
111
+ * .origin(...)
112
+ * .defaultBehavior({ functions: [{ eventType, code }] })
113
+ * .recommendedAlarms(false), // suppress alarms in the dist's own stack
114
+ *
115
+ * cdnAlarms: createCloudFrontAlarmBuilder()
116
+ * .distribution(ref<DistributionBuilderResult>("cdn"))
117
+ * .recommendedAlarms({ errorRate: { threshold: 2 } }),
118
+ * },
119
+ * { cdn: [], cdnAlarms: ["cdn"] },
120
+ * )
121
+ * .withStacks({
122
+ * cdn: siteStack, // eu-west-2
123
+ * cdnAlarms: certStack, // us-east-1 (existing ACM stack)
124
+ * })
125
+ * .build(app, "App");
126
+ * ```
127
+ *
128
+ * Set `crossRegionReferences: true` on both stacks so CDK can export the
129
+ * `DistributionId` from the site stack and import it in the alarm stack.
130
+ */
131
+ export declare function createCloudFrontAlarmBuilder(): ICloudFrontAlarmBuilder;
132
+ export {};
133
+ //# sourceMappingURL=cloudfront-alarm-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudfront-alarm-builder.d.ts","sourceRoot":"","sources":["../src/cloudfront-alarm-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAExD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,SAAS,EAEd,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,sBAAsB,EAAgB,MAAM,0BAA0B,CAAC;AAChF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAGjE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAE3E;;;;;;;;GAQG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;;;;;;;;;;;;;OAgBG;IACH,iBAAiB,CAAC,EAAE,uBAAuB,GAAG,KAAK,CAAC;CACrD;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC/B;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC,2BAA2B,EAAE,sBAAsB,CAAC,CAAC;AAsBpG;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,UAAU,EACjB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,IAAI,CAAC,yBAAyB,EAAE,cAAc,GAAG,WAAW,CAAC,EACrE,OAAO,GAAE;IACP,iBAAiB,CAAC,EAAE,uBAAuB,GAAG,KAAK,CAAC;IACpD,YAAY,CAAC,EAAE,sBAAsB,CAAC,YAAY,CAAC,EAAE,CAAC;CAClD,GACL,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAyBvB;AAED,cAAM,sBAAuB,YAAW,SAAS,CAAC,4BAA4B,CAAC;;IAC7E,KAAK,EAAE,OAAO,CAAC,2BAA2B,CAAC,CAAM;IAIjD;;;;;;;;;OASG;IACH,YAAY,CAAC,YAAY,EAAE,UAAU,CAAC,yBAAyB,CAAC,GAAG,IAAI;IAKvE;;;;;;;;OAQG;IACH,QAAQ,CACN,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,CACT,KAAK,EAAE,sBAAsB,CAAC,YAAY,CAAC,KACxC,sBAAsB,CAAC,YAAY,CAAC,GACxC,IAAI;IAKP,KAAK,CACH,KAAK,EAAE,UAAU,EACjB,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,4BAA4B;CAehC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,4BAA4B,IAAI,uBAAuB,CAEtE"}