From 14130330c6b24dedd271e35689a0c5ce1c77cbcf Mon Sep 17 00:00:00 2001 From: tstephen-nhs <231503406+tstephen-nhs@users.noreply.github.com> Date: Fri, 24 Apr 2026 14:10:50 +0000 Subject: [PATCH 1/6] feat: SnsAlarm --- package-lock.json | 33 +++- .../cdkConstructs/src/constructs/SnsAlarm.ts | 157 ++++++++++++++++++ .../tests/constructs/SnsAlarm.test.ts | 103 ++++++++++++ 3 files changed, 285 insertions(+), 8 deletions(-) create mode 100644 packages/cdkConstructs/src/constructs/SnsAlarm.ts create mode 100644 packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts diff --git a/package-lock.json b/package-lock.json index 6e0277be..0d97614e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,7 @@ "requires": true, "packages": { "": { + "name": "eps-cdk-utils", "license": "MIT", "workspaces": [ "packages/cdkConstructs", @@ -5109,7 +5110,9 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "5.0.4", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5932,7 +5935,9 @@ } }, "node_modules/flatted": { - "version": "3.3.3", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, "license": "ISC" }, @@ -6037,7 +6042,9 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.2", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", "dev": true, "license": "MIT", "dependencies": { @@ -6805,7 +6812,9 @@ } }, "node_modules/jest-util/node_modules/picomatch": { - "version": "4.0.3", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -7623,7 +7632,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -8162,7 +8173,9 @@ } }, "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.12", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -8190,7 +8203,9 @@ } }, "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -8734,7 +8749,9 @@ } }, "node_modules/vitest/node_modules/picomatch": { - "version": "4.0.3", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { diff --git a/packages/cdkConstructs/src/constructs/SnsAlarm.ts b/packages/cdkConstructs/src/constructs/SnsAlarm.ts new file mode 100644 index 00000000..9aa08842 --- /dev/null +++ b/packages/cdkConstructs/src/constructs/SnsAlarm.ts @@ -0,0 +1,157 @@ +import {Duration} from "aws-cdk-lib" +import {Construct} from "constructs" +import { + Alarm, + ComparisonOperator, + CreateAlarmOptions, + Metric, + MetricStatConfig, + TreatMissingData, + Unit +} from "aws-cdk-lib/aws-cloudwatch" +import {SnsAction} from "aws-cdk-lib/aws-cloudwatch-actions" +import {ITopic} from "aws-cdk-lib/aws-sns" + +/** + * Alarm definition for SnsAlarm with defaults applied by the construct. + */ +export interface SnsAlarmDefinition + extends Omit { + /** + * The value against which the specified statistic is compared. + * + * @default 1 + */ + readonly threshold?: number + + /** + * The number of periods over which data is compared to the specified threshold. + * + * @default 1 + */ + readonly evaluationPeriods?: number +} + +/** + * Metric stat configuration for SnsAlarm with defaults applied by the construct. + */ +export interface SnsMetricStatConfig extends Omit { + /** + * How many seconds to aggregate over. + * + * @default Duration.minutes(1) + */ + readonly period?: Duration + + /** + * Aggregation function to use. + * + * @default "Sum" + */ + readonly statistic?: string +} + +const toDimensionsMap = ( + dimensions: MetricStatConfig["dimensions"] +): {[dimensionName: string]: string} | undefined => { + if (!dimensions || dimensions.length === 0) { + return undefined + } + + const dimensionMap: {[dimensionName: string]: string} = {} + dimensions.forEach((dimension) => { + dimensionMap[dimension.name] = String(dimension.value) + }) + return dimensionMap +} + +/** + * Constructs a concrete CloudWatch Metric from a MetricStatConfig. + * @see {@link import("aws-cdk-lib/aws-cloudwatch").MetricConfig} for alternate concrete metric configs. + */ +export const metricFromStatConfig = ( + metricStatConfig: MetricStatConfig +): Metric => + new Metric({ + namespace: metricStatConfig.namespace, + metricName: metricStatConfig.metricName, + dimensionsMap: toDimensionsMap(metricStatConfig.dimensions), + statistic: metricStatConfig.statistic, + period: metricStatConfig.period, + unit: metricStatConfig.unitFilter, + account: metricStatConfig.accountOverride ?? metricStatConfig.account, + region: metricStatConfig.regionOverride ?? metricStatConfig.region + }) + +/** + * Configuration for creating a CloudWatch metric alarm with SNS publication construct. + */ +export interface SnsAlarmProps { + + /** Prefix used in the generated CloudWatch alarm name. */ + readonly stackName: string + /** Enables alarm actions when true, disabling notifications when false. */ + readonly enableAlerts: boolean + /** CloudWatch metric and threshold settings for the alarm. */ + readonly alarmDefinition: SnsAlarmDefinition + /** Defines the metric configuration to be monitored by the alarm. */ + readonly metricStatConfig: SnsMetricStatConfig + /** SNS topic that receives alarm, OK, and insufficient data notifications. */ + readonly slackAlertTopic: ITopic +} + +/** + * Creates a single CloudWatch alarm and wires all alarm state changes to an SNS topic. + */ +export class SnsAlarm extends Construct { + alarm: Alarm + + /** + * Creates a CloudWatch alarm and publishes alarm state changes to the provided SNS topic. + * + * @param props Alarm configuration including metric settings, threshold settings, and notification topic. + * @example + * new SnsAlarm(this, 'MyApiErrorAlarm', { + * stackName: 'pfp-prod', + * enableAlerts: true, + * alarmDefinition: { + * alarmDescription: 'API errors detected', + * threshold: 1 + * }, + * metricStatConfig: { + * namespace: 'LambdaLogFilterMetrics', + * metricName: 'ErrorCount' + * }, + * slackAlertTopic + * }) + */ + public constructor(scope: Construct, id: string, props: SnsAlarmProps) { + super(scope, id) + + const generatedAlarmName = props.alarmDefinition.alarmName ?? id + + const alarm = new Alarm(this, `${generatedAlarmName}Alarm`, { + alarmName: `${props.stackName}-${generatedAlarmName}`, + metric: metricFromStatConfig({ + ...props.metricStatConfig, + unitFilter: props.metricStatConfig.unitFilter ?? Unit.COUNT, + statistic: props.metricStatConfig.statistic ?? "Sum", + period: props.metricStatConfig.period ?? Duration.minutes(1) + }), + threshold: props.alarmDefinition.threshold ?? 1, + evaluationPeriods: props.alarmDefinition.evaluationPeriods ?? 1, + comparisonOperator: + props.alarmDefinition.comparisonOperator ?? ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + treatMissingData: props.alarmDefinition.treatMissingData ?? TreatMissingData.NOT_BREACHING, + alarmDescription: props.alarmDefinition.alarmDescription, + actionsEnabled: props.enableAlerts + }) + + const snsAction = new SnsAction(props.slackAlertTopic) + alarm.addAlarmAction(snsAction) + alarm.addOkAction(snsAction) + alarm.addInsufficientDataAction(snsAction) + + this.alarm = alarm + } +} diff --git a/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts b/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts new file mode 100644 index 00000000..34cb7b47 --- /dev/null +++ b/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts @@ -0,0 +1,103 @@ +import {App, Duration, Stack} from "aws-cdk-lib" +import {Template} from "aws-cdk-lib/assertions" +import {ComparisonOperator, Unit} from "aws-cdk-lib/aws-cloudwatch" +import {Topic} from "aws-cdk-lib/aws-sns" +import {describe, expect, it} from "vitest" +import {SnsAlarm} from "../../src/constructs/SnsAlarm" + +const importedSlackTopicArn = "arn:aws:sns:eu-west-2:111111111111:SlackAlertsTopic" + +describe("SnsAlarm construct", () => { + it("applies sane defaults for simple alarm definitions", () => { + const app = new App() + const stack = new Stack(app, "TestStack") + const slackAlertTopic = Topic.fromTopicArn(stack, "SlackAlertsTopic", importedSlackTopicArn) + + const metricAlarm = new SnsAlarm(stack, "SimpleMetricAlarm", { + stackName: "pfp-test-stack", + enableAlerts: true, + alarmDefinition: { + alarmName: "MySimpleAlarm", + alarmDescription: "An alarm for any breach (threshold 1) in a single period" + }, + metricStatConfig: { + namespace: "LambdaLogFilterMetrics", + metricName: "ErrorCount" + }, + slackAlertTopic + }) + + expect(metricAlarm.alarm).toBeDefined() + + const template = Template.fromStack(stack) + template.resourceCountIs("AWS::SNS::Topic", 0) + + template.hasResourceProperties("AWS::CloudWatch::Alarm", { + AlarmName: "pfp-test-stack-MySimpleAlarm", + Namespace: "LambdaLogFilterMetrics", + MetricName: "ErrorCount", + Threshold: 1, + ComparisonOperator: "GreaterThanOrEqualToThreshold", + Unit: "Count", + Statistic: "Sum", + Period: 60, + EvaluationPeriods: 1, + TreatMissingData: "notBreaching", + AlarmDescription: "An alarm for any breach (threshold 1) in a single period", + ActionsEnabled: true + }) + }) + + it("allows overriding threshold, comparison operator, unit and dimensions", () => { + const app = new App() + const stack = new Stack(app, "OverrideStack") + const slackAlertTopic = Topic.fromTopicArn(stack, "SlackAlertsTopic", importedSlackTopicArn) + + const metricAlarm = new SnsAlarm(stack, "OverrideMetricAlarm", { + stackName: "pfp-test-stack", + enableAlerts: false, + alarmDefinition: { + alarmName: "MyOverrideAlarm", + alarmDescription: "Override alarm", + threshold: 250, + comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD, + evaluationPeriods: 1 + }, + metricStatConfig: { + namespace: "CustomNamespace", + metricName: "Latency", + unitFilter: Unit.MILLISECONDS, + dimensions: [ + { + name: "FunctionName", + value: "my-function" + } + ], + period: Duration.minutes(1), + statistic: "Sum" + }, + slackAlertTopic + }) + + expect(metricAlarm.alarm).toBeDefined() + + const template = Template.fromStack(stack) + + template.hasResourceProperties("AWS::CloudWatch::Alarm", { + AlarmName: "pfp-test-stack-MyOverrideAlarm", + Namespace: "CustomNamespace", + MetricName: "Latency", + Threshold: 250, + ComparisonOperator: "GreaterThanThreshold", + Unit: "Milliseconds", + Dimensions: [ + { + Name: "FunctionName", + Value: "my-function" + } + ], + AlarmDescription: "Override alarm", + ActionsEnabled: false + }) + }) +}) From bd1aa48b627295faa8e8a7075e9f329d1a705445 Mon Sep 17 00:00:00 2001 From: tstephen-nhs <231503406+tstephen-nhs@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:54:11 +0100 Subject: [PATCH 2/6] fix: use modify standard for construct Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- packages/cdkConstructs/src/constructs/SnsAlarm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cdkConstructs/src/constructs/SnsAlarm.ts b/packages/cdkConstructs/src/constructs/SnsAlarm.ts index 9aa08842..34e246a9 100644 --- a/packages/cdkConstructs/src/constructs/SnsAlarm.ts +++ b/packages/cdkConstructs/src/constructs/SnsAlarm.ts @@ -104,7 +104,7 @@ export interface SnsAlarmProps { * Creates a single CloudWatch alarm and wires all alarm state changes to an SNS topic. */ export class SnsAlarm extends Construct { - alarm: Alarm + public readonly alarm: Alarm /** * Creates a CloudWatch alarm and publishes alarm state changes to the provided SNS topic. From e256d1a6e9504fad38438cd4ca38bab415bfdcdf Mon Sep 17 00:00:00 2001 From: tstephen-nhs <231503406+tstephen-nhs@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:01:43 +0000 Subject: [PATCH 3/6] fix: spread override properties, reexport sns alarm --- .../cdkConstructs/src/constructs/SnsAlarm.ts | 18 ++++++++++++------ packages/cdkConstructs/src/index.ts | 1 + .../tests/constructs/SnsAlarm.test.ts | 4 +++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/cdkConstructs/src/constructs/SnsAlarm.ts b/packages/cdkConstructs/src/constructs/SnsAlarm.ts index 34e246a9..9fcae008 100644 --- a/packages/cdkConstructs/src/constructs/SnsAlarm.ts +++ b/packages/cdkConstructs/src/constructs/SnsAlarm.ts @@ -129,8 +129,16 @@ export class SnsAlarm extends Construct { super(scope, id) const generatedAlarmName = props.alarmDefinition.alarmName ?? id + const { + threshold, + evaluationPeriods, + comparisonOperator, + treatMissingData, + ...supportedAlarmDefinitionProps + } = props.alarmDefinition const alarm = new Alarm(this, `${generatedAlarmName}Alarm`, { + ...supportedAlarmDefinitionProps, alarmName: `${props.stackName}-${generatedAlarmName}`, metric: metricFromStatConfig({ ...props.metricStatConfig, @@ -138,12 +146,10 @@ export class SnsAlarm extends Construct { statistic: props.metricStatConfig.statistic ?? "Sum", period: props.metricStatConfig.period ?? Duration.minutes(1) }), - threshold: props.alarmDefinition.threshold ?? 1, - evaluationPeriods: props.alarmDefinition.evaluationPeriods ?? 1, - comparisonOperator: - props.alarmDefinition.comparisonOperator ?? ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, - treatMissingData: props.alarmDefinition.treatMissingData ?? TreatMissingData.NOT_BREACHING, - alarmDescription: props.alarmDefinition.alarmDescription, + threshold: threshold ?? 1, + evaluationPeriods: evaluationPeriods ?? 1, + comparisonOperator: comparisonOperator ?? ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + treatMissingData: treatMissingData ?? TreatMissingData.NOT_BREACHING, actionsEnabled: props.enableAlerts }) diff --git a/packages/cdkConstructs/src/index.ts b/packages/cdkConstructs/src/index.ts index 39dc8095..9eabc6aa 100644 --- a/packages/cdkConstructs/src/index.ts +++ b/packages/cdkConstructs/src/index.ts @@ -7,6 +7,7 @@ export * from "./constructs/RestApiGateway/accessLogFormat.js" export * from "./constructs/RestApiGateway/LambdaEndpoint.js" export * from "./constructs/RestApiGateway/StateMachineEndpoint.js" export * from "./constructs/PythonLambdaFunction.js" +export * from "./constructs/SnsAlarm.js" export * from "./constructs/SsmParametersConstruct.js" export * from "./apps/createApp.js" export * from "./config/index.js" diff --git a/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts b/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts index 34cb7b47..906ccca6 100644 --- a/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts +++ b/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts @@ -61,7 +61,8 @@ describe("SnsAlarm construct", () => { alarmDescription: "Override alarm", threshold: 250, comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD, - evaluationPeriods: 1 + evaluationPeriods: 3, + datapointsToAlarm: 2 }, metricStatConfig: { namespace: "CustomNamespace", @@ -89,6 +90,7 @@ describe("SnsAlarm construct", () => { MetricName: "Latency", Threshold: 250, ComparisonOperator: "GreaterThanThreshold", + DatapointsToAlarm: 2, Unit: "Milliseconds", Dimensions: [ { From 5b11d7fc128a79f7c551f46e75c7aceb4622f7d0 Mon Sep 17 00:00:00 2001 From: tstephen-nhs <231503406+tstephen-nhs@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:04:42 +0000 Subject: [PATCH 4/6] fix: generalise topic name --- packages/cdkConstructs/src/constructs/SnsAlarm.ts | 6 +++--- packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cdkConstructs/src/constructs/SnsAlarm.ts b/packages/cdkConstructs/src/constructs/SnsAlarm.ts index 9fcae008..e4a63758 100644 --- a/packages/cdkConstructs/src/constructs/SnsAlarm.ts +++ b/packages/cdkConstructs/src/constructs/SnsAlarm.ts @@ -96,8 +96,8 @@ export interface SnsAlarmProps { readonly alarmDefinition: SnsAlarmDefinition /** Defines the metric configuration to be monitored by the alarm. */ readonly metricStatConfig: SnsMetricStatConfig - /** SNS topic that receives alarm, OK, and insufficient data notifications. */ - readonly slackAlertTopic: ITopic + /** SNS topic that receives alarm, OK, and insufficient data notifications. Common example is for Slack alerts. */ + readonly snsTopic: ITopic } /** @@ -153,7 +153,7 @@ export class SnsAlarm extends Construct { actionsEnabled: props.enableAlerts }) - const snsAction = new SnsAction(props.slackAlertTopic) + const snsAction = new SnsAction(props.snsTopic) alarm.addAlarmAction(snsAction) alarm.addOkAction(snsAction) alarm.addInsufficientDataAction(snsAction) diff --git a/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts b/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts index 906ccca6..8b5aa59e 100644 --- a/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts +++ b/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts @@ -24,7 +24,7 @@ describe("SnsAlarm construct", () => { namespace: "LambdaLogFilterMetrics", metricName: "ErrorCount" }, - slackAlertTopic + snsTopic: slackAlertTopic }) expect(metricAlarm.alarm).toBeDefined() @@ -77,7 +77,7 @@ describe("SnsAlarm construct", () => { period: Duration.minutes(1), statistic: "Sum" }, - slackAlertTopic + snsTopic: slackAlertTopic }) expect(metricAlarm.alarm).toBeDefined() From 34eb255dcb763f5f6dca5e4f8c2b4d58da501e3a Mon Sep 17 00:00:00 2001 From: tstephen-nhs <231503406+tstephen-nhs@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:11:54 +0000 Subject: [PATCH 5/6] test: bound actions --- packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts b/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts index 8b5aa59e..897ec140 100644 --- a/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts +++ b/packages/cdkConstructs/tests/constructs/SnsAlarm.test.ts @@ -44,6 +44,9 @@ describe("SnsAlarm construct", () => { EvaluationPeriods: 1, TreatMissingData: "notBreaching", AlarmDescription: "An alarm for any breach (threshold 1) in a single period", + AlarmActions: [importedSlackTopicArn], + OKActions: [importedSlackTopicArn], + InsufficientDataActions: [importedSlackTopicArn], ActionsEnabled: true }) }) @@ -99,6 +102,9 @@ describe("SnsAlarm construct", () => { } ], AlarmDescription: "Override alarm", + AlarmActions: [importedSlackTopicArn], + OKActions: [importedSlackTopicArn], + InsufficientDataActions: [importedSlackTopicArn], ActionsEnabled: false }) }) From 0d439a03184865ad52182f915e9bc1f6e0dce853 Mon Sep 17 00:00:00 2001 From: tstephen-nhs <231503406+tstephen-nhs@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:26:50 +0000 Subject: [PATCH 6/6] fix: generalise topic name --- packages/cdkConstructs/src/constructs/SnsAlarm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cdkConstructs/src/constructs/SnsAlarm.ts b/packages/cdkConstructs/src/constructs/SnsAlarm.ts index e4a63758..5f042039 100644 --- a/packages/cdkConstructs/src/constructs/SnsAlarm.ts +++ b/packages/cdkConstructs/src/constructs/SnsAlarm.ts @@ -122,7 +122,7 @@ export class SnsAlarm extends Construct { * namespace: 'LambdaLogFilterMetrics', * metricName: 'ErrorCount' * }, - * slackAlertTopic + * snsTopic: slackAlertTopic * }) */ public constructor(scope: Construct, id: string, props: SnsAlarmProps) {