Structured logging utility for AWS Lambda functions with context enrichment and CloudWatch integration
npx @tessl/cli install tessl/npm-aws-lambda-powertools--logger@2.29.0Structured JSON logging for AWS Lambda with automatic context enrichment, multiple log levels, and CloudWatch/X-Ray integration.
npm install @aws-lambda-powertools/loggerimport { Logger } from '@aws-lambda-powertools/logger';import { Logger } from '@aws-lambda-powertools/logger';
import type { Context } from 'aws-lambda';
const logger = new Logger({ serviceName: 'orderService' });
export const handler = async (event: unknown, context: Context) => {
logger.addContext(context);
logger.info('Processing request', { orderId: event.orderId });
try {
const result = await processOrder(event);
logger.info('Success', { result });
return result;
} catch (error) {
logger.error('Failed', error as Error);
throw error;
}
};const logger = new Logger({ serviceName: 'myService' });
// Log levels: trace, debug, info, warn, error, critical
logger.info('Message');
logger.debug('Details', { data: value });
logger.error('Failed', error as Error);
logger.error('Failed', { customError: error as Error, context: data });const logger = new Logger({
serviceName: 'myService',
persistentKeys: { version: '1.0.0', environment: 'prod' }
});
export const handler = async (event, context) => {
// Temporary keys (cleared on resetKeys or manually)
logger.appendKeys({ requestId: event.requestId });
logger.info('Processing'); // Includes both persistent and temporary keys
logger.removeKeys(['requestId']);
};import { Logger } from '@aws-lambda-powertools/logger';
import { injectLambdaContext } from '@aws-lambda-powertools/logger/middleware';
import middy from '@middy/core';
const logger = new Logger({ serviceName: 'myService' });
const lambdaHandler = async (event, context) => {
logger.info('Processing'); // Context auto-injected
return { statusCode: 200 };
};
export const handler = middy(lambdaHandler).use(
injectLambdaContext(logger, {
logEvent: false, // Log event payload (dev only)
resetKeys: true, // Clear temporary keys after invocation
correlationIdPath: 'requestContext.requestId' // Extract correlation ID
})
);import { Logger } from '@aws-lambda-powertools/logger';
import type { LambdaInterface } from '@aws-lambda-powertools/commons/types';
const logger = new Logger({ serviceName: 'myService' });
class Lambda implements LambdaInterface {
@logger.injectLambdaContext({ resetKeys: true })
public async handler(event: unknown, context: Context): Promise<void> {
logger.info('Processing'); // Context auto-injected, keys auto-cleared
}
}
export const handler = new Lambda().handler.bind(new Lambda());import { correlationPaths } from '@aws-lambda-powertools/logger/correlationId';
const logger = new Logger({ serviceName: 'myService' });
export const handler = async (event, context) => {
// Extract correlation ID from event
logger.setCorrelationId(event, correlationPaths.API_GATEWAY_REST);
logger.info('Request received');
// Retrieve for downstream calls
const correlationId = logger.getCorrelationId();
await callService({ headers: { 'X-Correlation-ID': correlationId } });
};const parentLogger = new Logger({
serviceName: 'parentService',
persistentKeys: { version: '1.0.0' }
});
const childLogger = parentLogger.createChild({
serviceName: 'dataProcessor',
persistentKeys: { component: 'validator' }
});
childLogger.info('Processing'); // Inherits parent config + adds own keysconst logger = new Logger({
serviceName: 'myService',
sampleRateValue: 0.1 // DEBUG logs 10% of invocations
});
export const handler = async (event, context) => {
logger.refreshSampleRateCalculation(); // Recalculate for warm starts
logger.debug('Sampled debug info'); // Logged 10% of time
logger.info('Always logged');
};const logger = new Logger({
serviceName: 'myService',
logBufferOptions: {
enabled: true,
maxBytes: 20480,
flushOnErrorLog: true
}
});
export const handler = async (event, context) => {
logger.debug('Step 1'); // Buffered
logger.debug('Step 2'); // Buffered
try {
await process();
logger.clearBuffer(); // Discard debug logs on success
} catch (error) {
logger.flushBuffer(); // Output debug logs for troubleshooting
logger.error('Failed', error as Error);
}
};type ConstructorOptions = {
logLevel?: LogLevel; // 'TRACE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'CRITICAL' | 'SILENT'
serviceName?: string; // Service identifier in logs
sampleRateValue?: number; // 0-1: DEBUG sampling rate
persistentKeys?: LogAttributes; // Keys in all log items
environment?: string; // Environment name
logFormatter?: LogFormatter; // Custom formatter (mutually exclusive with logRecordOrder)
logRecordOrder?: string[]; // Key ordering (mutually exclusive with logFormatter)
jsonReplacerFn?: CustomJsonReplacerFn; // Custom JSON serialization
logBufferOptions?: {
enabled?: boolean; // Enable buffering (default: false)
maxBytes?: number; // Buffer size (default: 20480)
flushOnErrorLog?: boolean; // Auto-flush on errors (default: false)
bufferAtVerbosity?: 'DEBUG' | 'INFO' | 'WARN'; // Buffer threshold
};
correlationIdSearchFn?: (event: unknown) => string; // Custom correlation ID extraction
};class Logger {
// Logging
trace(input: LogItemMessage, ...extraInput: LogItemExtraInput): void;
debug(input: LogItemMessage, ...extraInput: LogItemExtraInput): void;
info(input: LogItemMessage, ...extraInput: LogItemExtraInput): void;
warn(input: LogItemMessage, ...extraInput: LogItemExtraInput): void;
error(input: LogItemMessage, ...extraInput: LogItemExtraInput): void;
critical(input: LogItemMessage, ...extraInput: LogItemExtraInput): void;
// Context
addContext(context: Context): void;
// Temporary Attributes
appendKeys(attributes: LogAttributes): void;
removeKeys(keys: string[]): void;
resetKeys(): void;
// Persistent Attributes
appendPersistentKeys(attributes: LogAttributes): void;
removePersistentKeys(keys: string[]): void;
getPersistentLogAttributes(): LogAttributes;
// Log Level
setLogLevel(logLevel: LogLevel): void;
getLevelName(): Uppercase<LogLevel>;
get level(): number;
// Correlation ID
setCorrelationId(value: unknown, correlationIdPath?: string): void;
getCorrelationId(): unknown;
// Buffering
flushBuffer(): void;
clearBuffer(): void;
// Event Logging
logEventIfEnabled(event: unknown, overwriteValue?: boolean): void;
getLogEvent(): boolean;
shouldLogEvent(overwriteValue?: boolean): boolean;
// Sampling
refreshSampleRateCalculation(): void;
// Child Loggers
createChild(options?: ConstructorOptions): Logger;
// Decorator
injectLambdaContext(options?: InjectLambdaContextOptions): HandlerMethodDecorator;
}type LogLevel = 'TRACE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'CRITICAL' | 'SILENT'
| 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'critical' | 'silent';
type LogAttributes = { [key: string]: unknown };
type LogItemMessage = string | (LogAttributes & { message: string });
type LogItemExtraInput = [Error | string] | LogAttributes[];
type InjectLambdaContextOptions = {
logEvent?: boolean; // Log event payload (default: false)
resetKeys?: boolean; // Clear temporary keys (default: false)
flushBufferOnUncaughtError?: boolean; // Flush buffer on error (default: false)
correlationIdPath?: string; // JMESPath for correlation ID
};import { correlationPaths } from '@aws-lambda-powertools/logger/correlationId';
const correlationPaths = {
API_GATEWAY_REST: 'requestContext.requestId',
API_GATEWAY_HTTP: 'requestContext.requestId',
APPSYNC_RESOLVER: 'request.headers."x-amzn-trace-id"',
APPSYNC_AUTHORIZER: 'requestContext.requestId',
APPLICATION_LOAD_BALANCER: 'headers."x-amzn-trace-id"',
EVENT_BRIDGE: 'id',
LAMBDA_FUNCTION_URL: 'requestContext.requestId',
S3_OBJECT_LAMBDA: 'xAmzRequestId',
VPC_LATTICE: 'headers."x-amzn-trace-id"'
};AWS_LAMBDA_LOG_LEVEL / LOG_LEVEL / POWERTOOLS_LOG_LEVEL - Set log levelPOWERTOOLS_SERVICE_NAME - Default service namePOWERTOOLS_LOGGER_LOG_EVENT - Log events ('true'/'false')POWERTOOLS_LOGGER_SAMPLE_RATE - Debug sampling (0-1)POWERTOOLS_DEV - Pretty-print logs for developmentFor advanced usage, see:
Required:
npm install @aws-lambda-powertools/loggerOptional (for correlation IDs):
npm install @aws-lambda-powertools/jmespathOptional (for Middy middleware):
npm install @middy/core