Structured logging utility for AWS Lambda functions with context enrichment and CloudWatch integration
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Structured 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