The Logger utility must always be instantiated outside the Lambda handler. By doing this, subsequent invocations processed by the same instance of your function can reuse these resources. This saves cost by reducing function run time. In addition, Logger can keep track of a cold start and inject the appropriate fields into logs.
The library requires two settings. You can set them as environment variables, or pass them in the constructor.
These settings will be used across all logs emitted:
Setting
Description
Environment variable
Default Value
Allowed Values
Example Value
Constructor parameter
Service name
Sets the name of service of which the Lambda function is part of, that will be present across all log statements
POWERTOOLS_SERVICE_NAME
service_undefined
Any string
serverlessAirline
serviceName
Logging level
Sets how verbose Logger should be, from the most verbose to the least verbose (no logs)
LOG_LEVEL
info
DEBUG, INFO, WARN, ERROR, SILENT
ERROR
logLevel
Log incoming event
Whether to log or not the incoming event when using the decorator or middleware
POWERTOOLS_LOGGER_LOG_EVENT
false
true, false
false
logEvent
Debug log sampling
Probability that a Lambda invocation will print all the log items regardless of the log level setting
POWERTOOLS_LOGGER_SAMPLE_RATE
0
0.0 to 1
0.5
sampleRateValue
Example using AWS Serverless Application Model (SAM)¶
1 2 3 4 5 6 7 8 91011
import{Logger}from'@aws-lambda-powertools/logger';// Logger parameters fetched from the environment variables (see template.yaml tab)constlogger=newLogger();logger.info('Hello World');// You can also pass the parameters in the constructor// const logger = new Logger({// logLevel: 'WARN',// serviceName: 'serverlessAirline'// });
Optional - An object containing information about the Error passed to the logger
Info
When POWERTOOLS_DEV environment variable is present and set to "true" or "1", Logger will pretty-print log messages for easier readability. We recommend to use this setting only when debugging on local environments.
import{Logger,injectLambdaContext}from'@aws-lambda-powertools/logger';importmiddyfrom'@middy/core';constlogger=newLogger();constlambdaHandler=async(_event:unknown,_context:unknown):Promise<void>=>{logger.info('This is an INFO log with some context');};exportconsthandler=middy(lambdaHandler).use(injectLambdaContext(logger));
Info
Decorators can only be attached to a class declaration, method, accessor, property, or parameter. Therefore, if you prefer to write your handler as a standard function rather than a Class method, use the middleware or the manual instrumentation instead. See the official TypeScript documentation for more details.
1 2 3 4 5 6 7 8 9101112131415
import{Logger}from'@aws-lambda-powertools/logger';import{LambdaInterface}from'@aws-lambda-powertools/commons';constlogger=newLogger();classLambdaimplementsLambdaInterface{// Decorate your handler class method@logger.injectLambdaContext()publicasynchandler(_event:unknown,_context:unknown):Promise<void>{logger.info('This is an INFO log with some context');}}constmyFunction=newLambda();exportconsthandler=myFunction.handler.bind(myFunction);// (1)
Binding your handler method allows your handler to access this within the class methods.
123456789
import{Logger}from'@aws-lambda-powertools/logger';constlogger=newLogger();exportconsthandler=async(_event,context):Promise<void>=>{logger.addContext(context);logger.info('This is an INFO log with some context');};
In each case, the printed log will look like this:
1 2 3 4 5 6 7 8 9101112
{"cold_start":true,"function_arn":"arn:aws:lambda:eu-west-1:123456789012:function:shopping-cart-api-lambda-prod-eu-west-1","function_memory_size":128,"function_request_id":"c6af9ac6-7b61-11e6-9a41-93e812345678","function_name":"shopping-cart-api-lambda-prod-eu-west-1","level":"INFO","message":"This is an INFO log with some context","service":"serverlessAirline","timestamp":"2021-12-12T21:21:08.921Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}
When debugging in non-production environments, you can instruct Logger to log the incoming event with the middleware/decorator parameter logEvent or via POWERTOOLS_LOGGER_LOG_EVENT env var set to true.
Warning
This is disabled by default to prevent sensitive info being logged
1 2 3 4 5 6 7 8 9101112131415
import{Logger,injectLambdaContext}from'@aws-lambda-powertools/logger';importmiddyfrom'@middy/core';constlogger=newLogger();constlambdaHandler=async(_event:unknown,_context:unknown):Promise<void>=>{logger.info('This is an INFO log with some context');};exportconsthandler=middy(lambdaHandler).use(injectLambdaContext(logger,{logEvent:true}));
1 2 3 4 5 6 7 8 9101112131415
import{Logger}from'@aws-lambda-powertools/logger';import{LambdaInterface}from'@aws-lambda-powertools/commons';constlogger=newLogger();classLambdaimplementsLambdaInterface{// Set the log event flag to true@logger.injectLambdaContext({logEvent:true})publicasynchandler(_event:unknown,_context:unknown):Promise<void>{logger.info('This is an INFO log with some context');}}constmyFunction=newLambda();exportconsthandler=myFunction.handler.bind(myFunction);// (1)
Binding your handler method allows your handler to access this within the class methods.
Appending persistent additional log keys and values¶
You can append additional persistent keys and values in the logs generated during a Lambda invocation using either mechanism:
Via the Logger's appendKeys method, for all log items generated after calling this method
Passing them in the Logger's constructor
To remove the keys you added, you can use the removeKeys method.
import{Logger}from'@aws-lambda-powertools/logger';// Add persistent log keys via the constructorconstlogger=newLogger({persistentLogAttributes:{aws_account_id:'123456789012',aws_region:'eu-west-1',logger:{name:'@aws-lambda-powertools/logger',version:'0.0.1',},extra_key:'some-value',},});// OR add persistent log keys to an existing Logger instance with the appendKeys method:// logger.appendKeys({// aws_account_id: '123456789012',// aws_region: 'eu-west-1',// logger: {// name: '@aws-lambda-powertools/logger',// version: '0.0.1',// },// extra_key: "some-value"// });exportconsthandler=async(_event:unknown,_context:unknown):Promise<unknown>=>{// If you don't want to log the "extra_key" attribute in your logs, you can remove itlogger.removeKeys(['extra_key']);// This info log will print all extra custom attributes added above// Extra attributes: logger object with name and version of the logger library, awsAccountId, awsRegionlogger.info('This is an INFO log');logger.info('This is another INFO log');return{foo:'bar',};};
{"level":"INFO","message":"This is an INFO log","service":"serverlessAirline","timestamp":"2021-12-12T21:49:58.084Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456","aws_account_id":"123456789012","aws_region":"eu-west-1","logger":{"name":"@aws-lambda-powertools/logger","version":"0.0.1"}}{"level":"INFO","message":"This is another INFO log","service":"serverlessAirline","timestamp":"2021-12-12T21:49:58.088Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456","aws_account_id":"123456789012","aws_region":"eu-west-1","logger":{"name":"@aws-lambda-powertools/logger","version":"0.0.1"}}
Logger will automatically ignore any key with an undefined value
The Logger utility is commonly initialized in the global scope, outside the handler function.
When you attach persistent log attributes through the persistentLogAttributes constructor option or via the appendKeys, addPersistentLogAttributes methods, this data is attached to the Logger instance.
Due to the Lambda Execution Context reuse, this means those persistent log attributes may be reused across invocations.
If you want to make sure that persistent attributes added inside the handler function code are not persisted across invocations, you can set the parameter clearState as true in the injectLambdaContext middleware or decorator.
import{Logger,injectLambdaContext}from'@aws-lambda-powertools/logger';importmiddyfrom'@middy/core';// Persistent attributes added outside the handler will be// cached across invocationsconstlogger=newLogger({logLevel:'DEBUG',persistentLogAttributes:{foo:'bar',biz:'baz',},});constlambdaHandler=async(event:{special_key:string},_context:unknown):Promise<void>=>{// Persistent attributes added inside the handler will NOT be cached// across invocationsif(event['special_key']==='123456'){logger.appendKeys({details:{special_key:event['special_key']},});}logger.debug('This is a DEBUG log');};// Enable the clear state flagexportconsthandler=middy(lambdaHandler).use(injectLambdaContext(logger,{clearState:true}));
import{Logger}from'@aws-lambda-powertools/logger';import{LambdaInterface}from'@aws-lambda-powertools/commons';// Persistent attributes added outside the handler will be// cached across invocationsconstlogger=newLogger({logLevel:'DEBUG',persistentLogAttributes:{foo:'bar',biz:'baz',},});classLambdaimplementsLambdaInterface{// Enable the clear state flag@logger.injectLambdaContext({clearState:true})publicasynchandler(event:unknown,_context:unknown):Promise<void>{// Persistent attributes added inside the handler will NOT be cached// across invocationsif(event['special_key']==='123456'){logger.appendKeys({details:{special_key:'123456'},});}logger.debug('This is a DEBUG log');}}constmyFunction=newLambda();exportconsthandler=myFunction.handler.bind(myFunction);// (1)
Binding your handler method allows your handler to access this within the class methods.
In each case, the printed log will look like this:
1 2 3 4 5 6 7 8 91011121314151617
{"biz":"baz","cold_start":true,"details":{"special_key":"123456",},"foo":"bar","function_arn":"arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function","function_memory_size":128,"function_name":"foo-bar-function","function_request_id":"abcdef123456abcdef123456","level":"DEBUG","message":"This is a DEBUG log with the user_id","service":"hello-world","timestamp":"2021-12-12T22:32:54.670Z","xray_trace_id":"1-5759e988-bd862e3fe1be46a994272793"}
1 2 3 4 5 6 7 8 91011121314
{"biz":"baz","cold_start":false,"foo":"bar","function_arn":"arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function","function_memory_size":128,"function_name":"foo-bar-function","function_request_id":"abcdef123456abcdef123456","level":"DEBUG","message":"This is a DEBUG log with the user_id","service":"hello-world","timestamp":"2021-12-12T22:40:23.120Z","xray_trace_id":"1-5759e988-bd862e3fe1be46a994272793"}
You can append additional data to a single log item by passing objects as additional parameters.
Pass a simple string for logging it with default key name extra
Pass one or multiple objects containing arbitrary data to be logged. Each data object should be placed in an enclosing object as a single property value, you can name this property as you need: { myData: arbitraryObjectToLog }
If you already have an object containing a message key and an additional property, you can pass this object directly
import{Logger}from'@aws-lambda-powertools/logger';constlogger=newLogger();exportconsthandler=async(event:unknown,_context:unknown):Promise<unknown>=>{constmyImportantVariable={foo:'bar',};// Log additional data in single log items// As second parameterlogger.info('This is a log with an extra variable',{data:myImportantVariable,});// You can also pass multiple parameters containing arbitrary objectslogger.info('This is a log with 3 extra objects',{data:myImportantVariable},{correlationIds:{myCustomCorrelationId:'foo-bar-baz'}},{lambdaEvent:event});// Simply pass a string for logging additional datalogger.info('This is a log with additional string value','string value');// Directly passing an object containing both the message and the additional infoconstlogObject={message:'This is a log message',additionalValue:42,};logger.info(logObject);return{foo:'bar',};};
{"level":"INFO","message":"This is a log with an extra variable","service":"serverlessAirline","timestamp":"2021-12-12T22:06:17.463Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456","data":{"foo":"bar"}}{"level":"INFO","message":"This is a log with 3 extra objects","service":"serverlessAirline","timestamp":"2021-12-12T22:06:17.466Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456","data":{"foo":"bar"},"correlationIds":{"myCustomCorrelationId":"foo-bar-baz"},"lambdaEvent":{"exampleEventData":{"eventValue":42}}}{"level":"INFO","message":"This is a log with additional string value","service":"serverlessAirline","timestamp":"2021-12-12T22:06:17.463Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456","extra":"string value"}{"level":"INFO","message":"This is a log message","service":"serverlessAirline","timestamp":"2021-12-12T22:06:17.463Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456","additionalValue":42}
You can log errors by using the error method and pass the error object as parameter.
The error will be logged with default key name error, but you can also pass your own custom key name.
1 2 3 4 5 6 7 8 9101112131415161718192021222324
import{Logger}from'@aws-lambda-powertools/logger';constlogger=newLogger();exportconsthandler=async(_event:unknown,_context:unknown):Promise<void>=>{try{thrownewError('Unexpected error #1');}catch(error){// Log information about the error using the default "error" keylogger.error('This is the first error',errorasError);}try{thrownewError('Unexpected error #2');}catch(error){// Log information about the error using a custom "myCustomErrorKey" keylogger.error('This is the second error',{myCustomErrorKey:errorasError,});}};
{"level":"ERROR","message":"This is the first error","service":"serverlessAirline","timestamp":"2021-12-12T22:12:39.345Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456","error":{"name":"Error","location":"/path/to/my/source-code/my-service/handler.ts:18","message":"Unexpected error #1","stack":"Error: Unexpected error #1 at lambdaHandler (/path/to/my/source-code/my-service/handler.ts:18:11) at Object.<anonymous> (/path/to/my/source-code/my-service/handler.ts:35:1) at Module._compile (node:internal/modules/cjs/loader:1108:14) at Module.m._compile (/path/to/my/source-code/node_modules/ts-node/src/index.ts:1371:23) at Module._extensions..js (node:internal/modules/cjs/loader:1137:10) at Object.require.extensions.<computed> [as .ts] (/path/to/my/source-code/node_modules/ts-node/src/index.ts:1374:12) at Module.load (node:internal/modules/cjs/loader:973:32) at Function.Module._load (node:internal/modules/cjs/loader:813:14) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12) at main (/path/to/my/source-code/node_modules/ts-node/src/bin.ts:331:12)"}}{"level":"ERROR","message":"This is the second error","service":"serverlessAirline","timestamp":"2021-12-12T22:12:39.377Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456","myCustomErrorKey":{"name":"Error","location":"/path/to/my/source-code/my-service/handler.ts:24","message":"Unexpected error #2","stack":"Error: Unexpected error #2 at lambdaHandler (/path/to/my/source-code/my-service/handler.ts:24:11) at Object.<anonymous> (/path/to/my/source-code/my-service/handler.ts:35:1) at Module._compile (node:internal/modules/cjs/loader:1108:14) at Module.m._compile (/path/to/my/source-code/node_modules/ts-node/src/index.ts:1371:23) at Module._extensions..js (node:internal/modules/cjs/loader:1137:10) at Object.require.extensions.<computed> [as .ts] (/path/to/my/source-code/node_modules/ts-node/src/index.ts:1374:12) at Module.load (node:internal/modules/cjs/loader:973:32) at Function.Module._load (node:internal/modules/cjs/loader:813:14) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12) at main (/path/to/my/source-code/node_modules/ts-node/src/bin.ts:331:12)"}}
Logging errors and log level
You can also log errors using the warn, info, and debug methods. Be aware of the log level though, you might miss those errors when analyzing the log later depending on the log level configuration.
The default log level is INFO and can be set using the logLevel constructor option or by using the LOG_LEVEL environment variable.
Logger supports the following log levels:
Level
Numeric value
DEBUG
8
INFO
12
WARN
16
ERROR
20
CRITICAL
24
SILENT
28
You can access the current log level by using the getLevelName() method. This method returns the name of the current log level as a string. If you want to change the log level at runtime, you can use the setLogLevel() method. This method accepts a string value that represents the log level you want to set, both lower and upper case values are supported.
If you want to access the numeric value of the current log level, you can use the level property. For example, if the current log level is INFO, logger.level property will return 12.
The SILENT log level provides a simple and efficient way to suppress all log messages without the need to modify your code. When you set this log level, all log messages, regardless of their severity, will be silenced.
This feature is useful when you want to have your code instrumented to produce logs, but due to some requirement or business decision, you prefer to not emit them.
By setting the log level to SILENT, which can be done either through the logLevel constructor option or by using the LOG_LEVEL environment variable, you can easily suppress all logs as needed.
Note
Use the SILENT log level with care, as it can make it more challenging to monitor and debug your application. Therefore, we advise using this log level judiciously.
The createChild method allows you to create a child instance of the Logger, which inherits all of the attributes from its parent. You have the option to override any of the settings and attributes from the parent logger, including its settings, any persistent attributes, and the log formatter. Once a child logger is created, the logger and its parent will act as separate instances of the Logger class, and as such any change to one won't be applied to the other.
The following example shows how to create multiple Loggers that share service name and persistent attributes while specifying different logging levels within a single Lambda invocation. As the result, only ERROR logs with all the inherited attributes will be displayed in CloudWatch Logs from the child logger, but all logs emitted will have the same service name and persistent attributes.
import{Logger}from'@aws-lambda-powertools/logger';// This logger has a service name, some persistent attributes// and log level set to INFOconstlogger=newLogger({serviceName:'serverlessAirline',logLevel:'INFO',persistentLogAttributes:{aws_account_id:'123456789012',aws_region:'eu-west-1',},});// This other logger inherits all the parent's attributes// but the log level, which is now set to ERRORconstchildLogger=logger.createChild({logLevel:'ERROR',});exportconsthandler=async(_event:unknown,_context:unknown):Promise<void>=>{logger.info('This is an INFO log, from the parent logger');logger.error('This is an ERROR log, from the parent logger');childLogger.info('This is an INFO log, from the child logger');childLogger.error('This is an ERROR log, from the child logger');};
{"level":"INFO","message":"This is an INFO log, from the parent logger","service":"serverlessAirline","timestamp":"2021-12-12T22:32:54.667Z","aws_account_id":"123456789012","aws_region":"eu-west-1","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}{"level":"ERROR","message":"This is an ERROR log, from the parent logger","service":"serverlessAirline","timestamp":"2021-12-12T22:32:54.670Z","aws_account_id":"123456789012","aws_region":"eu-west-1","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}{"level":"ERROR","message":"This is an ERROR log, from the child logger","service":"serverlessAirline","timestamp":"2021-12-12T22:32:54.670Z","aws_account_id":"123456789012","aws_region":"eu-west-1","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}
Use sampling when you want to print all the log items generated in your code, based on a percentage of your concurrent/cold start invocations.
You can do that by setting a "sample rate", a float value ranging from 0.0 (0%) to 1 (100%), by using a POWERTOOLS_LOGGER_SAMPLE_RATE env var or passing the sampleRateValue parameter in the Logger constructor.
This number represents the probability that a Lambda invocation will print all the log items regardless of the log level setting.
For example, by setting the "sample rate" to 0.5, roughly 50% of your lambda invocations will print all the log items, including the debug ones.
When is this useful?
In production, to avoid log data pollution and reduce CloudWatch costs, developers are encouraged to use the logger with logLevel equal to ERROR or WARN.
This means that only errors or warnings will be printed.
However, it might still be useful to print all the logs (including debug ones) of a very small percentage of invocations to have a better understanding of the behaviour of your code in production even when there are no errors.
Sampling decision happens at the Logger initialization. This means sampling may happen significantly more or less than depending on your traffic patterns, for example a steady low number of invocations and thus few cold starts.
If you want to reset the sampling decision and refresh it for each invocation, you can call the logger.refreshSampleRateCalculation() method at the beginning or end of your handler.
1 2 3 4 5 6 7 8 910111213141516171819202122232425
import{Logger}from'@aws-lambda-powertools/logger';// Notice the log level set to 'ERROR'constlogger=newLogger({logLevel:'ERROR',sampleRateValue:0.5,});exportconsthandler=async(_event:unknown,_context:unknown):Promise<void>=>{// This log item (equal to log level 'ERROR') will be printed to standard output// in all Lambda invocationslogger.error('This is an ERROR log');// These log items (below the log level 'ERROR') have ~50% chance// of being printed in a Lambda invocationlogger.debug('This is a DEBUG log that has 50% chance of being printed');logger.info('This is an INFO log that has 50% chance of being printed');logger.warn('This is a WARN log that has 50% chance of being printed');// Optional: refresh sample rate calculation on runtime// logger.refreshSampleRateCalculation();};
{"level":"ERROR","message":"This is an ERROR log","sampling_rate":"0.5","service":"serverlessAirline","timestamp":"2021-12-12T22:59:06.334Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}{"level":"DEBUG","message":"This is a DEBUG log that has 50% chance of being printed","sampling_rate":"0.5","service":"serverlessAirline","timestamp":"2021-12-12T22:59:06.337Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}{"level":"INFO","message":"This is an INFO log that has 50% chance of being printed","sampling_rate":"0.5","service":"serverlessAirline","timestamp":"2021-12-12T22:59:06.338Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}{"level":"WARN","message":"This is a WARN log that has 50% chance of being printed","sampling_rate":"0.5","service":"serverlessAirline","timestamp":"2021-12-12T22:59:06.338Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}
12345678
{"level":"ERROR","message":"This is an ERROR log","sampling_rate":"0.5","service":"serverlessAirline","timestamp":"2021-12-12T22:59:06.334Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}
{"level":"ERROR","message":"This is an ERROR log","sampling_rate":"0.5","service":"serverlessAirline","timestamp":"2021-12-12T22:59:06.334Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}{"level":"DEBUG","message":"This is a DEBUG log that has 50% chance of being printed","sampling_rate":"0.5","service":"serverlessAirline","timestamp":"2021-12-12T22:59:06.337Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}{"level":"INFO","message":"This is an INFO log that has 50% chance of being printed","sampling_rate":"0.5","service":"serverlessAirline","timestamp":"2021-12-12T22:59:06.338Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}{"level":"WARN","message":"This is a WARN log that has 50% chance of being printed","sampling_rate":"0.5","service":"serverlessAirline","timestamp":"2021-12-12T22:59:06.338Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}
12345678
{"level":"ERROR","message":"This is an ERROR log","sampling_rate":"0.5","service":"serverlessAirline","timestamp":"2021-12-12T22:59:06.334Z","xray_trace_id":"abcdef123456abcdef123456abcdef123456"}
You can customize the structure (keys and values) of your log items by passing a custom log formatter, an object that implements the LogFormatter abstract class.
1 2 3 4 5 6 7 8 9101112131415161718192021222324
import{Logger}from'@aws-lambda-powertools/logger';import{MyCompanyLogFormatter}from'./utils/formatters/MyCompanyLogFormatter';constlogger=newLogger({logFormatter:newMyCompanyLogFormatter(),logLevel:'DEBUG',serviceName:'serverlessAirline',sampleRateValue:0.5,persistentLogAttributes:{awsAccountId:process.env.AWS_ACCOUNT_ID,logger:{name:'@aws-lambda-powertools/logger',version:'0.0.1',},},});exportconsthandler=async(event,context):Promise<void>=>{logger.addContext(context);logger.info('This is an INFO log',{correlationIds:{myCustomCorrelationId:'foo-bar-baz'},});};
This is how the MyCompanyLogFormatter (dummy name) would look like:
import{LogFormatter}from'@aws-lambda-powertools/logger';import{LogAttributes,UnformattedAttributes,}from'@aws-lambda-powertools/logger/lib/types';// Replace this line with your own typetypeMyCompanyLog=LogAttributes;classMyCompanyLogFormatterextendsLogFormatter{publicformatAttributes(attributes:UnformattedAttributes):MyCompanyLog{return{message:attributes.message,service:attributes.serviceName,environment:attributes.environment,awsRegion:attributes.awsRegion,correlationIds:{awsRequestId:attributes.lambdaContext?.awsRequestId,xRayTraceId:attributes.xRayTraceId,},lambdaFunction:{name:attributes.lambdaContext?.functionName,arn:attributes.lambdaContext?.invokedFunctionArn,memoryLimitInMB:attributes.lambdaContext?.memoryLimitInMB,version:attributes.lambdaContext?.functionVersion,coldStart:attributes.lambdaContext?.coldStart,},logLevel:attributes.logLevel,timestamp:this.formatTimestamp(attributes.timestamp),// You can extend this functionlogger:{sampleRateValue:attributes.sampleRateValue,},};}}export{MyCompanyLogFormatter};
This is how the printed log would look:
1 2 3 4 5 6 7 8 910111213141516171819202122232425
{"message":"This is an INFO log","service":"serverlessAirline","awsRegion":"eu-west-1","correlationIds":{"awsRequestId":"c6af9ac6-7b61-11e6-9a41-93e812345678","xRayTraceId":"abcdef123456abcdef123456abcdef123456","myCustomCorrelationId":"foo-bar-baz"},"lambdaFunction":{"name":"shopping-cart-api-lambda-prod-eu-west-1","arn":"arn:aws:lambda:eu-west-1:123456789012:function:shopping-cart-api-lambda-prod-eu-west-1","memoryLimitInMB":128,"version":"$LATEST","coldStart":true},"logLevel":"INFO","timestamp":"2021-12-12T23:13:53.404Z","logger":{"sampleRateValue":"0.5","name":"aws-lambda-powertools-typescript","version":"0.0.1"},"awsAccountId":"123456789012"}
Custom Log formatter and Child loggers
It is not necessary to pass the LogFormatter each time a child logger is created. The parent's LogFormatter will be inherited by the child logger.
When unit testing your code that makes use of logger.addContext() or injectLambdaContext middleware and decorator, you can optionally pass a dummy Lambda Context if you want your logs to contain this information.
This is a Jest sample that provides the minimum information necessary for Logger to inject context data:
When unit testing your code with Jest you can use the POWERTOOLS_DEV environment variable in conjunction with the Jest --silent CLI option to suppress logs from Logger.