Amazon Web Services (AWS) indisputably takes us one step closer to the elimination of bugs in cloud-deployed applications. The AWS service we will be looking at here in detail is Lambda. In particular, our focus is the difficulty many developers encounter when it comes to debugging AWS-deployed functions locally.
We’ll focus on Node.js as we guide you through!
But first…
The claim of AWS itself is that employing Lambda means enterprises adopting Serverless architecture can forget about the infrastructure of your project and get on with launching applications in the cloud while integrating with other Amazon services. Other notable benefits are scalability and the low cost of using AWS computing resources.
To get started all you need to do is to write a Lambda function and connect it with events. After that, Amazon will automate the function for each new event. Scaling and high availability is no longer a concern: the Lambda function will be able to process thousands of requests per hour on AWS without any effort on our part or a backend in the conventional sense.
When discussing a debugging process for AWS lambda functions, particularly close attention should be paid to 3 of the most popular methods:
1.AWS Cloud Watch: a default method. The appeal of using AWS Cloud Watch is that it doesn’t cost anything. However, the drawback is that it can be slow. I have personally had to spend wasted 40 minutes+ on logs output several times. So while it may not cost you anything to use Cloud Watch, the cost of the time involved when relying on this free AWS service shouldn’t be discounted.
2.Logging for deployed Lambda functions: This can be done with the support of other AWS DevOps services such as Kinesis. For developers, this process may initially seem faster. However, the need to create tools manually can mean developers actually spend significantly more time, which adds to expenses and the cost of using additional Amazon Infrastructure also has at least some impact on budgets.
3.Offline debugging: In the case of standard development processes, offline debugging that provides the possibility to work locally is a third option.
AWS has created specific tools to help with the debugging of lambda functions:
AWS SAM (3 506 GitHub stars) extends the AWS CloudFormation to provide a simplified method for defining the Gateway APIs, AWS (Amazon) Lambda functions and Amazon DynamoDB tables your serverless application requires. As an added bonus we also have the option to debug locally (or offline) with AWS SAM CLI.
AWS SAM CLI (3 006 GitHub stars) can run code inside a Docker container (emulating a Lambda runtime environment inside Amazon servers), transform your requests data to API Gateway events and invoke your functions with this event.
AWS SAM CLI allows you to run your code in an environment that replicates the real AWS (Amazon) Lambda environment. This means you can put breakpoints inside the code and expect the debug output to be the same as the deployed function. If you have a bug in the function deployed to AWS (Amazon) Lambda, you can rely upon local invoking that would result in the same bug.
All of these tools and methods have their strengths but there are also weaknesses that have to be taken into consideration.
-Minimal flexibility and capability. There are no plugins, so you can only send merge requests to main projects.
-AWS SAM is made by Golang, while AWS SAM CLI is made by Python. This necessitates all improvements or features also being developed in these languages.
-There are a lot of sources of Lambda function calls. If your project doesn’t only utilise Lambda and API Gateway you will also need to emulate them. But working with all these AWS services offline (not Lambda or API Gateway) is a challenge. You need to create an event file for every service and invoke your function with this event manually through a AWS-SAM-CLI module.
In the context of Node.js, the most popular module for debugging Lambda AWS locally is “Serverless Offline”. It’s a plugin for “Serverless Framework” (25 073 GitHub stars), which is a JS tool and a wrapper on AWS CloudFront. It can look similar to AWS SAM, but it provides for clear syntax and a number of other additional features not present in “SAM”. It also has a range of plugins that emulate the logic of different AWS (Amazon) services (S3, SNS, SQS, and others) locally. Serverless has plugins for other programming languages as well (e.g. Python, Swift, PHP, and Golang).
Debugging Lambda on AWS (Amazon): a Simple Example
To invoke and debug local emulations of AWS Lambda functions, we first have to install two NPM packages: serverless and serverless-offline. Remember that these two packages are alone not enough for a real project due to the number of triggers of the Lambda function: S3, SQS, API Gateway and other services & connections between these services and your computer by AWS CLI.
So we need to have a connection between AWS and Serverless on our machine. This means installing and using other plugins and functionalities provided by Serverless. But for Lambda debugging, a simple function is enough when using API Gateway in the role of a trigger (it’s a basic resource where most requests start from).
We will not explain what every line of the serverless.yml file means here but a quick additional online search will throw up the answers to any questions you might have on that front. Serverless Frameworkand Serverless Offline are also supported by awesome documentation.
To illustrate let’s perform the following steps:
1. So far our runtime option of the Lambda function is equal to “nodejs8.10”, it will run on your machine. We also have to use Node.js version 8.0.0 or higher (8.10 is the optimal choice). So, check your version by the command:
$ node -v
If output is less than “v8.0.0”, install the required version. You can find the installation here.
2. Our simple project and its dependencies are inside:
$ mkdir debug-lambda-local && cd debug-lambda-local && npm init -f && npm i -D serverless serverless-offline
3. Create files “serverless.yml” and “lambda-foo.js”:
$ touch serverless.yml lambda-foo.js
4. Put to “serverless.yml”, file the code below to configure Serverless framework and serverless-offline plugin that emulates API Gateway (proxy server) behavior:
serverless.yml
plugins: serverless-offline provider: name: aws runtime: nodejs8.10 stage: dev region: us-east-1 functions: getresponse: handler: lambda-foo.getResponse events: - http: path: getresponse method: GET custom: serverless-offline: port: 1221
5. Next, insert a simple code with our Lambda function that responds to API Gateway call into the “lambda-foo.js” file. We can put “console.log” anywhere inside this file:
lambda-foo.js
const TIMEOUT = 1000; const getResult = () => new Promise((resolve) => setTimeout(() => resolve(`Resolved after ${TIMEOUT} ms`), TIMEOUT)); exports.getResponse = async (event, context) => { return { statusCode: 200, body: JSON.stringify({ result: await getResult(), }), } }
6. If preferred, you can also substitute this file with any other handlers for an API Gateway request.
7. Start your AWS emulation in watch mode:
$ node_modules/.bin/serverless offline start
This will be the emulation process of API Gateway on localhost:1221.
8. And the final step. Call GET localhost:1221/getresponse and see the debug output from the “getResponse” function in the terminal window where we started Serverless.
You will see that working with the Serverless framework is really easy. But we have to keep in mind the main disadvantage. You can’t rely upon breakpoints in your code as they don’t show the same output as a deployed version of the code. The runtime environment is similar but not the same.
Summary
1.Lambda (Amazon) AWS functions work in an isolated environment. The consequence to this is that debugging becomes increasingly complicated. To offset this the function can be performed locally until deployment, and in the cloud following deployment.
2.It is important to differentiate local tools from communication methods with a cloud post-deployment.
3.To monitor and debug your code, when it is in the development phase, use Serverless Offline or Serverless Application Model.
4.Both Serverless and SAM enable testing of functionality manually without wasting time on deployment and further requests to the AWS (Amazon) cloud.