Created
October 17, 2023 15:07
-
-
Save julbrs/41d93dd234a5db69ad874101cb2853f1 to your computer and use it in GitHub Desktop.
Setup cloudwatch alarms on SST !
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// name: FunctionsAlarm.ts | |
// can be used with: | |
// new FunctionsAlarm(stack, 'ApiAlarmMain', { | |
// api, | |
// alarmNamePrefix: `API Error`, | |
// }); | |
// | |
// new FunctionsAlarm(stack, 'ApiAlarmMain', { | |
// functions: [cron.jobFunction], | |
// alarmNamePrefix: `Cron Job Error`, | |
// }); | |
import { Api, ApiAuthorizer, Function } from 'sst/constructs'; | |
import { Duration } from 'aws-cdk-lib'; | |
import { Alarm } from 'aws-cdk-lib/aws-cloudwatch'; | |
import { SnsAction } from 'aws-cdk-lib/aws-cloudwatch-actions'; | |
import { Topic } from 'aws-cdk-lib/aws-sns'; | |
import { EmailSubscription } from 'aws-cdk-lib/aws-sns-subscriptions'; | |
import { Construct } from 'constructs'; | |
export interface FunctionsAlarmProps { | |
/** | |
* Function to monitor | |
*/ | |
readonly functions?: Function[]; | |
/** | |
* The SST API to monitor | |
*/ | |
readonly api?: Api<Record<string, ApiAuthorizer>>; | |
/** | |
* The name of the alarm | |
*/ | |
readonly alarmNamePrefix: string; | |
} | |
/** | |
* This construct is responsible to create an alarm for all API Gateway endpoint. | |
*/ | |
export default class FunctionsAlarm extends Construct { | |
constructor(scope: Construct, id: string, props: FunctionsAlarmProps) { | |
super(scope, id); | |
if (props.functions === undefined && props.api === undefined) { | |
throw new Error('You must provide at least one function or an API'); | |
} | |
if (props.functions && props.api) { | |
throw new Error('You must provide either a function or an API, not both'); | |
} | |
if (!process.env.ALERT_EMAIL) { | |
throw new Error('You must provide an ALERT_EMAIL environment variable'); | |
} | |
const alarmTopic = new Topic(scope, `${id}-AlarmTopic`); | |
alarmTopic.addSubscription(new EmailSubscription(process.env.ALERT_EMAIL)); | |
// work on Function array | |
if (props.functions) { | |
for (const func of props.functions) { | |
// create a new alarm based on the metric | |
createAlarm(scope, func, props.alarmNamePrefix, alarmTopic); | |
} | |
} | |
// work on API construct | |
if (props.api) { | |
for (const route of props.api.routes) { | |
const func = props.api.getFunction(route); | |
if (func) { | |
createAlarm(scope, func, props.alarmNamePrefix, alarmTopic, route); | |
} | |
} | |
} | |
} | |
} | |
const createAlarm = ( | |
scope: Construct, | |
func: Function, | |
alarmNamePrefix: string, | |
alarmTopic: Topic, | |
route?: string | |
) => { | |
const alarm = new Alarm(scope, `FunctionAlarm-${func.id}`, { | |
metric: func.metricErrors({ | |
period: Duration.minutes(15), | |
}), | |
alarmName: route ? `${alarmNamePrefix} ${route}` : `${alarmNamePrefix} ${func.id}`, | |
threshold: 5, | |
evaluationPeriods: 1, | |
}); | |
alarm.addAlarmAction(new SnsAction(alarmTopic)); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment