@composurecdk/sqs 0.8.7 → 0.9.1

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 (94) hide show
  1. package/README.md +99 -13
  2. package/dist/commonjs/dlq-alarm-defaults.d.ts +53 -0
  3. package/dist/commonjs/dlq-alarm-defaults.d.ts.map +1 -0
  4. package/dist/commonjs/dlq-alarm-defaults.js +53 -0
  5. package/dist/commonjs/dlq-alarm-defaults.js.map +1 -0
  6. package/dist/commonjs/dlq-defaults.d.ts +19 -0
  7. package/dist/commonjs/dlq-defaults.d.ts.map +1 -0
  8. package/dist/commonjs/dlq-defaults.js +22 -0
  9. package/dist/commonjs/dlq-defaults.js.map +1 -0
  10. package/dist/commonjs/grants.d.ts +19 -0
  11. package/dist/commonjs/grants.d.ts.map +1 -0
  12. package/dist/commonjs/grants.js +28 -0
  13. package/dist/commonjs/grants.js.map +1 -0
  14. package/dist/commonjs/index.d.ts +6 -1
  15. package/dist/commonjs/index.d.ts.map +1 -1
  16. package/dist/commonjs/index.js +7 -1
  17. package/dist/commonjs/index.js.map +1 -1
  18. package/dist/commonjs/queue-alarm-config.d.ts +47 -11
  19. package/dist/commonjs/queue-alarm-config.d.ts.map +1 -1
  20. package/dist/commonjs/queue-alarm-defaults.d.ts +46 -11
  21. package/dist/commonjs/queue-alarm-defaults.d.ts.map +1 -1
  22. package/dist/commonjs/queue-alarm-defaults.js +11 -5
  23. package/dist/commonjs/queue-alarm-defaults.js.map +1 -1
  24. package/dist/commonjs/queue-alarm-profiles.d.ts +37 -0
  25. package/dist/commonjs/queue-alarm-profiles.d.ts.map +1 -0
  26. package/dist/commonjs/queue-alarm-profiles.js +96 -0
  27. package/dist/commonjs/queue-alarm-profiles.js.map +1 -0
  28. package/dist/commonjs/queue-alarms.d.ts +10 -3
  29. package/dist/commonjs/queue-alarms.d.ts.map +1 -1
  30. package/dist/commonjs/queue-alarms.js +52 -46
  31. package/dist/commonjs/queue-alarms.js.map +1 -1
  32. package/dist/commonjs/queue-builder.d.ts +70 -53
  33. package/dist/commonjs/queue-builder.d.ts.map +1 -1
  34. package/dist/commonjs/queue-builder.js +27 -68
  35. package/dist/commonjs/queue-builder.js.map +1 -1
  36. package/dist/commonjs/queue-props.d.ts +94 -0
  37. package/dist/commonjs/queue-props.d.ts.map +1 -0
  38. package/dist/commonjs/queue-props.js +16 -0
  39. package/dist/commonjs/queue-props.js.map +1 -0
  40. package/dist/commonjs/queue-role.d.ts +28 -0
  41. package/dist/commonjs/queue-role.d.ts.map +1 -0
  42. package/dist/commonjs/queue-role.js +13 -0
  43. package/dist/commonjs/queue-role.js.map +1 -0
  44. package/dist/commonjs/queue-validation.d.ts +12 -0
  45. package/dist/commonjs/queue-validation.d.ts.map +1 -0
  46. package/dist/commonjs/queue-validation.js +142 -0
  47. package/dist/commonjs/queue-validation.js.map +1 -0
  48. package/dist/esm/dlq-alarm-defaults.d.ts +53 -0
  49. package/dist/esm/dlq-alarm-defaults.d.ts.map +1 -0
  50. package/dist/esm/dlq-alarm-defaults.js +50 -0
  51. package/dist/esm/dlq-alarm-defaults.js.map +1 -0
  52. package/dist/esm/dlq-defaults.d.ts +19 -0
  53. package/dist/esm/dlq-defaults.d.ts.map +1 -0
  54. package/dist/esm/dlq-defaults.js +19 -0
  55. package/dist/esm/dlq-defaults.js.map +1 -0
  56. package/dist/esm/grants.d.ts +19 -0
  57. package/dist/esm/grants.d.ts.map +1 -0
  58. package/dist/esm/grants.js +25 -0
  59. package/dist/esm/grants.js.map +1 -0
  60. package/dist/esm/index.d.ts +6 -1
  61. package/dist/esm/index.d.ts.map +1 -1
  62. package/dist/esm/index.js +3 -0
  63. package/dist/esm/index.js.map +1 -1
  64. package/dist/esm/queue-alarm-config.d.ts +47 -11
  65. package/dist/esm/queue-alarm-config.d.ts.map +1 -1
  66. package/dist/esm/queue-alarm-defaults.d.ts +46 -11
  67. package/dist/esm/queue-alarm-defaults.d.ts.map +1 -1
  68. package/dist/esm/queue-alarm-defaults.js +11 -5
  69. package/dist/esm/queue-alarm-defaults.js.map +1 -1
  70. package/dist/esm/queue-alarm-profiles.d.ts +37 -0
  71. package/dist/esm/queue-alarm-profiles.d.ts.map +1 -0
  72. package/dist/esm/queue-alarm-profiles.js +92 -0
  73. package/dist/esm/queue-alarm-profiles.js.map +1 -0
  74. package/dist/esm/queue-alarms.d.ts +10 -3
  75. package/dist/esm/queue-alarms.d.ts.map +1 -1
  76. package/dist/esm/queue-alarms.js +53 -47
  77. package/dist/esm/queue-alarms.js.map +1 -1
  78. package/dist/esm/queue-builder.d.ts +70 -53
  79. package/dist/esm/queue-builder.d.ts.map +1 -1
  80. package/dist/esm/queue-builder.js +27 -68
  81. package/dist/esm/queue-builder.js.map +1 -1
  82. package/dist/esm/queue-props.d.ts +94 -0
  83. package/dist/esm/queue-props.d.ts.map +1 -0
  84. package/dist/esm/queue-props.js +13 -0
  85. package/dist/esm/queue-props.js.map +1 -0
  86. package/dist/esm/queue-role.d.ts +28 -0
  87. package/dist/esm/queue-role.d.ts.map +1 -0
  88. package/dist/esm/queue-role.js +9 -0
  89. package/dist/esm/queue-role.js.map +1 -0
  90. package/dist/esm/queue-validation.d.ts +12 -0
  91. package/dist/esm/queue-validation.d.ts.map +1 -0
  92. package/dist/esm/queue-validation.js +139 -0
  93. package/dist/esm/queue-validation.js.map +1 -0
  94. package/package.json +11 -5
