Skip to content

Software Engineer at Heydoc

Attach Visual Studio Code debugger to SAM (Serverless Application Model) local endpoint

Hi! I am not going to go through the basics of debugging or AWS SAM framework. At this point you are most likely familiar with those β€” otherwise, you would’ve not landed on this page. I am going to share with you how to attach Visual Studio Code debugger to local endpoint served by AWS SAM (Serverless Application Model). Let’s start with a simple server-less example app.

.
β”œβ”€β”€ src
β”‚   └── index.js
└── template.yaml
# template.yaml

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31

Resources:
  RandomNumber:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: index.handler
      Runtime: nodejs10.x
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /api
            Method: get
const getRandomNumber = () => Math.ceil(Math.random() * 10);

module.exports.handler = async () => ({
  statusCode: 200,
  body: {
    randomNumber: getRandomNumber()
  }
});

And to spin it up on a local endpoint using SAM CLI we have to…

sam local start-api

As you can see we built this sophisticated server-less program that each time when we hit http://127.0.0.1:3000/api with a GET request gives us a random number between 1 and 10. Maybe it isn’t a million dollars idea but should do the job as an example for this article.

Random number generator built using AWS SAM framework

Attach Visual Studio Code debugger to SAM local endpoint #

A debugger is my favourite way of stepping through the logic of a codebase. Some time ago I used to use mainly the one built into Google Chrome developer tools but nowadays I rarely use anything else than Visual Studio Code. Luckily, SAM CLI allows us to launch our local API in a debug mode.

sam local start-api -d 5858

From now on, whenever we execute a request to our endpoint, the program will pause to let us hook up into its internals. To do so using Visual Studio Code we need a bit of a config inside .vscode/launch.json file β€” I got you covered!

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "attach",
      "name": "Attach to SAM CLI",
      "address": "localhost",
      "port": 5858,
      "localRoot": "${workspaceRoot}/src",
      "remoteRoot": "/var/task",
      "protocol": "inspector",
      "stopOnEntry": false
    }
  ]
}

Now, as long as your API is running in debug mode you can attach your IDE to your program by hitting play button on debugger tab or by pressing F5. Add a breakpoint where you want your execution to pause and voila!

Attach Viusal Studio Code debugger to JavaScript file

Debug TypeScript codebase #

Nowadays, I very rarely write JavaScript that doesn’t go through any additional transformation before hitting production. TypeScript is my preferred way of writing JavaScript code and even though the debugging setup is a tiny bit more complicated, it is possible and works like a charm. Let’s recreate our program using TypeScript.

.
β”œβ”€β”€ dist
β”‚   β”œβ”€β”€ index.js
β”‚   └── index.js.map
β”œβ”€β”€ src
β”‚   └── index.ts
β”œβ”€β”€ template.yaml
└── yarn.lock
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31

Resources:
  RandomNumber:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: dist/
      Handler: index.handler
      Runtime: nodejs10.x
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /api
            Method: get

const getBody = (message: string) => JSON.stringify({ message });

interface IEvent {
  body: string;
}

module.exports.handler = async (event: IEvent) => {
  const { message } = JSON.parse(event.body);

  return {
    statusCode: 200,
    body: getBody(message)
  };
};
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "attach",
      "name": "Attach to SAM CLI",
      "address": "localhost",
      "port": 5858,
      "localRoot": "${workspaceRoot}/dist",
      "outFiles": ["${workspaceFolder}/dist/**/*.js"],
      "remoteRoot": "/var/task",
      "protocol": "inspector",
      "stopOnEntry": false
    }
  ]
}

It really doesn’t matter how you compile your .ts files to .js for this article so I skipped this implementation detail for clarity. Compiled version of our program landed in dist directory and this change has been reflected in CodeUri value inside the template file. Pay attention to index.js.map that lives directly next to the compiled version of a program β€” otherwise, our debugger won’t be able to map compiled code to the one inside src directory. Changes in files tree are reflected in the debugger config file that has been decorated with outFiles property that helps VSCode to identify the location of transpiled files.

Attach Viusal Studio Code debugger to TypeScript file

Happy debugging! The same patterns can be reused for tons of other frameworks and build tools. Hopefully, this quick article helped you out. Bye :-*

Comments

  • B
    Ba Doom

    Hello PaweΕ‚,

    thank you for this article. I am curious - is there a way to attach the debugger permanently? Now i have to manually start debugging in VSC before each request in sent.

    πŸ‘† you can use Markdown here

    Your comment is awaiting moderation. Thanks!
    • Pawel Grzybek
      Pawel Grzybek

      Hi.

      As long as you execute SAM with -d flag if should pause on every single request by itself, There is no action needed from VSCode perspective.

      Hopefully that answers your question.

      πŸ‘† you can use Markdown here

      Your comment is awaiting moderation. Thanks!
    • O
      Olias

      I have the same issue, the SAM instance is set on pause for each request, giving the following message Debugger listening on [::]:5858, and waits until you start the VSCode debugger before resuming execution.
      See this GIF:
      https://docs.aws.amazon.com...

      πŸ‘† you can use Markdown here

      Your comment is awaiting moderation. Thanks!
  • A
    Austin

    Has anyone figured out how to get VS Code's auto attach to work with the SAM CLI?

    πŸ‘† you can use Markdown here

    Your comment is awaiting moderation. Thanks!

Leave a comment

πŸ‘† you can use Markdown here

Your comment is awaiting moderation. Thanks!