Effortless Debugging: AWS CDK TypeScript Projects in VSCode

ianbrumby

Ian

Posted on October 27, 2024

Effortless Debugging: AWS CDK TypeScript Projects in VSCode

Debugging Lambda functions should be easy, right? You want to debug as you develop, using a standard editor (VSCode), a popular IaC framework (AWS CDK), and a widely adopted language (TypeScript).

But it is never quite that easy.

One of the main challenges to wider serverless adoption is the developer experience itself. Setting up an effective debugging environment for Lambda functions can be challenging, especially with the variety of tools, frameworks, and configurations available.

If you're using the same stack as I am, this guide will help you set up a smooth, flexible debugging environment so you can iterate through Lambda functions like a pro.

Introduction

The code for this article can be found here:

https://github.com/Crockwell-Solutions/cdk-lambda-debugger

The starter project provides a CDK configuration with an example resource stack (API Gateway -> Lambda -> SQS). The Lambda function is ready for debugging using both AWS SAM and Lambda Live Debugger. With this setup, you can iterate quickly through Lambda changes without any deployment delays.

Debugging Goals

When I built this, I wanted to simplify Lambda function debugging for a better developer experience. My main requirements were:

  • Quick debugging (<5 seconds): Debugging has got to be quick. I don’t want to run cdk synth every time I debug: Within a large project with multiple stacks and functions, this takes too long.
  • No deployment or hot-swap requirement: I want to debug without deploying each time.
  • Support for ephemeral environment: Within a team, I need the setup to support multiple developer environments. I want it to work with SSO and I don't want to commit local environment variables.
  • Local debugging with remote resources: I don't want to emulate resources locally, just the Lambda runtime.

This makes things a little trickier. There are plenty of options out there, but I really just needed a starter project with everything configured. I couldn't find one, so I've made one.

How it works

I want the most flexible developer experience, so the sample project uses two different debugging options.

  1. Run function locally, debug locally: Using AWS SAM
  2. Run function remotely, debug locally: Using Lambda Live Debugger

There is value in having both options available within a project as the SAM setup provides a bit more flexibility during early development for payloads and environment variables. Lambda Live Debugger provides a more representative runtime environment once you have your Lambda function is slightly more mature.

Getting Started

To get started with the sample project, clone the sample project and follow the installation instruction in the README.

After deployment, configure the required environment variables in a local.env.json file. Here’s an example of what that file might look like:

{
  "SQS_QUEUE_URL": "https://sqs.region.amazonaws.com/123456789012/LambdaDebuggerQueue"
}
Enter fullscreen mode Exit fullscreen mode

This file isn’t committed to version control, so each developer can set their own local environment variables. The local.env.json file is referenced from launch.json in VSCode using the SAM CLI argument --container-env-vars, which does then allow for committing and sharing of the launch.json.

{
  "type": "aws-sam",
  "request": "direct-invoke",
  "name": "Lambda Function - SAM Debugger",
  "preLaunchTask": "Build",
  "invokeTarget": {
    "target": "code",
    "architecture": "arm64",
    "projectRoot": "dist",
    "lambdaHandler": "lambda-debugging-function.handler"
  },
  "aws": {
    "region": "region"
  },
  "lambda": {
    "runtime": "nodejs20.x",
    "payload": {
      "path": "${workspaceFolder}/test/test-payload.json"
    }
  },
  "sam": {
    "localArguments": [
      "--container-env-vars",
      "${workspaceFolder}/local.env.json"
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

The project includes a reusable CustomLambda construct based on the CDK NodejsFunction, bundling with ESBuild and including Lambda Powertools. This bundling is handled as a preLaunchTask in launch.json, avoiding the need to perform a cdk synth. This saves crucial seconds when initiating the debug run.

AWS SAM Debugging

This uses AWS SAM to invoke the Lambda function locally. Select Lambda Function - SAM Debugger from the Run and Debug menu in VSCode and hit F5. You should see the logging output.

The debugger launch configuration triggers a build phase to bundle the code with ESBuild. Bundled code is saved to the dist folder and run locally, removing the need to synth the CDK project. You can set breakpoints in src/lambda-debugging-function.ts, and the debugger will respect source maps to link to the original code.

Debugging with AWS SAM

Lambda Live Debugging

Lambda Live Debugger is an alternative debugging option and offers the added benefit of validating permissions set up in CDK by running the Lambda functions remotely. This uses the Lambda Live Debugger project led by the industry hero Marko at Serverless Life.

  1. Deploy Lambda Live Debugger resources to your AWS account with npx lld.
  2. Set any custom debugger options in lldebugger.config.ts.
  3. In VSCode, select Lambda Function - Lambda Live Debugger from the Run and Debug menu, then press F5.

Lambda Live Debugger will work its magic and deploy out the required resources to your account. Now, to initiate the debug environment, you need to invoke the remote Lambda function. For example, you can add your breakpoint to your local code in src/lambda-debugging-function.ts and then invoke the Lambda function through the API with a call such as:

curl --request POST --header "Content-Type: application/json" --data '{"message": "This is a test message"}' https://xxxxxxxx.execute-api.eu-west-1.amazonaws.com/api/data
Enter fullscreen mode Exit fullscreen mode

Debugging with Lambda Live Debugger

In case of code changes, Lambda Live Debugger automatically reloads the updated code without the need to redeploy or restart the debugger. Magic!

When you’re done, remove the debugger resources with npx lld -r.

Wrapping Up

This is still an evolving area, new tools and best practice changes all the time.

I initially used Serverless Framework (v3) for debugging, but with its deprecation and the new signup requirement in v4, I’ve moved to the setup in this article. Running Lambda functions locally always risks slight discrepancies with deployed environments (especially in terms of permissions), but this approach with AWS SAM and Lambda Live Debugger balances speed with reliability.

About Me

I’m Ian, an AWS Serverless Specialist and AWS Certified Cloud Architect based in the UK. I work as an independent consultant, having worked across multiple sectors, with a passion for Aviation.

Let's connect on linkedIn, or find out more about my work at Crockwell Solutions

💖 💪 🙅 🚩
ianbrumby
Ian

Posted on October 27, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related