@condensetech/cdk-monitoring
v0.1.1
Published
AWS CDK constructs for alarm and notification monitoring: metric alarms via Aspects, severity-based audience routing, Discord + Microsoft Teams notification pipelines, and EventBridge rules for non-metric state changes.
Readme
@condensetech/cdk-monitoring
AWS CDK constructs for alarm-driven monitoring and notifications.
- Metric alarms via CDK Aspects — automatically discovers Fargate services, ALBs, target groups, ElastiCache clusters, RDS clusters and instances in a stack and attaches alarms with sensible defaults.
- Severity-based audience routing —
warningalarms go to the dev SNS topic only;criticalalarms go to both dev and management topics. One subscription per audience (e.g. Discord for dev, Microsoft Teams for management). - Discord + Microsoft Teams pipelines — ready-made
NotificationStackwith an inline Node.js Lambda that posts CloudWatch alarms and EventBridge events to Discord, plus an optional AWS Chatbot Microsoft Teams configuration. - EventBridge rules for state changes — helpers for ECS task failures, ECS deployment errors, and RDS cluster events published to the same SNS topics.
This library is intentionally alarm-only: no CloudWatch Dashboards are created. Operators read metrics from the AWS console on demand and act on alarms delivered to chat channels.
Installation
pnpm add @condensetech/cdk-monitoringPeer dependencies: aws-cdk-lib ^2.240.0, constructs ^10.5.0.
Quick start
import { App, Stack } from 'aws-cdk-lib';
import {
MonitoringFacade,
NotificationStack,
EventRulesStack,
} from '@condensetech/cdk-monitoring';
const app = new App();
// 1. Shared notification pipeline (one per environment).
const notifications = new NotificationStack(app, 'MyApp-Dev-Notifications', {
namePrefix: 'myapp-dev',
discordWebhookSecretName: 'myapp/monitoring/discord-webhook-dev',
// teamsChannel: { teamId, tenantId, channelId } // optional
});
// 2. Attach MonitoringFacade to each application stack you want covered.
const appStack = new MyAppStack(app, 'MyApp-Dev-Core', { /* ... */ });
new MonitoringFacade(appStack, {
environmentName: 'myapp-dev',
devTopicArn: notifications.devTopic.topicArn,
// managementTopicArn: notifications.managementTopic.topicArn,
});
// 3. Optional: EventBridge rules for non-metric state changes.
new EventRulesStack(app, 'MyApp-Dev-EventRules', {
devTopic: notifications.devTopic,
ecsCluster: appStack.cluster,
rdsCluster: appStack.database,
});MonitoringFacade
MonitoringFacade(scope, props) registers six CDK Aspects on the given stack. The aspects scan the stack at synth time and create alarms for any resource of a supported type they find:
| Aspect | Resource type | Alarms (default) |
|---|---|---|
| FargateServiceMonitoringAspect | ecs.FargateService | CPU (Average 90%), Memory (Maximum 90%) |
| ApplicationLoadBalancerMonitoringAspect | elbv2.ApplicationLoadBalancer | RedirectUrlLimit, RejectedConnections, TargetConnectionErrors, Target5xx |
| TargetGroupMonitoringAspect | elbv2.ApplicationTargetGroup | MinHealthyHosts (treat-missing BREACHING) |
| CacheClusterMonitoringAspect | elasticache.CfnCacheCluster | CPU per node, Connections per node, Memory, EngineCPU |
| RdsClusterMonitoringAspect | rds.DatabaseCluster | CPU, ReadLatency, EBS Balance (skipped on Aurora) |
| RdsInstanceMonitoringAspect | rds.DatabaseInstance | CPU, ReadLatency, EBS Balance |
Per-resource overrides are available via configFargateService(), configRdsCluster(), etc.
Severity-based routing
Every alarm carries a severity of warning (default) or critical. The facade wires SNS actions accordingly:
warning→devTopiconlycritical→devTopicANDmanagementTopic(if provided)
Set minSeverity: 'critical' on the facade to skip the creation of warning-level alarms altogether (saves ~$0.10/month per skipped alarm).
Alarm naming
Set environmentName to prepend an env prefix to every alarm name and description, so Discord notifications immediately show which deployment fired the alarm:
ALARM: myapp-dev-FargateService-MemoryUtilizationAlarm-core-service
[myapp-dev] Memory Utilization high on core-serviceNotificationStack
Creates:
- Two SNS topics:
<namePrefix>-dev-notificationsand<namePrefix>-management-notifications - A Node.js Lambda (
aws-lambda-nodejs) subscribed to the dev topic that formats CloudWatch alarm and EventBridge event messages as Discord embeds and POSTs to the webhook stored in Secrets Manager - An SQS dead-letter queue for the Lambda
- An AWS Chatbot
MicrosoftTeamsChannelConfigurationsubscribed to the management topic (whenteamsChannelis provided) - SSM parameters
<ssmParameterPrefix>/dev-topic-arnand/management-topic-arnso other repos can look up the topic ARNs viaStringParameter.valueForStringParameterwithout CloudFormation cross-stack imports
The Discord webhook Secrets Manager secret must be created separately (the stack references it by name). Value can be a plain URL or {"url": "..."} JSON.
EventRulesStack
Helpers and a ready-made stack for EventBridge rules that publish non-metric events to the same SNS pipeline:
addEcsTaskFailureRule(scope, id, { cluster, devTopic, ... })— ECS task STOPPED with a stop code other than normal scheduler/user stopsaddEcsDeploymentFailureRule(scope, id, { cluster, devTopic, ... })— ECS deploymenteventType=ERRORaddRdsClusterEventRule(scope, id, { cluster, devTopic, ... })— RDS clusterfailover,failure,maintenanceevents
License
MIT — see LICENSE.
