AWS Lambda - Test and Debug Locally in Visual Studio Code
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:
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 issam-app/
- All the subsequest commands including project
sam build
,sam deploy
, invoke and test lambda should be done from project root folder
- After project initialization from
- VSCode
- When you open the project make sure that your project root directory is pointing to
sam-app/
folder as shown in image below
- When you open the project make sure that your project root directory is pointing to
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.
This will create a new folder in the project with debug launch configuration launch.json
.
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.
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
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)
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.
All the code used for this post can be obtained from the GitHub repository hassaanbinaslam/2022-03-16-lambda-debug