DEV Community

Cover image for πŸ‹ AWS CDK 101 - πŸ¦‹ SAM local to test and debug lambda function
Aravind V for AWS Community Builders

Posted on • Originally published at devpost.hashnode.dev

πŸ‹ AWS CDK 101 - πŸ¦‹ SAM local to test and debug lambda function

πŸ”° Beginners new to AWS CDK, please do look at my previous articles one by one in this series.

If in case missed my previous article, do find it with the below links.

πŸ” πŸ”— Dev Post aws-cdk-101-send-message-across-accounts-using-sns-topic-and-sqs

πŸ” πŸ”— dev to aws-cdk-101-send-message-across-accounts-using-sns-topic-and-sqs-h2i

Also, we have started to develop an open source project which we would be using to play around with refracting the architecture as well as learn CDK stuff at the same time we will provide something useful for our community. Find more about this discussed in the article below.

arch

πŸ” Original project post at πŸ”— Dev Post aws-cdk-101-projects-cdk-stackresourcedrift-events-forwarded-to-cool-slack-posts-event-forwarder

πŸ” Reposted project post at πŸ”— dev to aws-cdk-101-projects-cdk-stackresourcedrift-events-forwarded-to-cool-slack-posts-event-forwarder-1m0m

event-forwarder Github repo

Integration testing lambda 🍑

Earlier in our article, we have seen how to use Eventbridge and SNS to forward over messages to remote stacks as well. Now let us make one more addition to our stack by setting up local integration testing of the lambda using sam local.

We need to get this since after performing numerous iterations with cdk deploy and validating the cloud watch logs, i wanted to find something which i could leverage to be capable of find the bugs prior to release.

Sam local 🀑

Using Sam local will be able to set up sam local docker to test our lambda processor, though someone of you may not find it useful. But you may be making changes to the code in repeated iterations. Now and then you may need to hot-swap or force deploy the changes and based on the assets it will unnecessarily lead to the below scenarios if you are not interested with

  • you could also check in your test events rather than using in lambda console.
  • you can try to run the lambda in a similar environment (like arm64) and runtime (different node versions) even if you don't have that locally
  • Inspect the environment information and debug log traces for lambda container
  • Monitor the system usage and audit the memory composition of the layers used
  • This can also help you use pull remote layers and bind with local layers to simulate it.
  • temporarily your network could be offline and you could not test.
  • increase asset file/zip uploads
  • KMS keys used for cross-account deploy buckets
  • need to commit for the pipeline to deploy event for minor changes
  • more importantly you may need to wait for the deployment/pipeline to complete

To start with we will be first discussing how to set up sam local.

SAM CLI Installation πŸ€–

For this, we need to install sam cli

Installing the AWS SAM CLI on Linux
Installing the AWS SAM CLI on Windows
Installing the AWS SAM CLI on macOS

I prefer the homebrew option if you have that installed already.

brew tap aws/tap
brew install aws-sam-cli
sam --version
Enter fullscreen mode Exit fullscreen mode

Json output format πŸ‘€

For better formatting, I use to have | jq . towards the end of certain npm run scripts. If you need this u need to install check out the below link
jq download

Again I do it with homebrew

brew install jq
Enter fullscreen mode Exit fullscreen mode

Add the below launch configuration 🦴

In vscode, you can also add the below launch config to the launch configurations in the file .vscode/launch.json. This will enable the js map link to the source as well so that we could follow the code in vscode with js map errors in debug console.

 {
    "name": "Attach to SAM CLI",
    "type": "node",
    "request": "attach",
    "address": "localhost",
    "port": 9999,
    "localRoot": "${workspaceRoot}/dist/lambda/stack-event-processor",
    "remoteRoot": "/var/task",
    "protocol": "inspector",
    "stopOnEntry": false
}
Enter fullscreen mode Exit fullscreen mode

If you don't like to use js debugging when using typescript with webpack you can add the below to your launch config attach configuration sourceMapPathOverrides as discussed above.

