Debugging lambda locally using cdk not sam

Viewed 2870

AWS CDK provides great features for developers. Using CDK deveolper can manage not only total infrastructure but also security, codepipeline, ...

However I recently struggling something. I used to debug lambda using SAM for local debugging. I know how to set up CDK environment, and debug CDK application itself. But I can't figure out how to debug lambda application inside CDK.

Can anyone help me?

4 Answers

As of 4/29/2021, there's an additional option for debugging CDK apps via SAM. It's in preview but this blog post covers it : https://aws.amazon.com/blogs/compute/better-together-aws-sam-and-aws-cdk/.

Basically, install the AWS CLI and AWS CDK. The install the SAM CLI - beta, available here : https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-cdk-getting-started.html.

Then you can run command's like:

sam-beta-cdk build sam-beta-cdk local invoke sam-beta-cdk local invoke start-api and even emulate the Lambda service with sam-beta-cdk local start-lambda

You can use SAM and CDK together as described here. In particular:

  1. Run your AWS CDK app and create a AWS CloudFormation template

    cdk synth --no-staging > template.yaml

  2. Find the logical ID for your Lambda function in template.yaml. It will look like MyFunction12345678, where 12345678 represents an 8-character unique ID that the AWS CDK generates for all resources. The line right after it should look like: Type: AWS::Lambda::Function

  3. Run the function by executing:

    sam local invoke MyFunction12345678 --no-event

if you are using VSCode, you can set up a launch action to run the current file in node to test it locally. All you need to do is hit F5 on the file you want to test.

You will need to add the following at the end of your handler files so that when executed in node the handler gets executed:

if (process.env.NODE_ENV === "development" && process.argv.includes(__filename)) {
  // Exercise the Lambda handler with a mock API Gateway event object.
  handler(({
    pathParameters: {
      param1: "test",
      param2: "code",
    },
  } as unknown) as APIGatewayProxyEvent)
    .then((response) => {
      console.log(JSON.stringify(response, null, 2));
      return response;
    })
    .catch((err: any) => console.error(err));
}

Add this to your launch configurations in your .vscode/launch.json:

  "configurations": [
    {
      "name": "Current TS File",
      "type": "node",
      "request": "launch",
      "args": ["${relativeFile}", "-p", "${workspaceFolder}/tsconfig.json"],
      "runtimeArgs": ["-r", "ts-node/register", "-r", "tsconfig-paths/register", "--nolazy"],
      "cwd": "${workspaceRoot}",
      "internalConsoleOptions": "openOnSessionStart",
      "envFile": "${workspaceFolder}/.env",
      "smartStep": true,
      "skipFiles": ["<node_internals>/**", "node_modules/**"]
    },

The ts-node and tsconfig-paths are only needed if using Typescript. You must add those with npm i -D ts-node tsconfig-paths if you dont already have them.

Before you run any of the sam local commands with a AWS CDK application, you must run cdk synth.

When running sam local invoke you need the function construct identifier that you want to invoke, and the path to your synthesized AWS CloudFormation template. If your application uses nested stacks, to resolve naming conflicts, you also need the stack name where the function is defined.

# Invoke the function FUNCTION_IDENTIFIER declared in the stack STACK_NAME
sam local invoke [OPTIONS] [STACK_NAME/FUNCTION_IDENTIFIER]

# Start all APIs declared in the AWS CDK application
sam local start-api -t ./cdk.out/CdkSamExampleStack.template.json [OPTIONS]

# Start a local endpoint that emulates AWS Lambda
sam local start-lambda -t ./cdk.out/CdkSamExampleStack.template.json [OPTIONS]
Related