@@ -0,0 +1,19 @@
1
+ import type { IGrantable } from "aws-cdk-lib/aws-iam";
2
+ import type { IQueue } from "aws-cdk-lib/aws-sqs";
3
+ import { type Grant, type Resolvable } from "@composurecdk/core";
4
+ /**
5
+ * Consumer-side grant helpers for an SQS queue. Pass one to a grantee builder's
6
+ * `grant(...)` — e.g.
7
+ * `role.grant(queueGrants.consume(ref("queue", (r) => r.queue)))`.
8
+ *
9
+ * Each delegates to the queue's native `grant*` method. See ADR-0013.
10
+ */
11
+ export declare const queueGrants: {
12
+ /** Receive and delete messages (`sqs:ReceiveMessage`, `DeleteMessage`, …). */
13
+ consume: (queue: Resolvable<IQueue>) => Grant<IGrantable>;
14
+ /** Send messages (`sqs:SendMessage`, `GetQueueAttributes`, …). */
15
+ send: (queue: Resolvable<IQueue>) => Grant<IGrantable>;
16
+ /** Purge the queue (`sqs:PurgeQueue`). */
17
+ purge: (queue: Resolvable<IQueue>) => Grant<IGrantable>;
18
+ };
19
+ //# sourceMappingURL=grants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grants.d.ts","sourceRoot":"","sources":["../../src/grants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,KAAK,KAAK,EAAY,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAQ3E;;;;;;GAMG;AACH,eAAO,MAAM,WAAW;IACtB,8EAA8E;qBAXtE,UAAU,CAAC,MAAM,CAAC,KAAG,KAAK,CAAC,UAAU,CAAC;IAe9C,kEAAkE;kBAf1D,UAAU,CAAC,MAAM,CAAC,KAAG,KAAK,CAAC,UAAU,CAAC;IAmB9C,0CAA0C;mBAnBlC,UAAU,CAAC,MAAM,CAAC,KAAG,KAAK,CAAC,UAAU,CAAC;CAuB/C,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { grantVia } from "@composurecdk/core";
2
+ /** Wraps one of {@link IQueue}'s native grant methods as a capability helper. */
3
+ const capability = (apply) => (queue) => grantVia(queue, apply);
4
+ /**
5
+ * Consumer-side grant helpers for an SQS queue. Pass one to a grantee builder's
6
+ * `grant(...)` — e.g.
7
+ * `role.grant(queueGrants.consume(ref("queue", (r) => r.queue)))`.
8
+ *
9
+ * Each delegates to the queue's native `grant*` method. See ADR-0013.
10
+ */
11
+ export const queueGrants = {
12
+ /** Receive and delete messages (`sqs:ReceiveMessage`, `DeleteMessage`, …). */
13
+ consume: capability((queue, grantee) => {
14
+ queue.grantConsumeMessages(grantee);
15
+ }),
16
+ /** Send messages (`sqs:SendMessage`, `GetQueueAttributes`, …). */
17
+ send: capability((queue, grantee) => {
18
+ queue.grantSendMessages(grantee);
19
+ }),
20
+ /** Purge the queue (`sqs:PurgeQueue`). */
21
+ purge: capability((queue, grantee) => {
22
+ queue.grantPurge(grantee);
23
+ }),
24
+ };
25
+ //# sourceMappingURL=grants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grants.js","sourceRoot":"","sources":["../../src/grants.ts"],"names":[],"mappings":"AAEA,OAAO,EAAc,QAAQ,EAAmB,MAAM,oBAAoB,CAAC;AAE3E,iFAAiF;AACjF,MAAM,UAAU,GACd,CAAC,KAAmD,EAAE,EAAE,CACxD,CAAC,KAAyB,EAAqB,EAAE,CAC/C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAE3B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,8EAA8E;IAC9E,OAAO,EAAE,UAAU,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACrC,KAAK,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC,CAAC;IACF,kEAAkE;IAClE,IAAI,EAAE,UAAU,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QAClC,KAAK,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC,CAAC;IACF,0CAA0C;IAC1C,KAAK,EAAE,UAAU,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACnC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC,CAAC;CACH,CAAC"}
@@ -1,5 +1,10 @@
1
- export { createQueueBuilder, type IQueueBuilder, type QueueBuilderProps, type QueueBuilderResult, } from "./queue-builder.js";
1
+ export { createQueueBuilder, type IQueueBuilder, type QueueBuilderResult, } from "./queue-builder.js";
2
+ export { queueGrants } from "./grants.js";
3
+ export { type QueueRole } from "./queue-role.js";
4
+ export { type FifoQueueName, type QueueBuilderProps, type FifoQueueBuilderProps, type DlqQueueBuilderProps, type FifoDlqQueueBuilderProps, type QueueBuilderPropsByRole, } from "./queue-props.js";
2
5
  export { QUEUE_DEFAULTS } from "./defaults.js";
6
+ export { DLQ_QUEUE_DEFAULTS } from "./dlq-defaults.js";
3
7
  export { type QueueAlarmConfig } from "./queue-alarm-config.js";
4
8
  export { QUEUE_ALARM_DEFAULTS } from "./queue-alarm-defaults.js";
9
+ export { DLQ_ALARM_DEFAULTS } from "./dlq-alarm-defaults.js";
5
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,aAAa,EAClB,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAMjD,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC7B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/esm/index.js CHANGED
@@ -1,4 +1,7 @@
1
1
  export { createQueueBuilder, } from "./queue-builder.js";