{
"sourceMapPathOverrides": {
    "meteor://πŸ’»ap{workspaceFolder}/*",
    "webpack:///./{workspaceFolder}/node_*",
    "webpack://?:{workspaceFolder}/*"
}
Enter fullscreen mode Exit fullscreen mode

Define the stack template in the package config πŸ”

Here I have defined a random stack template name for the remote stack npm_package_config_remoteTemplate since it has generated stack id ./cdk.out/RemoteEventRouterStack-ap-south-1-456.template.json.
You can update it to the correct one as per your synth.

  "config": {
    "stackName": "EventForwarderStack",
    "cfnTemplateProcessor": "./cdk.out/EventForwarderStack.template.json",
    "remoteTemplate": "./cdk.out/RemoteEventRouterStack-ap-south-1-456.template.json"
  },
Enter fullscreen mode Exit fullscreen mode

Sample Events πŸ₯

I have placed sample events in the events folder to run the function. This can grow based on needs. Here a dummy cloudformation event is stringified inside the body of the dummy sqs event payload.

events

Detecting sam local setup locally πŸ¦‰

You can add the below code into the handler to choice the right flow and use sam local seamlessly.

const handle = async function (event: SQSEvent) {

  if(process.env.AWS_SAM_LOCAL) {
    logger.info("running with sam local:", { event });
  }
Enter fullscreen mode Exit fullscreen mode

Note since we are using webpack to bundle to the dist folder we will using this our local and we could not link to typescript, so we have place a similar break point in the js file to linkable by the debugger

Else add add the sourceMapPathOverrides property to the launch config as discussed above for webpack.

How to run 🦚

As already advised the config and the AWS named profile and package config has to be updated as per your preference and then you can run the below scripts.

Build script with sam template 🐒

{
    "sam:b:1": "sam build --docker-network cloud -t $npm_package_config_cfnTemplateProcessor --profile av --region ap-south-1 ",
    "sam:b:2": "sam build --docker-network cloud -t $npm_package_config_remoteTemplate --profile av-s --region ap-south-1 ",
}
Enter fullscreen mode Exit fullscreen mode

Run scripts for testing 🐜

Note for testing you have to provide the event payload in the below format as follows.

Directly invoking the function when the sam template is already validated

npm run t:1:func1 -- --event=events/event_stack_delete_complete.json

or always build with sam before testing

npm run t:1:1 -- --event=events/event_stack_delete_complete.json

response in t 1

{
    "sam:i": "sam local invoke $npm_config_fname --docker-network cloud -e $npm_config_event | jq .",
    "t:1:func1": "npm run sam:i --fname=stackEventProcessor",
    "t:1:func2": "npm run sam:i --fname=failedMessageLogger",
    "t:2:func1": "npm run sam:i --fname=failedMessageAggregator",
    "t:1:1": "npm run sam:b:1 && npm run t:1:func1",
    "t:1:2": "npm run sam:b:1 && npm run t:1:func2",
    "t:2:1": "npm run sam:b:2 && npm run t:2:func1"
}
Enter fullscreen mode Exit fullscreen mode

run scripts for debugging 🌸

Note for debugging you have to provide the event payload in the below format as follows.

--log-file logs/sam-debug-logs.txt is used to move the cloudwatch logs to my current folder you may remove that if you prefer. Also when the log file is enabled you won't get the web socket link for debugging and you only get the below notification. Once you find it you can switch to vscode to attach to SAM CLI process using our config defined above.

interrupt handler

--debug option is used to capture more verbose environment-related insights and trace beyond your function logic, feel free to remove it if you don't need them

In these scripts, you may additionally find that we are synthesizing and building before debugging to make sure the latest code changes are into sam local.

npm run d:1:func1 -- --event=events/event_stack_delete_complete.json

{

    "sam:i:debug": "sam local invoke $npm_config_fname --docker-network cloud -d 9999 -e $npm_config_event  --log-file logs/sam-debug-logs.txt --debug | jq .",
    "d:1:func1": "npm run cdk:synth:all && npm run sam:b:1 && npm run sam:i:debug --fname=stackEventProcessor",
    "d:1:func2": "npm run cdk:synth:all && npm run sam:b:1 && npm run sam:i:debug --fname=failedMessageLogger",
    "d:2:func2": "npm run cdk:synth:all && npm run sam:b:2 && npm run sam:i:debug --fname=failedMessageAggregator",

}
Enter fullscreen mode Exit fullscreen mode

Debugging in vscode 🌹

logs and vscode

As discussed earlier we made a break point in the js file under the dist folder to catch via the debugger.

debug in vscode set breakpoint

Inspect Docker container while debugging πŸ’

Understand system processes and usage

Understand system processes and usage

memory requirements of layers

memory requirements of layers

lambda container environment variables

sam local env 1

sam local env 2

Conclusion β›²

This will be extremely useful when you repeatedly iterate and make code changes to the processor and you could use the test event to test it swiftly. Watch out for our next article on local dynamodb setup and integration.

We will be talking about more similar engineering concepts as we refactor and refine the event forwarder project. Keep following for similar posts on engineering with IaC primarily using AWS CDK and Serverless.

Also, feel free to contribute to the progress of the below solution with your comments, and issues, maybe you can also do a pr if you feel it can help our community.

event-forwarder Github repo

arch

πŸ” Original project post at πŸ”— Dev Post aws-cdk-101-projects-cdk-stackresourcedrift-events-forwarded-to-cool-slack-posts-event-forwarder

πŸ” Reposted project post at πŸ”— dev to aws-cdk-101-projects-cdk-stackresourcedrift-events-forwarded-to-cool-slack-posts-event-forwarder-1m0m

⏭ We have our next article in serverless and IaC, do check out

https://dev.to/aws-builders/aws-cdk-101-dynamodb-local-setup-and-integrating-with-sam-invoke-527f

πŸŽ‰ Thanks for supporting! πŸ™

Would be great if you like to β˜• Buy Me a Coffee, to help boost my efforts 😍.

Buy Me a Coffee at ko-fi.com

πŸ” Original post at πŸ”— Dev Post aws-cdk-101-sam-local-to-test-and-debug-lambda-function

πŸ” Reposted at πŸ”— dev to @aravindvcyber aws-cdk-101-sam-local-to-test-and-debug-lambda-function-1afj

Top comments (0)