SLF4J based, simple, efficient logger.
This logger is great for applications that use synchronous output or run in single-thread like command line applications or Serverless applications.
Features:
- Performance optimizations.
- GraalVM friendly.
- JSON format support.
- Environment variables logging.
- slf4j-simple-logger compatible configuration.
And more...
implementation "io.goodforgod:slf4j-simple-logger:2.0.0"
<dependency>
<groupId>io.goodforgod</groupId>
<artifactId>slf4j-simple-logger</artifactId>
<version>2.0.0</version>
</dependency>
Below is example of logged message in text format:
Marker myMarker = MarkerFactory.getMarker("my_marker");
myMarker.add(MarkerFactory.getMarker("my_marker_ref"));
logger.debug(myMarker, "Message is printed for this logger");
Result logged message:
Date Time Implementation Log Level Markers Environment variables Thread Logger Name Log Message
| | | | | | | |
___________|__________ ______|_______ __|__ ________________|______________ __________________|_______________ __|__ ___________|___________ ________________|________________
| | | | | | | | | | | | | | |
| | | | | | | | | | | | | | |
2022-02-23T15:43:40.331 [0.9.0-SNAPSHOT] [DEBUG] [markers=my_marker,my_marker_ref] [SESSION=Console, PROCESSOR_LEVEL=6] [main] io.goodforgod.Application - Message is printed for this logger
Below is example of logged message in json format:
Exception e = new RuntimeException();
Marker myMarker = MarkerFactory.getMarker("my_marker");
myMarker.add(MarkerFactory.getMarker("my_marker_ref"));
logger.debug(myMarker, "Message is printed for this logger", e);
Result logged message:
{
"timestamp": "2022-02-23T15:43:40.331",
"implementation": "0.9.0-SNAPSHOT",
"level": "DEBUG",
"thread": "main",
"logger": "io.goodforgod.Application",
"markers": ["my_marker", "my_marker_ref"],
"environment": [
{
"name": "SESSION",
"value": "Console"
},
{
"name": "PROCESSOR_LEVEL",
"value": "6"
}
],
"message": "Message is printed for this logger",
"exception": "Ops",
"stacktrace": [
{
"clazz": "io.goodforgod.slf4j.simplelogger.JsonLoggerLayoutTests",
"message": "Ops",
"method": "throwableOutput:279"
},
{
"clazz": "jdk.internal.reflect.NativeMethodAccessorImpl",
"method": "invoke0:-2"
}
]
}
This implementation is based on default slf4j-simple-logger, but there are plenty of performance and feature improvements.
Some cases are 200% faster others are 800% faster, you can read more about here in my JVM benchmark.
There is option to output logged messages in different formats, currently supported formats:
- TEXT
- JSON
You can check example of each format here.
Configuration for format is below for TEXT (default value).
org.slf4j.simpleLogger.format=TEXT
And same for JSON:
org.slf4j.simpleLogger.format=JSON
There are three options to output date & time:
- DATE_TIME - in format uuuu-MM-dd'T'HH:mm:ss.SSS, example is - 2022-02-23T15:43:40.331 (read more about Java Date & Time formats here)
- TIME - in format HH:mm:ss.SSS, example is - 15:43:40.331 (read more about Java Date & Time formats here)
- UNIX_TIME - time since epoch.
- MILLIS_FROM_START - Millis from SimpleLoggerConfiguration initialization (may not properly work in GraalVM setups)
You can also change formatter for DATE_TIME and TIME via configuration:
org.slf4j.simpleLogger.dateTimeFormat=uuuu-MM-dd'T'HH:mm:ss.SSS
There is configuration to abbreviate logger name, like in logback.
If configuration is:
org.slf4j.simpleLogger.showShortLogName=false
org.slf4j.simpleLogger.showLogName=true
org.slf4j.simpleLogger.logNameLength=36
And logger is:
package io.goodforgod.internal.logger.example;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
public class Application {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Application.class);
logger.info("Message is printed for this logger");
}
}
Then logger name will be outputted like:
2022-02-23T15:43:40.331 [DEBUG] i.g.i.logger.example.Application - Message is printed for this logger
Abbreviation happened to full logger name: io.goodforgod.internal.logger.example.Application -> i.g.i.logger.example.Application
It is possible to log environment, format how it will be outputted can be seen here.
If the configuration is:
# Set environment names to show in output. Envs will be printed out in order they preserve in configuration.
org.slf4j.simpleLogger.environments=SESSION,PROCESSOR_LEVEL
# Set to true to show environment with nullable values.
org.slf4j.simpleLogger.environmentShowNullable=false
# Set to true to show environment names.
org.slf4j.simpleLogger.environmentShowName=true
# Set to true to caches environment values on configuration initialization and then always uses them when logging.
org.slf4j.simpleLogger.environmentRememberOnStart=false
Then the output will be:
2022-02-23T15:43:40.331 [DEBUG] [SESSION=Console, PROCESSOR_LEVEL=6] [main] io.goodforgod.Application - Message is printed for this logger
Environment variables are printed in order they preserve in configuration (in example above first SESSION, then PROCESSOR_LEVEL).
You can use environment variables to configure values for property config.
Below is example where there are two environment variables are used for configuration (SHOW_LOG_NAME and LOG_NAME_LENGTH):
org.slf4j.simpleLogger.showLogName=${SHOW_LOG_NAME}
org.slf4j.simpleLogger.logNameLength=${LOG_NAME_LENGTH:36}
If environment variable value is absent, then default value is used.
Environment variable configuration can be refresh in runtime. This can be useful when environment changed, and it is required to update logger config without stopping application.
SimpleLoggerFactory.refresh();
Only these properties can be changed in runtime:
# Default logging level for all loggers. Must be one of ("TRACE", "DEBUG", "INFO", "WARN", or "ERROR"). (default INFO)
org.slf4j.simpleLogger.defaultLogLevel=INFO
# Set logging message output format. Must be one of ("TEXT", "JSON"). (default TEXT)
org.slf4j.simpleLogger.format=TEXT
# Set to true to show current datetime in output. (default true)
org.slf4j.simpleLogger.showDateTime=true
# Set datetime output type. Must be one of ("TIME", "DATE_TIME", "UNIX_TIME", "MILLIS_FROM_START"). (default DATE_TIME)
org.slf4j.simpleLogger.dateTimeOutputType=DATE_TIME
# The date and time formatter pattern to be used in the output. (default uuuu-MM-dd'T'HH:mm:ss.SSS)
org.slf4j.simpleLogger.dateTimeFormat=uuuu-MM-dd'T'HH:mm:ss.SSS
# Set ZoneId to use as adjustment for DATE_TIME or TIME. (default ZoneId.systemDefault())
org.slf4j.simpleLogger.zoneId=UTC
# Set to true if to show application implementation version from MANIFEST.MF (default false)
org.slf4j.simpleLogger.showImplementationVersion=false
# Set to true to show logging level in brackets like: [INFO] (default true)
org.slf4j.simpleLogger.levelInBrackets=true
# Set to true if to show current thread in output. (default false)
org.slf4j.simpleLogger.showThreadName=false
# Set to true if to show marker parameter values. (default false)
org.slf4j.simpleLogger.showMarkers=false
# Set to true to show only class name in output. (default false)
org.slf4j.simpleLogger.showShortLogName=false
# Set to true if to show full class name in output (package + class name). (default true)
org.slf4j.simpleLogger.showLogName=true
# Set maximum logger name to output and abbreviate if it exceeds length. (default null)
org.slf4j.simpleLogger.logNameLength=36
# Set environment names to show in output. Envs will be printed out in order they preserve in configuration. (default null)
org.slf4j.simpleLogger.environments=SESSION_ID,ORIGIN,HOST
# Set to true to show environment with nullable values. (default false)
org.slf4j.simpleLogger.environmentShowNullable=false
# Set to true to show environment names. (default false)
org.slf4j.simpleLogger.environmentShowName=false
There is possibility to split WARN and ERROR logs to different output.
If configuration is:
# Set default logger output file or System.out or System.error (default System.out)
org.slf4j.simpleLogger.logFile=System.out
# Set logger WARN logs output file or System.out or System.error (default System.out)
org.slf4j.simpleLogger.logFileWarn=System.error
# Set logger ERROR logs output file or System.out or System.error (default System.out)
org.slf4j.simpleLogger.logFileError=System.error
Then all logs of TRACE, DEBUG, INFO will be forwarded to System.out and all WARN & ERROR logs will be forwarded to System.error.
Callable or Supplier can be passed as arguments to logger and computed correctly:
Callable<String> supplier = () -> "argument";
logger.info("Value supplier is {}.", supplier);
Resulted output:
Value supplier is argument.
You can change loggers level using io.goodforgod.slf4j.simplelogger.SimpleLoggerFactory:
SimpleLoggerFactory factory = (SimpleLoggerFactory) LoggerFactory.getILoggerFactory();
factory.setLogLevel(Level.DEBUG);
Or you can use predicate to filter out loggers:
SimpleLoggerFactory factory = (SimpleLoggerFactory) LoggerFactory.getILoggerFactory();
factory.setLogLevel(Level.DEBUG, logger -> logger.getName().startsWith("io.goodforgod.internal.logger.example"));
Library is fully compatibly with slf4j-simple-logger configuration, you can check it here.
Example of full simplelogger.properties file:
# Default logging level for all loggers. Must be one of ("TRACE", "DEBUG", "INFO", "WARN", or "ERROR"). (default INFO)
org.slf4j.simpleLogger.defaultLogLevel=INFO
# Set logging message output format. Must be one of ("TEXT", "JSON"). (default TEXT)
org.slf4j.simpleLogger.format=TEXT
# Set to true to show current datetime in output. (default true)
org.slf4j.simpleLogger.showDateTime=true
# Set datetime output type. Must be one of ("TIME", "DATE_TIME", "UNIX_TIME", "MILLIS_FROM_START"). (default DATE_TIME)
org.slf4j.simpleLogger.dateTimeOutputType=DATE_TIME
# The date and time formatter pattern to be used in the output. (default uuuu-MM-dd'T'HH:mm:ss.SSS)
org.slf4j.simpleLogger.dateTimeFormat=uuuu-MM-dd'T'HH:mm:ss.SSS
# Set ZoneId to use as adjustment for DATE_TIME or TIME. (default ZoneId.systemDefault())
org.slf4j.simpleLogger.zoneId=UTC
# Set to true if to show application implementation version from MANIFEST.MF (default false)
org.slf4j.simpleLogger.showImplementationVersion=false
# Set to true to show logging level in brackets like: [INFO] (default true)
org.slf4j.simpleLogger.levelInBrackets=true
# Set to true if to show current thread in output. (default false)
org.slf4j.simpleLogger.showThreadName=false
# Set to true if to show marker parameter values. (default false)
org.slf4j.simpleLogger.showMarkers=false
# Set to true to show only class name in output. (default false)
org.slf4j.simpleLogger.showShortLogName=false
# Set to true if to show full class name in output (package + class name). (default true)
org.slf4j.simpleLogger.showLogName=true
# Set maximum logger name to output and abbreviate if it exceeds length. (default null)
org.slf4j.simpleLogger.logNameLength=36
# Set logger output charset to use (default UTF-8)
org.slf4j.simpleLogger.charset=UTF-8
# Set environment names to show in output. Envs will be printed out in order they preserve in configuration. (default null)
org.slf4j.simpleLogger.environments=SESSION_ID,ORIGIN,HOST
# Set to true to show environment with nullable values. (default false)
org.slf4j.simpleLogger.environmentShowNullable=false
# Set to true to show environment names. (default false)
org.slf4j.simpleLogger.environmentShowName=false
# Set to true to caches environment values on configuration initialization and then always uses them when logging. (default false)
org.slf4j.simpleLogger.environmentRememberOnStart=false
# Set default logger output file or System.out or System.error (default System.out)
org.slf4j.simpleLogger.logFile=System.out
# Set logger WARN logs output file or System.out or System.error (default System.out)
org.slf4j.simpleLogger.logFileWarn=System.out
# Set logger ERROR logs output file or System.out or System.error (default System.out)
org.slf4j.simpleLogger.logFileError=System.out
# Set log level for custom loggers
org.slf4j.simpleLogger.log.path.to.class=WARN
Starting from version 2.0.0 library ships for SLF4J 2.0.0+. (Based on SLF4J 2.0.7+)
Starting from version 1.0.0 library ships for SLF4J 1.7.5+. (Based on SLF4J 1.7.36+)
This project licensed under the Apache License 2.0 - see the LICENSE file for details