Tracking AWS Lambda errors with Sentry (and CloudFormation)
I enjoy working with Sentry 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:
-
Install Sentry lib:
npm install --save @sentry/serverless
-
Wrap the Lambda handler:
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 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:
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.
(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):
-
Setup the Cloudformation template: add an environment parameter and Sentry DSN parameter
# 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...
-
In Lambda, read from the env vars instead:
Sentry.AWSLambda.init({ dsn: process.env.SENTRY_DSN, environemnt: process.env.LAMBDA_ENVIRONMENT, })
-
When deploying the CloudFormation stack in a CI pipeline, supply
--parameter-overrides
argument toaws cloudformation deploy
:aws cloudformation deploy --template-file template.yml \ --parameter-overrides "LAMBDA_ENVIRONMENT=acc" \ # ... other args & options ...
This should be it 🎉.
Sidenote on AWS Lambda logs & CLI #
Speaking of errors, it turns out one can tail aws logs via a CLI using aws logs
. Plus, there's no need to specify the log stream, which is handy:
# print all log groups
aws logs describe-log-groups
# tail logs for lambda example-lambda since 1 day ago
aws logs tail /aws/lambda/example-lambda --since 1d --follow |
I like to combine aws logs
with grep context lines to search for errors with the surrounding context:
# show all ERROR log messages. For each ERROR msg, show 10 preceding messages
aws logs tail /aws/lambda/example-name --since 1d | grep -B 10 'ERROR'
- ← Previous post: Defining resources conditionally based on environment
- → Next post: Changelog of this blog (meta)
This blog is written by Marcel Krcah, an independent consultant for product-oriented software engineering. If you like what you read, sign up for my newsletter