DEV Community

Cover image for Serverless Observability with AWS Lambda Powertools and AWS CDK
Hassan Azhar
Hassan Azhar

Posted on

Serverless Observability with AWS Lambda Powertools and AWS CDK

Introduction

This guide demonstrates how to use AWS CDK to deploy a Lambda function with AWS Lambda Powertools for TypeScript. We'll enable structured logging, distributed tracing (via AWS X-Ray), and custom metrics, all while automating infrastructure provisioning.

Setting Up the CDK Project

Prerequisites

  • AWS CDK: Install AWS CDK if you haven’t already:
    npm install -g aws-cdk

  • Bootstrap CDK:
    cdk bootstrap

  • Project Initialisation:
    mkdir lambda-powertools-cdk && cd lambda-powertools-cdk cdk init app --language=typescript

Installing Dependencies

Install the required libraries:
npm install @aws-cdk/aws-lambda @aws-cdk/aws-lambda-nodejs @aws-cdk/aws-apigateway @aws-cdk/aws-iam @aws-cdk/aws-cloudwatch

Install Lambda Powertools:
npm install @aws-lambda-powertools/logger @aws-lambda-powertools/tracer @aws-lambda-powertools/metrics axios

Lambda Code(lambda/index.ts)
Save the Lambda function code in the lambda directory.

import { Logger } from "@aws-lambda-powertools/logger";
import { Tracer } from "@aws-lambda-powertools/tracer";
import { Metrics, MetricUnits } from "@aws-lambda-powertools/metrics";
import axios from "axios";

// Initialize Powertools utilities
const logger = new Logger();
const tracer = new Tracer();
const metrics = new Metrics();

const WEATHER_API_URL = process.env.WEATHER_API_URL || "https://api.weatherapi.com/v1/current.json";
const API_KEY = process.env.API_KEY || "your_weather_api_key";

export const handler = async (event: any): Promise<any> => {
  logger.info("Lambda function invoked", { event });

  const city = event.queryStringParameters?.city || "London";

  try {
    tracer.annotateColdStart();
    logger.info("Fetching weather data", { city });

    const response = await tracer.captureAWSv3Client(axios).get(`${WEATHER_API_URL}`, {
      params: {
        key: API_KEY,
        q: city,
      },
    });

    logger.info("Weather data fetched successfully", { data: response.data });

    metrics.addMetric("WeatherAPICallSuccess", MetricUnits.Count, 1);

    return {
      statusCode: 200,
      body: JSON.stringify({
        message: "Weather data fetched successfully",
        data: response.data,
      }),
    };
  } catch (error) {
    logger.error("Failed to fetch weather data", { error });

    metrics.addMetric("WeatherAPICallFailure", MetricUnits.Count, 1);

    return {
      statusCode: 500,
      body: JSON.stringify({
        message: "Failed to fetch weather data",
        error: error.message,
      }),
    };
  }
};

Enter fullscreen mode Exit fullscreen mode

CDK Stack (lib/lambda-powertools-stack.ts)
This CDK stack provisions the Lambda function with X-Ray tracing enabled, along with an API Gateway.

import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as apigateway from "aws-cdk-lib/aws-apigateway";
import * as path from "path";

export class LambdaPowertoolsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Create the Lambda function
    const weatherLambda = new lambda.Function(this, "WeatherLambda", {
      runtime: lambda.Runtime.NODEJS_18_X,
      handler: "index.handler",
      code: lambda.Code.fromAsset(path.join(__dirname, "../lambda")),
      environment: {
        WEATHER_API_URL: "https://api.weatherapi.com/v1/current.json",
        API_KEY: "your_weather_api_key", // Replace with your API key
      },
      tracing: lambda.Tracing.ACTIVE, // Enable X-Ray tracing
    });

    // Grant permissions to Lambda for X-Ray
    weatherLambda.addToRolePolicy(
      new cdk.aws_iam.PolicyStatement({
        actions: ["xray:PutTraceSegments", "xray:PutTelemetryRecords"],
        resources: ["*"],
      })
    );

    // Create an API Gateway to invoke the Lambda function
    const api = new apigateway.LambdaRestApi(this, "WeatherAPI", {
      handler: weatherLambda,
      proxy: true,
    });

    // Output the API endpoint
    new cdk.CfnOutput(this, "APIEndpoint", {
      value: api.url,
    });
  }
}

Enter fullscreen mode Exit fullscreen mode

Deploy the Stack

  1. Build and Deploy: cdk deploy

2.Test the API :Use the output API endpoint to test the function:
curl https://<API_ENDPOINT>?city=New%20York

Observability in Action

1. CloudWatch Logs
Structured logs from the Lambda function will be available in CloudWatch Logs. For example:
{ "level": "INFO", "message": "Weather data fetched successfully", "data": { ... } }

2. AWS X-Ray Traces
X-Ray traces will show:

  • The Lambda execution.

  • A subsegment for the external API call.

3. Custom Metrics
View the custom metrics (WeatherAPICallSuccessand WeatherAPICallFailure) in the CloudWatch Metrics console.

Key Features of the CDK Integration

  1. Automation:
  • Automates infrastructure provisioning, ensuring consistency across environments.
  1. X-Ray Integration:
  • Automatically enables X-Ray tracing for the Lambda function.
  1. Environment Configuration:
  • Manages environment variables (e.g., API keys) securely.
  1. API Gateway Integration:
  • Provides an easy way to expose the Lambda function via an API Gateway.

Conclusion

AWS Lambda Powertools, combined with AWS CDK, simplifies observability for serverless applications. By leveraging structured logging, distributed tracing, and custom metrics, you can enhance your application's monitoring and debugging capabilities. With CDK, you can automate infrastructure provisioning, ensuring consistency and scalability.

Integrate these practices into your serverless projects to achieve better observability and operational excellence.

Top comments (0)