Middleware-based tracing provides automatic instrumentation for function-based Lambda handlers using the Middy middleware framework. This pattern is ideal for functional programming styles and integrates seamlessly with other Middy middleware.
Automatically trace Lambda handler execution with cold start detection and error handling using Middy middleware.
/**
* Middy middleware automating capture of metadata and annotations on segments or subsegments for a Lambda Handler
*
* Automatically:
* - Handles subsegment lifecycle
* - Adds ColdStart annotation
* - Adds ServiceName annotation
* - Adds function response as metadata (configurable)
* - Adds function error as metadata (if any)
*/
function captureLambdaHandler(
target: Tracer,
options?: CaptureLambdaHandlerOptions
): MiddlewareLikeObj;
interface CaptureLambdaHandlerOptions {
/** Whether to capture the Lambda handler response as subsegment metadata (default: true) */
captureResponse?: boolean;
}
interface MiddlewareLikeObj {
before?: (request: MiddyLikeRequest) => void | Promise<void>;
after?: (request: MiddyLikeRequest) => void | Promise<void>;
onError?: (request: MiddyLikeRequest) => void | Promise<void>;
}Basic Usage:
import { Tracer } from '@aws-lambda-powertools/tracer';
import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware';
import middy from '@middy/core';
const tracer = new Tracer({ serviceName: 'serverlessAirline' });
const lambdaHandler = async (event: unknown, context: unknown): Promise<void> => {
// Handler logic - automatically traced
tracer.putAnnotation('successfulBooking', true);
};
export const handler = middy(lambdaHandler).use(captureLambdaHandler(tracer));Disabling Response Capture:
import { Tracer } from '@aws-lambda-powertools/tracer';
import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware';
import middy from '@middy/core';
const tracer = new Tracer({ serviceName: 'paymentService' });
const lambdaHandler = async (event: PaymentEvent, context: unknown): Promise<PaymentResponse> => {
// Process payment - response not captured due to sensitive data
return { transactionId: '123', status: 'success' };
};
export const handler = middy(lambdaHandler).use(
captureLambdaHandler(tracer, { captureResponse: false })
);import { Tracer } from '@aws-lambda-powertools/tracer';
import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware';
import { DynamoDBClient, GetItemCommand } from '@aws-sdk/client-dynamodb';
import middy from '@middy/core';
const tracer = new Tracer({ serviceName: 'bookingService' });
// Instrument AWS SDK client
const dynamoDB = tracer.captureAWSv3Client(new DynamoDBClient({}));
interface BookingEvent {
bookingId: string;
userId: string;
}
interface BookingResponse {
booking: {
id: string;
status: string;
};
}
const lambdaHandler = async (
event: BookingEvent,
context: unknown
): Promise<BookingResponse> => {
// Add custom annotations
tracer.putAnnotation('bookingId', event.bookingId);
tracer.putAnnotation('userId', event.userId);
// Get booking from DynamoDB (automatically traced)
const result = await dynamoDB.send(new GetItemCommand({
TableName: 'Bookings',
Key: { bookingId: { S: event.bookingId } }
}));
// Add metadata
tracer.putMetadata('dbResponse', result);
return {
booking: {
id: event.bookingId,
status: 'confirmed'
}
};
};
// Wrap handler with middleware
export const handler = middy(lambdaHandler).use(captureLambdaHandler(tracer));The Tracer middleware integrates seamlessly with other Middy middleware:
import { Tracer } from '@aws-lambda-powertools/tracer';
import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware';
import middy from '@middy/core';
import httpJsonBodyParser from '@middy/http-json-body-parser';
import httpErrorHandler from '@middy/http-error-handler';
const tracer = new Tracer({ serviceName: 'apiService' });
const lambdaHandler = async (event: APIEvent, context: unknown): Promise<APIResponse> => {
tracer.putAnnotation('endpoint', event.path);
// Business logic
return {
statusCode: 200,
body: JSON.stringify({ message: 'Success' })
};
};
export const handler = middy(lambdaHandler)
.use(httpJsonBodyParser())
.use(captureLambdaHandler(tracer))
.use(httpErrorHandler());The middleware automatically captures errors as metadata:
import { Tracer } from '@aws-lambda-powertools/tracer';
import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware';
import middy from '@middy/core';
const tracer = new Tracer({ serviceName: 'orderService' });
const lambdaHandler = async (event: OrderEvent, context: unknown): Promise<void> => {
tracer.putAnnotation('orderId', event.orderId);
// Simulate an error
if (!event.isValid) {
throw new Error('Invalid order');
}
// Process order
};
// Middleware will automatically capture the error as metadata
export const handler = middy(lambdaHandler).use(captureLambdaHandler(tracer));The middleware is fully typed and works with typed events and responses:
import { Tracer } from '@aws-lambda-powertools/tracer';
import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware';
import type { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
import middy from '@middy/core';
const tracer = new Tracer({ serviceName: 'apiService' });
const lambdaHandler = async (
event: APIGatewayProxyEvent,
context: Context
): Promise<APIGatewayProxyResult> => {
tracer.putAnnotation('path', event.path);
tracer.putAnnotation('method', event.httpMethod);
return {
statusCode: 200,
body: JSON.stringify({ message: 'Hello World' })
};
};
export const handler = middy(lambdaHandler).use(captureLambdaHandler(tracer));To use the Tracer middleware, you need to install Middy:
npm install @middy/coreMiddy is specified as an optional peer dependency with version compatibility:
Use Middleware when:
Use Decorators when:
See Decorator-based Tracing for decorator usage.