AWS Lambda - Test and Debug Locally in Visual Studio Code

aws
lambda
docker
A tutorial on testing and debugging AWS Lambda function from Visual Studio Code.
Published

March 16, 2022

About

This post is about running, and debugging AWS Lambda function locally from Visual Studio Code environment and it extensions AWS Toolkit.

Environment Details

  • Python = 3.8.x
  • WSL version = 2
  • WSL Ubuntu version = 20.04
  • Docker Engine version = 20.10.12
  • Docker Desktop version = 4.4.4
  • Host OS = Windows 10
  • VSCode version = 1.65
  • SAM CLI version = 1.40.1

Sample Application

For this post we will use a simple hello world application as our focus is on debugging. We will use AWS SAM CLI to create our application. You can follow the steps provided in tutorial AWS SAM Developer Guide>Getting started with AWS SAM to create this application.

From the provided link (SAM Developer Guide): This application implements a basic API backend. It consists of an Amazon API Gateway endpoint and an AWS Lambda function. When you send a GET request to the API Gateway endpoint, the Lambda function is invoked. This function returns a hello world message.

The following diagram shows the components of this application:

sam-getting-started-hello-world

To initialize a serverless app use command

sam init

Complete the SAM initialization setup steps

PS C:\MyWorkspace\gitrepos\2022-03-16-lambda-debug> sam init

You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.

Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1

Choose an AWS Quick Start application template
        1 - Hello World Example
        2 - Multi-step workflow
        3 - Serverless API
        4 - Scheduled task
        5 - Standalone function
        6 - Data processing
        7 - Infrastructure event management
        8 - Machine Learning
Template: 1

 Use the most popular runtime and package type? (Python and zip) [y/N]: y

Project name [sam-app]:

Cloning from https://github.com/aws/aws-sam-cli-app-templates (process may take a moment)

    -----------------------
    Generating application:
    -----------------------
    Name: sam-app
    Runtime: python3.9
    Architectures: x86_64
    Dependency Manager: pip
    Application Template: hello-world
    Output Directory: .

    Next steps can be found in the README file at ./sam-app/README.md


    Commands you can use next
    =========================
    [*] Create pipeline: cd sam-app && sam pipeline init --bootstrap
    [*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch

Once the application is initialized the project structure will look like this

sam-app/
   ├── README.md
   ├── events/
   │   └── event.json
   ├── hello_world/
   │   ├── __init__.py
   │   ├── app.py            #Contains your AWS Lambda handler logic.
   │   └── requirements.txt  #Contains any Python dependencies the application requires, used for sam build
   ├── template.yaml         #Contains the AWS SAM template defining your application's AWS resources.
   └── tests/
       └── unit/
           ├── __init__.py
           └── test_handler.py

There are three especially important files:

  • template.yaml: Contains the AWS SAM template that defines your application’s AWS resources.
  • hello_world/app.py: Contains your actual Lambda handler logic.
  • hello_world/requirements.txt: Contains any Python dependencies that the application requires, and is used for sam build.

Follow the instructions from the tutorial to build, test, and deploy the application.

All the code used for this post can be obtained from the GitHub repository hassaanbinaslam/2022-03-16-lambda-debug

SAM Project Directory

  • SAM CLI
    • After project initialization from sam init make sure that you move to project root folder
    • Project root folder is the one that contain template.yaml defining application AWS resources. In this app case project root folder is sam-app/
    • All the subsequest commands including project sam build, sam deploy, invoke and test lambda should be done from project root folder
  • VSCode
    • When you open the project make sure that your project root directory is pointing to sam-app/ folder as shown in image below

vscode-project-root

Run Lambda Locally

To invoke lambda function locally use SAM CLI command

sam local invoke
PS C:\MyWorkspace\gitrepos\2022-03-16-lambda-debug\sam-app> sam local invoke
Invoking app.lambda_handler (python3.9)
Skip pulling image and use local one: public.ecr.aws/sam/emulation-python3.9:rapid-1.40.1-x86_64.

Mounting C:\MyWorkspace\gitrepos\2022-03-16-lambda-debug\sam-app\hello_world as /var/task:ro,delegated inside runtime container
START RequestId: 1d4e45de-38be-4b91-8e9f-4d3c7da8788a Version: $LATEST
END RequestId: 1d4e45de-38be-4b91-8e9f-4d3c7da8788a
REPORT RequestId: 1d4e45de-38be-4b91-8e9f-4d3c7da8788a  Init Duration: 1.40 ms  Duration: 990.84 ms     Billed Duration: 991 ms Memory Size: 128 MB  Max Memory Used: 128 MB
{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}

If you have multiple lambda functions in the app, you can invoke a specific lambda function by using it’s name in invoke command as

sam local invoke "HelloWorldFunction"

Run API Gateway Locally

You can run API Gateway locally to test HTTP request response functionality using command

sam local start-api

This command will start a local instance of API Gateway and provide you with a URL that you can use to send a request using CURL commmand

PS C:\MyWorkspace\gitrepos\2022-03-16-lambda-debug\sam-app> sam local start-api
Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2022-03-17 11:41:55  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)

From terminal output you can find tha HelloWorldFunction is mounted at http://127.0.0.1:3000/hello. From another terminal we can call this URL

PS C:\MyWorkspace\gitrepos\2022-03-16-lambda-debug\sam-app> curl http://127.0.0.1:3000/hello


StatusCode        : 200
StatusDescription : OK
Content           : {"message": "hello world"}
RawContent        : HTTP/1.0 200 OK
                    Content-Length: 26
                    Content-Type: application/json
                    Date: Thu, 17 Mar 2022 06:43:08 GMT
                    Server: Werkzeug/1.0.1 Python/3.8.8

                    {"message": "hello world"}
Forms             : {}
Headers           : {[Content-Length, 26], [Content-Type, application/json], [Date, Thu, 17 Mar 2022 06:43:08 GMT], [Server,
                    Werkzeug/1.0.1 Python/3.8.8]}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 26

Debug Lambda Application Locally

To debug a lambda function we have following options

Option 1: Debug through SAM template

From VSCode open template.yaml, and go to the resources section of the template that defines serverless resources. Click on the lambda function resource, which in our case is HelloWorldFunction. A tooltip will appear over it saying AWS: Add Debug Configuration. Click it as shown below.

sam-template-add-debug-config

This will create a new folder in the project with debug launch configuration launch.json.

debug-launch-config

Let’s add a breakpoint in our lambda handler code hello_world/app.py, and start debugging by clicking the green “play” button in the RUN view. When the debugging sessions starts, the DEBUG CONSOLE panel shows debugging output and displays any values returned by the Lambda function.

lambda-debug-template

Option 2: Debug Lambda Directly from Code

From VSCode open lambda handler code sam-app/hello_world/app.py. A tooltip will appear above the lambda_handler function with options * AWS: Add Debug Configuration * AWS: Edit Debug Configuration

lambda-debug-tooltip

Click on AWS: Add Debug Configuration and it will show two further options * template.yaml:HelloWorldFunction (to debug only the lambda function) * template.yaml:HelloWorldFunction (API Event: HelloWorld) (to debug lambda function along with API gateway)

lambda-debug-options

Let’s select API option this time. It will again create a launch configuration, and now we can debug our code. Click on the green “play” button again to start the debug session with request request coming from API Gateway to Lambda function.

You can also edit the debug config visually by selecting the AWS: Edit Debug Configuration, and a side pane will appear from where we can easily edit and update our debug configuration.

edit-debug-config

All the code used for this post can be obtained from the GitHub repository hassaanbinaslam/2022-03-16-lambda-debug