2
+ export { queueGrants } from "./grants.js";
2
3
  export { QUEUE_DEFAULTS } from "./defaults.js";
4
+ export { DLQ_QUEUE_DEFAULTS } from "./dlq-defaults.js";
3
5
  export { QUEUE_ALARM_DEFAULTS } from "./queue-alarm-defaults.js";
6
+ export { DLQ_ALARM_DEFAULTS } from "./dlq-alarm-defaults.js";
4
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAInB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAGnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAe1C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,9 +1,12 @@
1
1
  import type { AlarmConfig } from "@composurecdk/cloudwatch";
2
2
  /**
3
3
  * Controls which recommended alarms are created for an SQS queue.
4
- * All applicable alarms are enabled by default with AWS-recommended thresholds.
5
- * Set individual alarms to `false` to disable them, or provide an
6
- * {@link AlarmConfig} to tune thresholds.
4
+ * Which alarms are enabled by default — and their thresholds — depends
5
+ * on the queue's {@link QueueRole}: the primary roles (`"standard"`,
6
+ * `"fifo"`) and the dead-letter roles (`"dlq"`, `"fifo-dlq"`) invert
7
+ * which signals matter. Set an individual alarm to `false` to disable
8
+ * it, or provide an {@link AlarmConfig} to enable it (if off by
9
+ * default) or tune its thresholds (if on by default).
7
10
  *
8
11
  * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#SQS
9
12
  */
