An SLF4J Logger implementation for AWS Lambda and CloudWatch.
Logger | Release | Javadoc |
---|---|---|
aws-lambda-slf4j-logger | ||
aws-lambda-slf4j-json-logger |
Created by gh-md-toc
Yet another SLF4J Simple, isn't it?
No, it isn't.
This implementation supports MDC to print out AWS request ID in start of every logging record and supports Markers too. And the killer feature: it solves the CRLF issue described by Frank Afriat in Solving the Java Aws Lambda logging problem - you don't have to prepare logging messages and stacktraces to log them on CloudWatch Logs.
The footprint of aws-lambda-slf4j-logger (36K) and aws-lambda-slf4j-json-logger (116K) are the same as slf4j-simple (16K) and much smaller than logback (888K).
There is a great original manual.
The sample code:
@Override
public String handleRequest(Map<String, Object> input, Context context) {
MDC.put("@aws-request-id@", context.getAwsRequestId());
logger.trace("trace message");
logger.debug("debug message");
logger.info("info message");
logger.warn("warning message");
logger.error("error message");
var marker = new BasicMarkerFactory().getMarker("important");
Stream.of("\n", "\r\n", "\r").forEach(injection -> {
logger.trace(marker, "CRLF{}injection", injection);
});
logger.warn("printable stacktrace", new Throwable("Printable Stacktrace Demo"));
return "done";
}
The log with aws-lambda-slf4j-logger:
983f71e5-9091-443b-8c01-6668120c0e5d INFO io.github.vitalijr2.slf4j_demo.BotHandler - info message
983f71e5-9091-443b-8c01-6668120c0e5d WARN io.github.vitalijr2.slf4j_demo.BotHandler - warning message
983f71e5-9091-443b-8c01-6668120c0e5d ERROR io.github.vitalijr2.slf4j_demo.BotHandler - error message
983f71e5-9091-443b-8c01-6668120c0e5d TRACE io.github.vitalijr2.slf4j_demo.BotHandler - CRLF
injection
983f71e5-9091-443b-8c01-6668120c0e5d TRACE io.github.vitalijr2.slf4j_demo.BotHandler - CRLF
injection
983f71e5-9091-443b-8c01-6668120c0e5d TRACE io.github.vitalijr2.slf4j_demo.BotHandler - CRLF
injection
983f71e5-9091-443b-8c01-6668120c0e5d WARN io.github.vitalijr2.slf4j_demo.BotHandler - printable stacktrace
There is a JSON option with aws-lambda-slf4j-json-logger:
{
"level": "INFO",
"logname": "io.github.vitalijr2.slf4j_demo.BotHandler",
"message": "info message",
"aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf"
}
{
"level": "WARN",
"logname": "io.github.vitalijr2.slf4j_demo.BotHandler",
"message": "warning message",
"aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf"
}
{
"level": "ERROR",
"logname": "io.github.vitalijr2.slf4j_demo.BotHandler",
"message": "error message",
"aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf"
}
{
"level": "TRACE",
"logname": "io.github.vitalijr2.slf4j_demo.BotHandler",
"message": "CRLF\ninjection",
"aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf"
}
{
"level": "TRACE",
"logname": "io.github.vitalijr2.slf4j_demo.BotHandler",
"message": "CRLF\r\ninjection",
"aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf"
}
{
"level": "TRACE",
"logname": "io.github.vitalijr2.slf4j_demo.BotHandler",
"message": "CRLF\rinjection",
"aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf"
}
{
"stack-trace": "java.lang.Throwable: Printable Stacktrace Demo\n\tat io.github.vitalijr2.slf4j_demo.BotHandler.handleRequest(BotHandler.java:36)\n\tat io.github.vitalijr2.slf4j_demo.BotHandler.handleRequest(BotHandler.java:12)\n\tat lambdainternal.EventHandlerLoader$PojoHandlerAsStreamHandler.handleRequest(EventHandlerLoader.java:205)\n\tat lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:905)\n\tat lambdainternal.AWSLambda.startRuntime(AWSLambda.java:261)\n\tat lambdainternal.AWSLambda.startRuntime(AWSLambda.java:200)\n\tat lambdainternal.AWSLambda.main(AWSLambda.java:194)\n",
"level": "WARN",
"logname": "io.github.vitalijr2.slf4j_demo.BotHandler",
"message": "printable stacktrace",
"aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf"
}
The configuration is similar to SLF4J Simple.
It looks for the lambda-logger.properties
resource and read properties:
- dateTimeFormat - The date and time format to be used in the output messages. The pattern describing the date and time format is defined by SimpleDateFormat. If the format is not specified or is invalid, the number of milliseconds since start up will be output.
- defaultLogLevel - Default log level for all instances of LambdaLogger. Must be one of (trace, debug, info, warn, error), a value is case-insensitive. If not specified, defaults to info.
- levelInBrackets - Should the level string be output in brackets?
Defaults to
false
. - log.a.b.c - Logging detail level for a LambdaLogger instance named a.b.c.
- requestId - Set the context name of AWS request ID.
Defaults to
AWS_REQUEST_ID
. - showDateTime - Set to
true
if you want the current date and time to be included in output messages. Defaults tofalse
. - showLogName - Set to
true
if you want the Logger instance name to be included in output messages. Defaults totrue
. - showShortLogName - Set to
true
if you want the last component of the name to be included in output messages. Defaults tofalse
. - showThreadId - If you would like to output the current thread id,
then set to
true
. Defaults tofalse
. - showThreadName - Set to
true
if you want to output the current thread name. Defaults tofalse
.
The environment variables overrides the properties: LOG_AWS_REQUEST_ID, LOG_DATE_TIME_FORMAT, LOG_DEFAULT_LEVEL, LOG_LEVEL_IN_BRACKETS, LOG_SHOW_DATE_TIME, LOG_SHOW_NAME, LOG_SHOW_SHORT_NAME, LOG_SHOW_THREAD_ID, LOG_SHOW_THREAD_NAME.
SLF4J 2.0.9 allows a provider to be explicitly specified. Since AWS Lambda Environment does not provide any configuration options to set what options should be used on startup, the trick is to use the JAVA_TOOL_OPTIONS environment variable.
If your AWS Java Lambda has some SLF4J providers and you want
to point one of them, that needs to setup a System property
named slf4j.provider
, as in the following:
Other AWS centric loggers are SLF4J/Logback Appender, slf4j-simple-lambda, Logback's CloudWatch appender and CloudWatchLogs Java appender.
Please read Contributing.
See Changelog
- Replace the custom output to stdout with AWS LambdaLogger, the main idea from @igorakkerman SLF4J/Logback Appender.
Copyright 2022-2024 Vitalij Berdinskih
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.