Enhance AWS Lambda Functions using Powertools for .NET

Somebody who likes to code
Search for a command to run...

Somebody who likes to code
No comments yet. Be the first to comment.
Testing AWS Lambda functions locally can be a crucial step in the development process, as it allows developers to identify and resolve issues before deploying their code to the cloud. In this regard, AWS SAM provides a method for testing our API call...
Google processes tens of thousands of code changes every day across a codebase of hundreds of millions of lines. The secret isn't magic tooling — it's a documented, principled approach to code review

Amazon Simple Notification Service (SNS) looks straightforward on the surface — publish a message, deliver it to subscribers — but the gap between a topic that "works in dev" and one that is productio

Amazon Simple Queue Service (SQS) is deceptively simple to get started with, but surprisingly easy to misconfigure in ways that cause silent message loss, runaway costs, duplicate processing storms, o

HTTP API is the right default choice for the majority of .NET serverless workloads. At 70% less cost than REST API, lower latency, and native JWT authorization, it covers most production requirements

AWS Lambda has become a cornerstone of modern serverless architectures, but writing a function that "just works" is very different from writing one that is performant, cost-effective, secure, and read

The increasing complexity of serverless applications demands an efficient way to manage and maintain their components. AWS Lambda Powertools offers a suite of utilities designed to simplify the development process, enhance observability, and implement best practices for building serverless applications. By leveraging these tools, developers can focus on their application's core functionality while enjoying the benefits of a streamlined and optimized infrastructure. AWS Lambda Powertools provides three main features:
Logging: Offers structured logs.
Tracing: Supplies a straightforward way for sending traces to AWS X-Ray.
Metrics: Provides an easy way to collect custom metrics.
Ensure you have an IAM User with programmatic access.
Install the Amazon Lambda Templates with this command: dotnet new -i Amazon.Lambda.Templates
Install the Amazon Lambda Tools with this command: dotnet tool install -g Amazon.Lambda.Tools
Install the AWS SAM CLI.
Run the following commands to create a Lambda function:
dotnet new lambda.EmptyFunction -n HelloWorldApi -o .
dotnet add src/HelloWorldApi package Amazon.Lambda.APIGatewayEvents
dotnet new sln -n AwsPowertools
dotnet sln add --in-root src/HelloWorldApi
Open the solution, navigate to the HelloWorldApi project, and update the Function.cs file as follows:
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace HelloWorldApi
{
public class Function
{
public async Task<APIGatewayHttpApiV2ProxyResponse> FunctionHandler(APIGatewayHttpApiV2ProxyRequest input, ILambdaContext context)
{
var key = await KeyGenerator();
return new APIGatewayHttpApiV2ProxyResponse
{
Body = $@"{{""Message"":""This is your key {key}""}}",
StatusCode = 200,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}
private async Task<string> KeyGenerator()
{
await Task.Delay(Random.Shared.Next(2000));
return Guid.NewGuid().ToString();
}
}
}
Create a template.yml file (AWS SAM) with the following content:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
AWS PowerTools
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Timeout: 60
MemorySize: 512
Tracing: Active
Runtime: dotnet6
Architectures:
- x86_64
Handler: HelloWorldApi::HelloWorldApi.Function::FunctionHandler
CodeUri: ./src/HelloWorldApi/
Events:
ListPosts:
Type: Api
Properties:
Path: /
Method: get
Run sam build and sam deploy --guided and follow the instructions to deploy the Lambda function.
To add the Powertools logging library to your project, execute the following command:
dotnet add src/HelloWorldApi package AWS.Lambda.Powertools.Logging
Add the following section in the template.yml file:
Globals:
Function:
Environment:
Variables:
POWERTOOLS_SERVICE_NAME: myfunction
POWERTOOLS_LOG_LEVEL: Debug
The complete list of environment variables (each of which can be set at the code level using the Logging attribute) is as follows:
POWERTOOLS_SERVICE_NAME: Sets service name used for tracing namespace, metrics dimension, and structured logging.
POWERTOOLS_LOG_LEVEL: Sets logging level(Trace, Debug, Information, Warning, Error, Critical, None).
POWERTOOLS_LOGGER_CASE: Override the default casing(CamelCase, PascalCase, SnakeCase) for log keys.
POWERTOOLS_LOGGER_LOG_EVENT: Logs incoming event.
POWERTOOLS_LOGGER_SAMPLE_RATE: Debug log sampling.
Modify the FunctionHandler implementation as follows:
[Logging(LogEvent = true)]
public async Task<APIGatewayHttpApiV2ProxyResponse> FunctionHandler(APIGatewayHttpApiV2ProxyRequest input, ILambdaContext context)
{
Logger.LogInformation("Generating a new key");
var key = await KeyGenerator();
Logger.LogInformation(new Dictionary<string, object>() { { "Key", key } },"New key generated");
return new APIGatewayHttpApiV2ProxyResponse
{
Body = $@"{{""Message"":""This is your key {key}""}}",
StatusCode = 200,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}
The Logging attribute instructs the function to log the incoming event (when the LogEvent property is true).
Logger.LogInformation("Generating a new key") logs a simple message.
Logger.LogInformation(new Dictionary<string, object>() { { "Key", key } },"New key generated") logs a message with properties.
Deploy the function to view outputs such as:
{
"cold_start": false,
"xray_trace_id": "1-648fbb32-7935059f75c9ef6705c24cb0",
"function_name": "awspowertools-MyFunction-3wYZWUsiQxv5",
"function_version": "$LATEST",
"function_memory_size": 512,
"function_arn": "arn:aws:lambda:us-east-2:020000000000:function:awspowertools-MyFunction-3wYZWUsiQxv5",
"function_request_id": "d833025d-8aa3-4766-9738-e5be283c233a",
"key": "0eb5d295-d646-4ba9-be06-22db05504836",
"timestamp": "2023-06-19T02:19:30.8281371Z",
"level": "Information",
"service": "myfunction",
"name": "AWS.Lambda.Powertools.Logging.Logger",
"message": "New key generated"
}
With structured logs, we can perform searches on this structured data using CloudWatch Logs Insights:

For more information, please refer to the official documentation here.
To add the Powertools tracing library (wrapper for AWS X-Ray SDK for .NET) to your project, run the following command:
dotnet nuget add AWS.Lambda.Powertools.Tracing
Ensure that the Tracing property is activated for your AWS::Serverless::Function resource. Like the logging library, there are a set of environment variables (each of which can be set at the code level using the Tracing attribute) that we can use:
POWERTOOLS_SERVICE_NAME: Sets service name used for tracing namespace, metrics dimension, and structured logging.
POWERTOOLS_TRACE_DISABLED: Disables tracing.
POWERTOOLS_TRACER_CAPTURE_RESPONSE: Captures Lambda or method return as metadata.
POWERTOOLS_TRACER_CAPTURE_ERROR: Captures Lambda or method exception as metadata.
Update the template.yml file as follows:
Globals:
Function:
Environment:
Variables:
POWERTOOLS_SERVICE_NAME: myfunction
POWERTOOLS_LOG_LEVEL: Debug
POWERTOOLS_TRACER_CAPTURE_RESPONSE: true
POWERTOOLS_TRACER_CAPTURE_ERROR: true
To enable PowerTools tracing for our function, add the Tracing attribute to our FunctionHandler method or to any other method:
[Logging(LogEvent = true)]
[Tracing]
public async Task<APIGatewayHttpApiV2ProxyResponse> FunctionHandler(APIGatewayHttpApiV2ProxyRequest input, ILambdaContext context)
{
Logger.LogInformation("Generating a new key");
var key = await KeyGenerator();
Logger.LogInformation(new Dictionary<string, object>() { { "Key", key } }, "New key generated");
return new APIGatewayHttpApiV2ProxyResponse
{
Body = $@"{{""Message"":""This is your key {key}""}}",
StatusCode = 200,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}
[Tracing(SegmentName = "Key generator service")]
private async Task<string> KeyGenerator()
{
await Task.Delay(Random.Shared.Next(2000));
return Guid.NewGuid().ToString();
}
Deploy the function, then navigate to AWS X-Ray traces to view the results:

We can instrument all our AWS SDK for .NET clients by calling
AWSSDKHandler.RegisterXRayForAllServices()at the constructor level.
For more information, please refer to the official documentation here.
To add the Powertools metrics library to your project, execute the following command:
dotnet nuget add AWS.Lambda.Powertools.Metrics
The metrics utility generates custom metrics asynchronously by logging metrics to standard output using the Amazon CloudWatch Embedded Metric Format (EMF). The set of environment variables (each of which can be set at the code level using the Metrics attribute) we can use are:
POWERTOOLS_SERVICE_NAME: Sets service name used for tracing namespace, metrics dimension, and structured logging.
POWERTOOLS_METRICS_NAMESPACE: Sets namespace used for metrics.
Update the template.yml file as follows:
Globals:
Function:
Environment:
Variables:
POWERTOOLS_SERVICE_NAME: myfunction
POWERTOOLS_LOG_LEVEL: Debug
POWERTOOLS_TRACER_CAPTURE_RESPONSE: true
POWERTOOLS_TRACER_CAPTURE_ERROR: true
POWERTOOLS_METRICS_NAMESPACE: mymetrics
Modify the FunctionHandler implementation as follows:
[Logging(LogEvent = true)]
[Metrics]
[Tracing]
public async Task<APIGatewayHttpApiV2ProxyResponse> FunctionHandler(APIGatewayHttpApiV2ProxyRequest input, ILambdaContext context)
{
Logger.LogInformation("Generating a new key");
var key = await KeyGenerator();
Logger.LogInformation(new Dictionary<string, object>() { { "Key", key } }, "New key generated");
Metrics.AddMetric("SuccessfulKeyGeneration", 1, MetricUnit.Count);
return new APIGatewayHttpApiV2ProxyResponse
{
Body = $@"{{""Message"":""This is your key {key}""}}",
StatusCode = 200,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}
Deploy the function, then navigate to CloudWatch metrics to view the results:

For more information, please refer to the official documentation here.
AWS Lambda Powertools for .NET is a collection of utilities that simplifies serverless application development. By using its logging, tracing, and metrics features, developers can concentrate on their application's core functionality. All the code is available here. Thanks, and happy coding.