@@ -16,15 +19,16 @@ export interface QueueAlarmConfig {
16
19
  enabled?: boolean;
17
20
  /**
18
21
  * Alarm when the oldest unprocessed message in the queue has been
19
- * waiting longer than the configured threshold. Primary signal that
20
- * consumers are falling behind.
22
+ * waiting longer than the configured threshold.
23
+ *
24
+ * On a primary queue this is the primary signal that consumers are
25
+ * falling behind (default threshold: > 300 seconds). On a dead-letter
26
+ * queue it signals messages approaching the end of the queue's
27
+ * `retentionPeriod` unattended (default threshold: 75% of the
28
+ * retention period — see {@link DLQ_ALARM_DEFAULTS}).
21
29
  *
22
30
  * Metric: `AWS/SQS ApproximateAgeOfOldestMessage`, statistic Maximum,
23
31
  * period 1 minute.
24
- * Default threshold: > 300 seconds (5 minutes).
25
- *
26
- * The default is conservative and should be tuned to the queue's
27
- * SLA and `retentionPeriod`.
28
32
  *
29
33
  * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#SQS
30
34
  */
@@ -34,13 +38,45 @@ export interface QueueAlarmConfig {
34
38
  * messages approaches the SQS quota of 120,000 per queue. A breach
35
39
  * means new messages will start being rejected.
36
40
  *
41
+ * Enabled by default on primary queues (threshold: > 90,000 — 75% of
42
+ * the quota). Disabled by default on dead-letter queues, where nothing
43
+ * is normally in flight.
44
+ *
37
45
  * Metric: `AWS/SQS ApproximateNumberOfMessagesNotVisible`, statistic
38
46
  * Maximum, period 1 minute.
39
- * Default threshold: > 90,000 (75% of the in-flight quota).
40
47
  *
41
- * @see https://docs.aws.amazon.com/AmazonSQS/latest/SQSDeveloperGuide/quotas-messages.html#quotas-in-flight
48
+ * @see https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/quotas-messages.html#quotas-in-flight
42
49
  * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#SQS
43
50
  */
44
51
  approximateNumberOfMessagesNotVisible?: AlarmConfig | false;
52
+ /**
53
+ * Alarm when the queue has visible (available-to-receive) messages
54
+ * above the threshold.
55
+ *
56
+ * Disabled by default on a primary queue — messages waiting to be
57
+ * consumed are the normal state, and no generic threshold suits every
58
+ * workload's processing capacity. Enable it explicitly with a
59
+ * threshold sized to your consumers; enabling it on a primary queue
60
+ * without a threshold throws at build.
61
+ *
62
+ * Enabled by default on a dead-letter queue, where any message present
63
+ * is itself the alert (default threshold: > 0). See
64
+ * {@link DLQ_ALARM_DEFAULTS}.
65
+ *
66
+ * Metric: `AWS/SQS ApproximateNumberOfMessagesVisible`, statistic
67
+ * Maximum, period 1 minute.
68
+ *
69
+ * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#SQS
70
+ */
71
+ approximateNumberOfMessagesVisible?: AlarmConfig | false;
45
72
  }
73
+ /**
74
+ * Keys of the recommended SQS alarms a queue builder can create —
75
+ * every {@link QueueAlarmConfig} entry except the `enabled` master
76
+ * switch. Shared between the primary-queue defaults
77
+ * ({@link QUEUE_ALARM_DEFAULTS}) and the dead-letter-queue defaults
78
+ * ({@link DLQ_ALARM_DEFAULTS}) so every builder resolves the same
79
+ * config shape.
80
+ */
81
+ export type QueueAlarmKey = Exclude<keyof QueueAlarmConfig, "enabled">;
46
82
  //# sourceMappingURL=queue-alarm-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queue-alarm-config.d.ts","sourceRoot":"","sources":["../../src/queue-alarm-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;;;;;;OAaG;IACH,6BAA6B,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAEpD;;;;;;;;;;;OAWG;IACH,qCAAqC,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;CAC7D"}
1
+ {"version":3,"file":"queue-alarm-config.d.ts","sourceRoot":"","sources":["../../src/queue-alarm-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;;;;;;;OAcG;IACH,6BAA6B,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAEpD;;;;;;;;;;;;;;OAcG;IACH,qCAAqC,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAE5D;;;;;;;;;;;;;;;;;;OAkBG;IACH,kCAAkC,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;CAC1D;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,gBAAgB,EAAE,SAAS,CAAC,CAAC"}
@@ -1,18 +1,53 @@
1
+ import { TreatMissingData } from "aws-cdk-lib/aws-cloudwatch";
1
2
  import type { AlarmConfigDefaults } from "@composurecdk/cloudwatch";
2
- interface QueueAlarmDefaults {
3
- enabled: true;
4
- approximateAgeOfOldestMessage: AlarmConfigDefaults;
5
- approximateNumberOfMessagesNotVisible: AlarmConfigDefaults;
6
- }
3
+ import type { QueueAlarmKey } from "./queue-alarm-config.js";
7
4
  /**
8
- * AWS-recommended default alarm configuration for SQS queues.
5
+ * Shape of a recommended-alarm default set: an {@link AlarmConfigDefaults}
6
+ * baseline per recommended SQS alarm. Partial — an alarm with no entry
7
+ * has no generic default and requires an explicit threshold when
8
+ * enabled. Implemented by {@link QUEUE_ALARM_DEFAULTS} (primary queues)
9
+ * and {@link DLQ_ALARM_DEFAULTS} (dead-letter queues).
10
+ */
11
+ export type QueueAlarmDefaults = Partial<Record<QueueAlarmKey, AlarmConfigDefaults>>;
12
+ /**
13
+ * AWS-recommended default alarm configuration for primary
14
+ * (consumer-fed) SQS queues, standard and FIFO alike — since November
15
+ * 2024 FIFO queues share the standard 120,000 in-flight quota, so the
16
+ * same thresholds apply.
9
17
  *
10
- * Tuned for primary (consumer-fed) queues. Dead-letter queues need
11
- * different thresholds — any message on a DLQ is itself an alert,
12
- * whereas a primary queue with messages is normal.
18
+ * These are threshold baselines only — which alarms are *enabled* by
19
+ * default differs per builder: dead-letter queues invert the set (see
20
+ * {@link DLQ_ALARM_DEFAULTS}) because any message on a DLQ is itself an
21
+ * alert, whereas a primary queue with messages is normal. There is no
22
+ * entry for `approximateNumberOfMessagesVisible`: no generic threshold
23
+ * suits a primary queue, so enabling it requires an explicit threshold.
13
24
  *
14
25
  * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#SQS
26
+ * @see https://aws.amazon.com/about-aws/whats-new/2024/11/amazon-sqs-increases-in-flight-limit-fifo-queues/
15
27
  */
16
- export declare const QUEUE_ALARM_DEFAULTS: QueueAlarmDefaults;
17
- export {};
28
+ export declare const QUEUE_ALARM_DEFAULTS: {
29
+ /**
30
+ * 5 minutes. Conservative starting point for a "consumer falling
31
+ * behind" alarm. The right value depends on the workload's SLA and
32
+ * `retentionPeriod`; tune via `recommendedAlarms`.
33
+ */
34
+ approximateAgeOfOldestMessage: {
35
+ threshold: number;
36
+ evaluationPeriods: number;
37
+ datapointsToAlarm: number;
38
+ treatMissingData: TreatMissingData.NOT_BREACHING;
39
+ };
40
+ /**
41
+ * 90,000 — 75% of the SQS 120,000 in-flight message quota. Proactive
42
+ * guardrail; a breach means the queue is approaching the point where
43
+ * new messages will be rejected.
44
+ * @see https://docs.aws.amazon.com/AmazonSQS/latest/SQSDeveloperGuide/quotas-messages.html#quotas-in-flight
45
+ */
46
+ approximateNumberOfMessagesNotVisible: {
47
+ threshold: number;
48
+ evaluationPeriods: number;
49
+ datapointsToAlarm: number;
50
+ treatMissingData: TreatMissingData.NOT_BREACHING;
51
+ };
52
+ };
18
53
  //# sourceMappingURL=queue-alarm-defaults.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queue-alarm-defaults.d.ts","sourceRoot":"","sources":["../../src/queue-alarm-defaults.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,UAAU,kBAAkB;IAC1B,OAAO,EAAE,IAAI,CAAC;IACd,6BAA6B,EAAE,mBAAmB,CAAC;IACnD,qCAAqC,EAAE,mBAAmB,CAAC;CAC5D;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,kBA2BlC,CAAC"}
1
+ {"version":3,"file":"queue-alarm-defaults.d.ts","sourceRoot":"","sources":["../../src/queue-alarm-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAErF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,oBAAoB;IAC/B;;;;OAIG;;;;;;;IAQH;;;;;OAKG;;;;;;;CAOyB,CAAC"}
@@ -1,15 +1,21 @@
1
1
  import { TreatMissingData } from "aws-cdk-lib/aws-cloudwatch";
2
2
  /**
3
- * AWS-recommended default alarm configuration for SQS queues.
3
+ * AWS-recommended default alarm configuration for primary
4
+ * (consumer-fed) SQS queues, standard and FIFO alike — since November
5
+ * 2024 FIFO queues share the standard 120,000 in-flight quota, so the
6
+ * same thresholds apply.
4
7
  *
5
- * Tuned for primary (consumer-fed) queues. Dead-letter queues need
6
- * different thresholds — any message on a DLQ is itself an alert,
7
- * whereas a primary queue with messages is normal.
8
+ * These are threshold baselines only — which alarms are *enabled* by
9
+ * default differs per builder: dead-letter queues invert the set (see
10
+ * {@link DLQ_ALARM_DEFAULTS}) because any message on a DLQ is itself an
11
+ * alert, whereas a primary queue with messages is normal. There is no
12
+ * entry for `approximateNumberOfMessagesVisible`: no generic threshold
13
+ * suits a primary queue, so enabling it requires an explicit threshold.
8
14
  *
9
15
  * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#SQS
16
+ * @see https://aws.amazon.com/about-aws/whats-new/2024/11/amazon-sqs-increases-in-flight-limit-fifo-queues/
10
17
  */
11
18
  export const QUEUE_ALARM_DEFAULTS = {
12
- enabled: true,
13
19
  /**
14
20
  * 5 minutes. Conservative starting point for a "consumer falling
15
21
  * behind" alarm. The right value depends on the workload's SLA and
@@ -1 +1 @@
1
- {"version":3,"file":"queue-alarm-defaults.js","sourceRoot":"","sources":["../../src/queue-alarm-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAS9D;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAuB;IACtD,OAAO,EAAE,IAAI;IAEb;;;;OAIG;IACH,6BAA6B,EAAE;QAC7B,SAAS,EAAE,GAAG;QACd,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;IAED;;;;;OAKG;IACH,qCAAqC,EAAE;QACrC,SAAS,EAAE,MAAM;QACjB,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;CACF,CAAC"}
1
+ {"version":3,"file":"queue-alarm-defaults.js","sourceRoot":"","sources":["../../src/queue-alarm-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAa9D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC;;;;OAIG;IACH,6BAA6B,EAAE;QAC7B,SAAS,EAAE,GAAG;QACd,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;IAED;;;;;OAKG;IACH,qCAAqC,EAAE;QACrC,SAAS,EAAE,MAAM;QACjB,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;KACjD;CAC2B,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { Duration } from "aws-cdk-lib";
2
+ import type { IQueue } from "aws-cdk-lib/aws-sqs";
3
+ import type { IConstruct } from "constructs";
4
+ import type { AlarmMetric } from "@composurecdk/cloudwatch";
5
+ import type { QueueAlarmKey } from "./queue-alarm-config.js";
6
+ import type { QueueAlarmDefaults } from "./queue-alarm-defaults.js";
7
+ /** Metric factory for each recommended SQS alarm. */
8
+ export declare const QUEUE_ALARM_METRICS: Record<QueueAlarmKey, (queue: IQueue) => AlarmMetric>;
9
+ /**
10
+ * How a queue builder interprets the recommended-alarm set: which alarms
11
+ * are created without explicit opt-in, the default thresholds each alarm
12
+ * merges against (an alarm with no baseline requires an explicit
13
+ * threshold when enabled), and the description each produces. Primary
14
+ * queues and dead-letter queues need different profiles because the
15
+ * alarm semantics invert — see {@link DLQ_ALARM_DEFAULTS}.
16
+ */
17
+ export interface QueueAlarmProfile {
18
+ /** Whether each alarm is created when the user hasn't configured it. */
19
+ enablement: Record<QueueAlarmKey, boolean>;
20
+ /** Default config each alarm merges user overrides against. */
21
+ defaults: QueueAlarmDefaults;
22
+ /** Alarm description, given the resolved threshold. */
23
+ descriptions: Record<QueueAlarmKey, (threshold: number) => string>;
24
+ }
25
+ /** Recommended-alarm profile for primary (consumer-fed) queues, standard and FIFO. */
26
+ export declare const PRIMARY_ALARM_PROFILE: QueueAlarmProfile;
27
+ /**
28
+ * Recommended-alarm profile for dead-letter queues. The age alarm's
29
+ * default threshold is {@link DLQ_AGE_ALARM_RETENTION_RATIO} of the
30
+ * queue's resolved `retentionPeriod`, so it keeps firing before messages
31
+ * age out even when retention is tuned. When the retention is an
32
+ * unresolved token there is no basis to derive from — the age alarm is
33
+ * skipped with an acknowledgeable warning (unless explicitly configured
34
+ * with a threshold), per the library-wide derived-threshold convention.
35
+ */
36
+ export declare function dlqAlarmProfile(scope: IConstruct, retentionPeriod: Duration | undefined): QueueAlarmProfile;
37
+ //# sourceMappingURL=queue-alarm-profiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-alarm-profiles.d.ts","sourceRoot":"","sources":["../../src/queue-alarm-profiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAOpE,qDAAqD;AACrD,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,WAAW,CAOrF,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAC3C,+DAA+D;IAC/D,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;CACpE;AAOD,sFAAsF;AACtF,eAAO,MAAM,qBAAqB,EAAE,iBAgBnC,CAAC;AAkCF;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,QAAQ,GAAG,SAAS,GACpC,iBAAiB,CAwBnB"}
@@ -0,0 +1,92 @@
1
+ import { Duration } from "aws-cdk-lib";
2
+ import { resolveAlarmThresholdBasis } from "@composurecdk/cloudwatch";
3
+ import { QUEUE_ALARM_DEFAULTS } from "./queue-alarm-defaults.js";
4
+ import { DLQ_AGE_ALARM_RETENTION_RATIO, DLQ_ALARM_DEFAULTS } from "./dlq-alarm-defaults.js";
5
+ const METRIC_PERIOD = Duration.minutes(1);
6
+ const METRIC_PERIOD_LABEL = `${String(METRIC_PERIOD.toMinutes())} minute`;
7
+ /** Metric factory for each recommended SQS alarm. */
8
+ export const QUEUE_ALARM_METRICS = {
9
+ approximateAgeOfOldestMessage: (queue) => queue.metricApproximateAgeOfOldestMessage({ period: METRIC_PERIOD }),
10
+ approximateNumberOfMessagesNotVisible: (queue) => queue.metricApproximateNumberOfMessagesNotVisible({ period: METRIC_PERIOD }),
11
+ approximateNumberOfMessagesVisible: (queue) => queue.metricApproximateNumberOfMessagesVisible({ period: METRIC_PERIOD }),
12
+ };
13
+ const describeInFlight = (threshold) => `SQS queue's in-flight messages are approaching the 120,000 per-queue quota; ` +
14
+ `further receives will be rejected once the quota is hit. ` +
15
+ `Threshold: > ${String(threshold)} in-flight in ${METRIC_PERIOD_LABEL}.`;
16
+ /** Recommended-alarm profile for primary (consumer-fed) queues, standard and FIFO. */
17
+ export const PRIMARY_ALARM_PROFILE = {
18
+ enablement: {
19
+ approximateAgeOfOldestMessage: true,
20
+ approximateNumberOfMessagesNotVisible: true,
21
+ approximateNumberOfMessagesVisible: false,
22
+ },
23
+ defaults: QUEUE_ALARM_DEFAULTS,
24
+ descriptions: {
25
+ approximateAgeOfOldestMessage: (threshold) => `SQS queue's oldest message has been waiting longer than the threshold, ` +
26
+ `indicating consumers are falling behind. Threshold: > ${String(threshold)} seconds in ${METRIC_PERIOD_LABEL}.`,
27
+ approximateNumberOfMessagesNotVisible: describeInFlight,
28
+ approximateNumberOfMessagesVisible: (threshold) => `Queue has more visible messages waiting than expected for this workload. ` +
29
+ `Threshold: > ${String(threshold)} in ${METRIC_PERIOD_LABEL}.`,
30
+ },
31
+ };
32
+ const DLQ_ALARM_ENABLEMENT = {
33
+ approximateAgeOfOldestMessage: true,
34
+ approximateNumberOfMessagesNotVisible: false,
35
+ approximateNumberOfMessagesVisible: true,
36
+ };
37
+ const DLQ_ALARM_DESCRIPTIONS = {
38
+ approximateAgeOfOldestMessage: (threshold) => `Dead-letter queue's oldest message is approaching the queue's retentionPeriod — ` +
39
+ `investigate and redrive it before SQS deletes it. ` +
40
+ `Threshold: > ${String(threshold)} seconds in ${METRIC_PERIOD_LABEL}.`,
41
+ approximateNumberOfMessagesNotVisible: describeInFlight,
42
+ approximateNumberOfMessagesVisible: (threshold) => `Dead-letter queue has messages present — any message here indicates a delivery ` +
43
+ `failure that needs investigation. Threshold: > ${String(threshold)} in ${METRIC_PERIOD_LABEL}.`,
44
+ };
45
+ /**
46
+ * The dead-letter profile when the retention period is an unresolved
47
+ * token: the retention-derived age alarm has no basis to derive from,
48
+ * so it is off (an explicit user threshold still re-enables it); the
49
+ * rest of the DLQ set is unchanged.
50
+ */
51
+ const DLQ_TOKEN_RETENTION_ALARM_PROFILE = {
52
+ enablement: { ...DLQ_ALARM_ENABLEMENT, approximateAgeOfOldestMessage: false },
53
+ defaults: {
54
+ approximateNumberOfMessagesNotVisible: DLQ_ALARM_DEFAULTS.approximateNumberOfMessagesNotVisible,
55
+ approximateNumberOfMessagesVisible: DLQ_ALARM_DEFAULTS.approximateNumberOfMessagesVisible,
56
+ },
57
+ descriptions: DLQ_ALARM_DESCRIPTIONS,
58
+ };
59
+ /**
60
+ * Recommended-alarm profile for dead-letter queues. The age alarm's
61
+ * default threshold is {@link DLQ_AGE_ALARM_RETENTION_RATIO} of the
62
+ * queue's resolved `retentionPeriod`, so it keeps firing before messages
63
+ * age out even when retention is tuned. When the retention is an
64
+ * unresolved token there is no basis to derive from — the age alarm is
65
+ * skipped with an acknowledgeable warning (unless explicitly configured
66
+ * with a threshold), per the library-wide derived-threshold convention.
67
+ */
68
+ export function dlqAlarmProfile(scope, retentionPeriod) {
69
+ const retentionSeconds = resolveAlarmThresholdBasis({
70
+ scope,
71
+ value: retentionPeriod,
72
+ resolve: (duration) => duration.toSeconds(),
73
+ isUnresolved: (duration) => duration.isUnresolved(),
74
+ warningId: "@composurecdk/sqs:dlq-age-alarm-token-retention",
75
+ alarmLabel: "dead-letter queue message-age",
76
+ suppressHint: "recommendedAlarms({ approximateAgeOfOldestMessage: false })",
77
+ });
78
+ if (retentionSeconds === undefined)
79
+ return DLQ_TOKEN_RETENTION_ALARM_PROFILE;
80
+ return {
81
+ enablement: DLQ_ALARM_ENABLEMENT,
82
+ defaults: {
83
+ ...DLQ_ALARM_DEFAULTS,
84
+ approximateAgeOfOldestMessage: {
85
+ ...DLQ_ALARM_DEFAULTS.approximateAgeOfOldestMessage,
86
+ threshold: Math.round(retentionSeconds * DLQ_AGE_ALARM_RETENTION_RATIO),
87
+ },
88
+ },
89
+ descriptions: DLQ_ALARM_DESCRIPTIONS,
90
+ };
91
+ }
92
+ //# sourceMappingURL=queue-alarm-profiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-alarm-profiles.js","sourceRoot":"","sources":["../../src/queue-alarm-profiles.ts"],"names":[],"mappings":"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"}
@@ -4,11 +4,15 @@ import type { IConstruct } from "constructs";
4
4
  import type { AlarmDefinition } from "@composurecdk/cloudwatch";
5
5
  import { AlarmDefinitionBuilder } from "@composurecdk/cloudwatch";
6
6
  import type { QueueAlarmConfig } from "./queue-alarm-config.js";
7
+ import type { QueueAlarmProfile } from "./queue-alarm-profiles.js";
7
8
  /**
8
9
  * Resolves the recommended alarm configuration into fully-resolved
9
10
  * {@link AlarmDefinition}s for an SQS queue.
11
+ *
12
+ * @param profile - The builder's alarm profile: which alarms are created
13
+ * without explicit opt-in and the defaults they merge against.
10
14
  */
11
- export declare function resolveQueueAlarmDefinitions(queue: IQueue, config: QueueAlarmConfig | undefined): AlarmDefinition[];
15
+ export declare function resolveQueueAlarmDefinitions(queue: IQueue, config: QueueAlarmConfig | undefined, profile: QueueAlarmProfile): AlarmDefinition[];
12
16
  /**
13
17
  * Creates AWS-recommended CloudWatch alarms for an SQS queue, merging
14
18
  * recommended definitions with any custom alarm builders.
@@ -16,11 +20,14 @@ export declare function resolveQueueAlarmDefinitions(queue: IQueue, config: Queu
16
20
  * @param scope - CDK construct scope for creating alarm constructs.
17
21
  * @param id - Base identifier for alarm construct ids.
18
22
  * @param queue - The SQS queue to create alarms for.
19
- * @param config - User-provided alarm configuration, or `false` to disable all.
23
+ * @param config - User-provided alarm configuration, or `false` to disable the
24
+ * recommended alarms.
20
25
  * @param customAlarms - Custom alarm builders added via `addAlarm()`.
26
+ * @param profile - The builder's alarm profile; see
27
+ * {@link resolveQueueAlarmDefinitions}.
21
28
  * @returns A record mapping alarm keys to their created Alarm constructs.
22
29
  *
23
30
  * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#SQS
24
31
  */
25
- export declare function createQueueAlarms(scope: IConstruct, id: string, queue: IQueue, config: QueueAlarmConfig | false | undefined, customAlarms?: AlarmDefinitionBuilder<IQueue>[]): Record<string, Alarm>;
32
+ export declare function createQueueAlarms(scope: IConstruct, id: string, queue: IQueue, config: QueueAlarmConfig | false | undefined, customAlarms: AlarmDefinitionBuilder<IQueue>[], profile: QueueAlarmProfile): Record<string, Alarm>;
26
33
  //# sourceMappingURL=queue-alarms.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queue-alarms.d.ts","sourceRoot":"","sources":["../../src/queue-alarms.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,KAAK,EAAsB,MAAM,4BAA4B,CAAC;AAC5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAoC,MAAM,0BAA0B,CAAC;AACpG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAMhE;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,GAAG,SAAS,GACnC,eAAe,EAAE,CA+CnB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,UAAU,EACjB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,GAAG,KAAK,GAAG,SAAS,EAC5C,YAAY,GAAE,sBAAsB,CAAC,MAAM,CAAC,EAAO,GAClD,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAUvB"}
1
+ {"version":3,"file":"queue-alarms.d.ts","sourceRoot":"","sources":["../../src/queue-alarms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAwC,MAAM,4BAA4B,CAAC;AAC9F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAoC,MAAM,0BAA0B,CAAC;AACpG,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,yBAAyB,CAAC;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAenE;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,GAAG,SAAS,EACpC,OAAO,EAAE,iBAAiB,GACzB,eAAe,EAAE,CAoCnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,UAAU,EACjB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,GAAG,KAAK,GAAG,SAAS,EAC5C,YAAY,EAAE,sBAAsB,CAAC,MAAM,CAAC,EAAE,EAC9C,OAAO,EAAE,iBAAiB,GACzB,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAQvB"}
@@ -1,49 +1,55 @@
1
- import { Duration } from "aws-cdk-lib";
2
- import { ComparisonOperator } from "aws-cdk-lib/aws-cloudwatch";
1
+ import { ComparisonOperator, TreatMissingData } from "aws-cdk-lib/aws-cloudwatch";
3
2
  import { createAlarms, resolveAlarmConfig } from "@composurecdk/cloudwatch";
4
- import { QUEUE_ALARM_DEFAULTS } from "./queue-alarm-defaults.js";
5
- const METRIC_PERIOD = Duration.minutes(1);
6
- const METRIC_PERIOD_LABEL = `${String(METRIC_PERIOD.toMinutes())} minute`;
3
+ import { QUEUE_ALARM_METRICS } from "./queue-alarm-profiles.js";
4
+ const QUEUE_ALARM_KEYS = Object.keys(QUEUE_ALARM_METRICS);
5
+ /**
6
+ * Non-threshold baseline for alarms enabled without a profile default —
7
+ * the threshold itself must come from the user's config.
8
+ */
9
+ const OPT_IN_ALARM_BASELINE = {
10
+ evaluationPeriods: 1,
11
+ datapointsToAlarm: 1,
12
+ treatMissingData: TreatMissingData.NOT_BREACHING,
13
+ };
7
14
  /**
8
15
  * Resolves the recommended alarm configuration into fully-resolved
9
16
  * {@link AlarmDefinition}s for an SQS queue.
17
+ *
18
+ * @param profile - The builder's alarm profile: which alarms are created
19
+ * without explicit opt-in and the defaults they merge against.
10
20
  */
11
- export function resolveQueueAlarmDefinitions(queue, config) {
21
+ export function resolveQueueAlarmDefinitions(queue, config, profile) {
12
22
  if (config?.enabled === false)
13
23
  return [];
14
- const definitions = [];
15
- if (config?.approximateAgeOfOldestMessage !== false) {
16
- const cfg = resolveAlarmConfig(config?.approximateAgeOfOldestMessage, QUEUE_ALARM_DEFAULTS.approximateAgeOfOldestMessage);
17
- definitions.push({
18
- key: "approximateAgeOfOldestMessage",
19
- alarmName: cfg.alarmName,
20
- metric: queue.metricApproximateAgeOfOldestMessage({ period: METRIC_PERIOD }),
21
- threshold: cfg.threshold,
22
- comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
23
- evaluationPeriods: cfg.evaluationPeriods,
24
- datapointsToAlarm: cfg.datapointsToAlarm,
25
- treatMissingData: cfg.treatMissingData,
26
- description: `SQS queue's oldest message has been waiting longer than the threshold, ` +
27
- `indicating consumers are falling behind. Threshold: > ${String(cfg.threshold)} seconds in ${METRIC_PERIOD_LABEL}.`,
28
- });
29
- }
30
- if (config?.approximateNumberOfMessagesNotVisible !== false) {
31
- const cfg = resolveAlarmConfig(config?.approximateNumberOfMessagesNotVisible, QUEUE_ALARM_DEFAULTS.approximateNumberOfMessagesNotVisible);
32
- definitions.push({
33
- key: "approximateNumberOfMessagesNotVisible",
34
- alarmName: cfg.alarmName,
35
- metric: queue.metricApproximateNumberOfMessagesNotVisible({ period: METRIC_PERIOD }),
36
- threshold: cfg.threshold,
37
- comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
38
- evaluationPeriods: cfg.evaluationPeriods,
39
- datapointsToAlarm: cfg.datapointsToAlarm,
40
- treatMissingData: cfg.treatMissingData,
41
- description: `SQS queue's in-flight messages are approaching the 120,000 per-queue quota; ` +
42
- `further receives will be rejected once the quota is hit. ` +
43
- `Threshold: > ${String(cfg.threshold)} in-flight in ${METRIC_PERIOD_LABEL}.`,
44
- });
45
- }
46
- return definitions;
24
+ return QUEUE_ALARM_KEYS.flatMap((key) => {
25
+ const userConfig = config?.[key];
26
+ if (userConfig === false)
27
+ return [];
28
+ if (userConfig === undefined && !profile.enablement[key])
29
+ return [];
30
+ const baseline = profile.defaults[key];
31
+ if (baseline === undefined && userConfig?.threshold === undefined) {
32
+ throw new Error(`Queue "${queue.node.id}": the "${key}" alarm has no generic default threshold for ` +
33
+ `this queue type — no value fits every workload. Supply one explicitly, e.g. ` +
34
+ `recommendedAlarms({ ${key}: { threshold: … } }).`);
35
+ }
36
+ const cfg = resolveAlarmConfig(userConfig,
37
+ // userConfig.threshold is present whenever baseline is not — the guard above ensures it.
38
+ baseline ?? { ...OPT_IN_ALARM_BASELINE, threshold: userConfig?.threshold ?? 0 });
39
+ return [
40
+ {
41
+ key,
42
+ alarmName: cfg.alarmName,
43
+ metric: QUEUE_ALARM_METRICS[key](queue),
44
+ threshold: cfg.threshold,
45
+ comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
46
+ evaluationPeriods: cfg.evaluationPeriods,
47
+ datapointsToAlarm: cfg.datapointsToAlarm,
48
+ treatMissingData: cfg.treatMissingData,
49
+ description: profile.descriptions[key](cfg.threshold),
50
+ },
51
+ ];
52
+ });
47
53
  }
48
54
  /**
49
55
  * Creates AWS-recommended CloudWatch alarms for an SQS queue, merging
@@ -52,19 +58,19 @@ export function resolveQueueAlarmDefinitions(queue, config) {
52
58
  * @param scope - CDK construct scope for creating alarm constructs.
53
59
  * @param id - Base identifier for alarm construct ids.
54
60
  * @param queue - The SQS queue to create alarms for.
55
- * @param config - User-provided alarm configuration, or `false` to disable all.
61
+ * @param config - User-provided alarm configuration, or `false` to disable the
62
+ * recommended alarms.
56
63
  * @param customAlarms - Custom alarm builders added via `addAlarm()`.
64
+ * @param profile - The builder's alarm profile; see
65
+ * {@link resolveQueueAlarmDefinitions}.
57
66
  * @returns A record mapping alarm keys to their created Alarm constructs.
58
67
  *
59
68
  * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#SQS
60
69
  */
61
- export function createQueueAlarms(scope, id, queue, config, customAlarms = []) {
62
- if (config === false)
63
- return {};
64
- const enabled = config?.enabled ?? QUEUE_ALARM_DEFAULTS.enabled;
65
- if (!enabled)
66
- return {};
67
- const recommended = resolveQueueAlarmDefinitions(queue, config);
70
+ export function createQueueAlarms(scope, id, queue, config, customAlarms, profile) {
71
+ const recommended = config === false || config?.enabled === false
72
+ ? []
73
+ : resolveQueueAlarmDefinitions(queue, config, profile);
68
74
  const custom = customAlarms.map((b) => b.resolve(queue));
69
75
  return createAlarms(scope, id, [...recommended, ...custom]);
70
76
  }
@@ -1 +1 @@
1
- {"version":3,"file":"queue-alarms.js","sourceRoot":"","sources":["../../src/queue-alarms.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"queue-alarms.js","sourceRoot":"","sources":["../../src/queue-alarms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAI9F,OAAO,EAA0B,YAAY,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGpG,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAoB,CAAC;AAE7E;;;GAGG;AACH,MAAM,qBAAqB,GAAG;IAC5B,iBAAiB,EAAE,CAAC;IACpB,iBAAiB,EAAE,CAAC;IACpB,gBAAgB,EAAE,gBAAgB,CAAC,aAAa;CACjD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,4BAA4B,CAC1C,KAAa,EACb,MAAoC,EACpC,OAA0B;IAE1B,IAAI,MAAM,EAAE,OAAO,KAAK,KAAK;QAAE,OAAO,EAAE,CAAC;IAEzC,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAC,GAAG,EAAqB,EAAE;QACzD,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,UAAU,KAAK,KAAK;YAAE,OAAO,EAAE,CAAC;QACpC,IAAI,UAAU,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,CAAC;QAEpE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,QAAQ,KAAK,SAAS,IAAI,UAAU,EAAE,SAAS,KAAK,SAAS,EAAE,CAAC;YAClE,MAAM,IAAI,KAAK,CACb,UAAU,KAAK,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,+CAA+C;gBAClF,8EAA8E;gBAC9E,uBAAuB,GAAG,wBAAwB,CACrD,CAAC;QACJ,CAAC;QAED,MAAM,GAAG,GAAG,kBAAkB,CAC5B,UAAU;QACV,yFAAyF;QACzF,QAAQ,IAAI,EAAE,GAAG,qBAAqB,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,IAAI,CAAC,EAAE,CAChF,CAAC;QACF,OAAO;YACL;gBACE,GAAG;gBACH,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,MAAM,EAAE,mBAAmB,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;gBACvC,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,kBAAkB,EAAE,kBAAkB,CAAC,sBAAsB;gBAC7D,iBAAiB,EAAE,GAAG,CAAC,iBAAiB;gBACxC,iBAAiB,EAAE,GAAG,CAAC,iBAAiB;gBACxC,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;gBACtC,WAAW,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC;aACtD;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAiB,EACjB,EAAU,EACV,KAAa,EACb,MAA4C,EAC5C,YAA8C,EAC9C,OAA0B;IAE1B,MAAM,WAAW,GACf,MAAM,KAAK,KAAK,IAAI,MAAM,EAAE,OAAO,KAAK,KAAK;QAC3C,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,4BAA4B,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAEzD,OAAO,YAAY,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,GAAG,WAAW,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;AAC9D,CAAC"}