Logger
Logger provides an opinionated logger with output structured as JSON.
Key features¶
- Capturing key fields from the Lambda context, cold starts, and structure logging output as JSON.
- Logging Lambda invocation events when instructed (disabled by default).
- Printing all the logs only for a percentage of invocations via log sampling (disabled by default).
- Appending additional keys to structured logs at any point in time.
- Providing a custom log formatter (Bring Your Own Formatter) to output logs in a structure compatible with your organizationās Logging RFC.
Getting started¶
Installation¶
Install the library in your project:
1 |
|
Usage¶
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.
1 2 3 4 5 6 7 |
|
Utility settings¶
The library has three optional settings, which can be set via environment variables or passed 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) | POWERTOOLS_LOG_LEVEL |
INFO |
DEBUG , INFO , WARN , ERROR , CRITICAL , SILENT |
ERROR |
logLevel |
Sample rate | 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 |
0.1 |
sampleRateValue |
See all environment variables in the Environment variables section. Check API docs to learn more about Logger constructor options.
Example using AWS Serverless Application Model (SAM)¶
1 2 3 4 5 6 7 8 9 10 11 |
|
1 2 3 4 5 6 7 8 9 |
|
Standard structured keys¶
Your Logger will include the following keys to your structured logging (default log formatter):
Key | Example | Note |
---|---|---|
level: string |
INFO |
Logging level set for the Lambda function's invocation |
message: string |
Query performed to DynamoDB |
A descriptive, human-readable representation of this log item |
sampling_rate: float |
0.1 |
When enabled, it prints all the logs of a percentage of invocations, e.g. 10% |
service: string |
serverlessAirline |
A unique name identifier of the service this Lambda function belongs to, by default service_undefined |
timestamp: string |
2011-10-05T14:48:00.000Z |
Timestamp string in simplified extended ISO format (ISO 8601) |
xray_trace_id: string |
1-5759e988-bd862e3fe1be46a994272793 |
X-Ray Trace ID. This value is always presented in Lambda environment, whether tracing is enabled or not. Logger will always log this value. |
error: Object |
{ name: "Error", location: "/my-project/handler.ts:18", message: "Unexpected error #1", stack: "[stacktrace]"} |
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.
Capturing Lambda context info¶
You can enrich your structured logs with key Lambda context information in multiple ways.
This functionality will include the following keys in your structured logs:
Key | Example |
---|---|
cold_start: bool |
false |
function_name string |
shopping-cart-api-lambda-prod-eu-west-1 |
function_memory_size: number |
128 |
function_arn: string |
arn:aws:lambda:eu-west-1:123456789012:function:shopping-cart-api-lambda-prod-eu-west-1 |
function_request_id: string |
c6af9ac6-7b61-11e6-9a41-93e812345678 |
A note about Middy
Currently we support only Middy v3.x
that you can install it by running npm i @middy/core@~3
.
Check their docs to learn more about Middy and its middleware stack as well as best practices when working with Powertools.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Note
The class method decorators in this project follow the experimental implementation enabled via the experimentalDecorators
compiler option in TypeScript. Additionally, they are implemented in a way that fits asynchronous methods. When decorating a synchronous method, the decorator replaces its implementation with an asynchronous one causing the caller to have to await
the now decorated method.
If this is not the desired behavior, you can call the logger.injectLambdaContext()
method directly in your handler.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
- Binding your handler method allows your handler to access
this
within the class methods.
1 2 3 4 5 6 7 8 9 |
|
In each case, the printed log will look like this:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Log incoming event¶
When debugging in non-production environments, you can instruct Logger to log the incoming event with the middleware/decorator parameter logEvent
.
Warning
This is disabled by default to prevent sensitive info being logged
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
- Binding your handler method allows your handler to access
this
within the class methods.
Use POWERTOOLS_LOGGER_LOG_EVENT
environment variable to enable or disable (true
/false
) this feature.
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
Logger will automatically ignore any key with an undefined
value
Clearing all state¶
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
- 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 9 10 11 12 13 14 15 16 17 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Appending additional data to a single log item¶
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Logging errors¶
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 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
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.
Advanced¶
Log levels¶
The default log level is INFO
and can be set using the logLevel
constructor option or by using the POWERTOOLS_LOG_LEVEL
environment variable.
We support 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.
1 2 3 4 5 6 7 |
|
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
.
Silencing logs¶
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 POWERTOOLS_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.
AWS Lambda Advanced Logging Controls (ALC)¶
With AWS Lambda Advanced Logging Controls (ALC), you can control the output format of your logs as either TEXT
or JSON
and specify the minimum accepted log level for your application. Regardless of the output format setting in Lambda, we will always output JSON formatted logging messages.
When you have this feature enabled, log messages that donāt meet the configured log level are discarded by Lambda. For example, if you set the minimum log level to WARN
, you will only receive WARN
and ERROR
messages in your AWS CloudWatch Logs, all other log levels will be discarded by Lambda.
sequenceDiagram
title Lambda ALC allows WARN logs only
participant Lambda service
participant Lambda function
participant Application Logger
Note over Lambda service: AWS_LAMBDA_LOG_LEVEL="WARN"
Lambda service->>Lambda function: Invoke (event)
Lambda function->>Lambda function: Calls handler
Lambda function->>Application Logger: logger.warn("Something happened")
Lambda function-->>Application Logger: logger.debug("Something happened")
Lambda function-->>Application Logger: logger.info("Something happened")
Lambda service->>Lambda service: DROP INFO and DEBUG logs
Lambda service->>CloudWatch Logs: Ingest error logs
Priority of log level settings in Powertools for AWS Lambda
When the Advanced Logging Controls feature is enabled, we are unable to increase the minimum log level below the AWS_LAMBDA_LOG_LEVEL
environment variable value, see AWS Lambda service documentation for more details.
We prioritise log level settings in this order:
AWS_LAMBDA_LOG_LEVEL
environment variable- Setting the log level in code using the
logLevel
constructor option, or by calling thelogger.setLogLevel()
method POWERTOOLS_LOG_LEVEL
environment variable
In the event you have set a log level in Powertools to a level that is lower than the ACL setting, we will output a warning log message informing you that your messages will be discarded by Lambda.
Using multiple Logger instances across your code¶
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
Sampling logs¶
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 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
1 2 3 4 5 6 7 8 |
|
Custom Log formatter (Bring Your Own Formatter)¶
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 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
This is how the MyCompanyLogFormatter
(dummy name) would look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
This is how the printed log would look:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
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.
Testing your code¶
Inject Lambda Context¶
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:
1 2 3 4 5 6 7 8 |
|
Tip
If you don't want to declare your own dummy Lambda Context, you can use ContextExamples.helloworldContext
from @aws-lambda-powertools/commons
.
Suppress logs with Jest¶
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.
Disabling logs while testing with Jest | |
---|---|
1 |
|