UPDATE: For lambdas, I have moved towards [[lumigo might help with lambda observability|lumigo]].
I enjoy working with [Sentry](https://sentry.io/organizations/sungevity/issues/) for error tracking: I have a real-time overview of errors, I set up various alerts, and I use it in both backend and frontend systems. Now, how to setup Sentry for AWS Lambda that is provisioned by AWS CloudFormation?
There are currently two ways to do it: wrapping up the Lambda handler or using AWS Lambda layers. I focus on the Lambda handler here.
## Step 1: Wrapping up handler
Following the Sentry docs on integrating with AWS Lambda, this step was straightforward. Here's an example of a wrapped Node handler:
1. Install Sentry lib:
```bash
npm install --save @sentry/serverless
```
2. Wrap the Lambda handler:
```typescript
const Sentry = require("@sentry/serverless")
Sentry.AWSLambda.init({
dsn: "<Your Sentry DSN>",
// ...
})
exports.handler = Sentry.AWSLambda.wrapHandler(async (event, context) => {
// Your handler code
})
```
In the current version of the library (6.2.3), I had to [tweak the setup a bit](https://github.com/getsentry/sentry-javascript/issues/2984#issuecomment-805857077) to make it work with WebPack and Typescript.
## Step 2: Setting up CloudFormation
Now, Sentry supports monitoring errors per _environment_, such as dev, acceptance, or production. I like that because I have more control over errors in different environments. The environment is set up in the Lambda itself:
```typescript
Sentry.AWSLambda.init({
dsn: "<Your Sentry DSN>",
environemnt: "acceptnace", // <--- here we supply the lambda environment
})
```
Now, how to supply the lambda environment using CloudFormation? It turns out, this can be achieved with [parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html).
(In the steps below, I also use AWS Parameter Store to fetch the Sentry DSN instead of having the DSN hardcoded in the Sentry init):
1. Setup the Cloudformation template: add an environment parameter and Sentry DSN parameter
```yaml
# content of template.yml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
# here we define that the CloudFormation stack accepts environment parameter
LambdaEnvironment:
Type: String
AllowedValues:
- dev
- acc
- prod
# here we fetch the sentry URL from SSM Parameter store
SentryDSN:
Type: AWS::SSM::Parameter::Value<String>
Default: '/<your-path-to-sentry-dsn-ssm-parameter>'
Resources:
ExampleLambda:
Type: AWS::Serverless::Function
Properties:
Environment:
# here we supply sentry dsn & lambda environment to lambda
Variables:
SENTRY_DSN: !Ref SentryDSN
LAMBDA_ENVIRONMENT: !Ref LambdaEnvironment
Policies:
# we need to allow reads from SSM parameter store
- SSMParameterReadPolicy:
ParameterName: '/<your-path-to-sentry-dsn-ssm-parameter>'
#CodeUri, Events, etc...
```
2. In Lambda, read from the env vars instead:
```typescript
Sentry.AWSLambda.init({
dsn: process.env.SENTRY_DSN,
environemnt: process.env.LAMBDA_ENVIRONMENT,
})
```
3. When deploying the CloudFormation stack in a CI pipeline, supply `--parameter-overrides` argument to `aws cloudformation deploy`:
```bash
aws cloudformation deploy --template-file template.yml \
--parameter-overrides "LAMBDA_ENVIRONMENT=acc" \
# ... other args & options ...
```
This should be it 🎉.