Quick Log4j2 Notes
November 27, 2022
Sample Log4j2 Configuration and Explanation
Below is a sample log4j2 properties file and configuration file. By default log4j2 searches for a file called log4j2.xml on the classpath but you can configure it to search for a specific file using a log4j2.component.properties
properties file. Make sure to replace anything that starts with “REPLACE_WITH”.
log4j2.component.properties
- Optional file for configuring log4j2 system properties.
# Log4j2 properties here: https://logging.apache.org/log4j/2.x/manual/configuration.html#SystemProperties# inherit threadcontext for child threadslog4j2.isThreadContextMapInheritable=true# custom xml file locationlog4j2.configurationFile=<REPLACE_WITH_CUSTOM_PATH_TO_XML_FILE>
log4j2.xml
- Main log4j2 configuration file.
<!-- the status in the configuration is the level that log4j2 will print its own events at. Change to debug if having log4j2 issues--><Configuration status="INFO"><Properties><Property name="root.folder"><REPLACE_WITH_APPLICATION_ROOT></Property><Property name="logs.path">${root.folder}/logs</Property><Property name="logs.archive.path">${logs.path}/archive</Property><Property name="logs.filename">app.log</Property><!-- Ansi (highlighting, coloring, bolding, etc..) can be used for console, non ansi should be used for files (unless have an ascii viewer for logs like vscode ansi extension). Consider using noConsoleNoAnsi option in PatternLayout instead of having two patternLayouts. --><Property name="pattern.layout.ansi">%d{MMM dd yyyy HH:mm:ss,SSS}{EST} EST [%style{%thread}{bright,blue}] %highlight{%level} %style{%C{1.}}{bright,yellow} [%X] %ex%m%n</Property><Property name="pattern.layout.non.ansi">%d{MMM dd yyyy HH:mm:ss,SSS}{EST} EST [%thread] %level %C{1.} [%X] %ex%m%n</Property></Properties><Appenders><Console name="Console" target="SYSTEM_OUT"><PatternLayout pattern="${pattern.layout.ansi}"/></Console><RollingFile name="LocalFile"fileName="${logs.path}/${logs.filename}"filePattern="${logs.archive.path}/${logs.filename}.%d{yyyy-MM-dd-hh-mm}.gz"><PatternLayout pattern="${pattern.layout.non.ansi}"/><Policies><!-- rollover on startup, daily and when the file reaches 10 MegaBytes --><OnStartupTriggeringPolicy /><SizeBasedTriggeringPolicysize="10 MB" /><TimeBasedTriggeringPolicy /></Policies></RollingFile></Appenders><Loggers><Root level="INFO"><AppenderRef ref="LocalFile"/></Root><Logger name="org.example.scratch.log4j2_learning.AdditivityTrueStdOutLogger" level="TRACE" additivity="true"><AppenderRef ref="Console"/></Logger><Logger name="org.example.scratch.log4j2_learning.AdditivityFalseStdOutErrorLogger" level="ERROR" additivity="false"><AppenderRef ref="Console"/></Logger></Loggers></Configuration>
Log4J2Scratch.java
- Java file for demonstrating logging configuration.
package org.example.scratch.log4j2_learning;/** This file is used to demonstrate log4j2 configuration.*/import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;//@Log4j2 - Lombok annotation to autogenerate logger.public class Log4j2Scratch {private final static Logger log = LogManager.getLogger(Log4j2Scratch.class);private final static String logPrefix = "In Log4j2Scratch: ";public static void main(String[] args) {//Testing logger for this classlog.info(logPrefix + "I am an info log.");log.warn(logPrefix + "I am an warning log.");log.error(logPrefix + "I am an error log.");//Testing loggers for separate classesAdditivityFalseStdOutErrorLogger aFalse = new AdditivityFalseStdOutErrorLogger();AdditivityTrueStdOutLogger aTrue = new AdditivityTrueStdOutLogger();UnTargetedLogger unT = new UnTargetedLogger();}}class AdditivityFalseStdOutErrorLogger {private final static Logger log = LogManager.getLogger(AdditivityFalseStdOutErrorLogger.class);private String logPrefix = "In AdditivityFalseStdOutErrorLogger: ";public AdditivityFalseStdOutErrorLogger() {log.info(logPrefix + "I am an info log");log.warn(logPrefix + "I am an warning log");log.error(logPrefix + "I am an error log");}}class AdditivityTrueStdOutLogger {private final static Logger log = LogManager.getLogger(AdditivityTrueStdOutLogger.class);private String logPrefix = "In AdditivityTrueStdOutLogger: ";public AdditivityTrueStdOutLogger() {log.info(logPrefix + "I am an info log");log.warn(logPrefix + "I am an warning log");log.error(logPrefix + "I am an error log");}}class UnTargetedLogger {private final static Logger log = LogManager.getLogger(UnTargetedLogger.class);private String logPrefix = "In UnTargetedLogger: ";public UnTargetedLogger() {log.info(logPrefix + "I am an info log");log.warn(logPrefix + "I am an warning log");log.error(logPrefix + "I am an error log");}}
Explanation of Log4j2.xml
Properties
- The properties section lets you define variables to reference throughout your log4j2 configuration. In this case we defined variables for log path and naming, as well as pattern layout (which we will talk about later) which we used further down in the configuration.
Appenders
- Appenders are responsible for writing log data to output locations. This can be the console (standard out), a file, database, http endpoint, etc. In this case we created two appenders. We used a ConsoleAppender for writing to standard out and a RollingFileAppender to write a file to local disk.
- Layouts are used by appenders to structure the output logs. The PatternLayout layout is used to determine the format of single line text logs. You can include and the log with things like date, timezone, log level, thread, class name and more to your liking.
Loggers
- Loggers define what appenders the java classes in your code will write to.
- RootLogger
- The RootLogger must always be present and all java classes will use it by default unless otherwise configured (more on that now).
- Class Specific Loggers
- Apart from the RootLogger, more specific loggers can be defined that will determine how a selected class will write its logs. In our case, we created specific loggers for the org.example.scratch.log4j2_learning.AdditivityTrueStdOutLogger and org.example.scratch.log4j2_learning.AdditivityFalseStdOutErrorLogger classes in our java code.
AdditivityTrueStdOutLogger
.- The
AdditivityTrueStdOutLogger
refers to ourConsole
Appender meaning events from this class will be logged to the console. - It is set to
TRACE
meaning it will log events at a lower level of detail than theINFO
set by the RootLogger (see “log levels” in the docs to see how the levels compare). - Since
additivity="true"
, it will log to the Console in addition to the RootLogger logging its events in the file. So we should see this logger’s events in both the console and the file.
- The
AdditivityFalseStdOutErrorLogger
.- The
AdditivityFalseStdOutErrorLogger
refers to ourConsole
Appender meaning events from this class will also be logged to the console. - It is set to
ERROR
meaning it will only log events atERROR
level or below (much lessINFO
level). - Since
additivity="false"
, it will log to the Console instead of the RootLogger logging its events in the file. Meaning we will see this logger’s events in the console but not the file.
- The
With this explanation, consider what logs should be printed from the Log4j2Scratch.java
code. Note that the code prints out at various log levels each for different classes. The output of running that file will look like this.
File output of Log4j2Scratch testing file - app.log
Dec 16 2022 06:29:45,644 EST [main] INFO o.e.s.l.Log4j2Scratch [{}] In Log4j2Scratch: I am an info log.Dec 16 2022 06:29:45,647 EST [main] WARN o.e.s.l.Log4j2Scratch [{}] In Log4j2Scratch: I am an warning log.Dec 16 2022 06:29:45,648 EST [main] ERROR o.e.s.l.Log4j2Scratch [{}] In Log4j2Scratch: I am an error log.Dec 16 2022 06:29:45,648 EST [main] INFO o.e.s.l.AdditivityTrueStdOutLogger [{}] In AdditivityTrueStdOutLogger: I am an info logDec 16 2022 06:29:45,648 EST [main] WARN o.e.s.l.AdditivityTrueStdOutLogger [{}] In AdditivityTrueStdOutLogger: I am an warning logDec 16 2022 06:29:45,648 EST [main] ERROR o.e.s.l.AdditivityTrueStdOutLogger [{}] In AdditivityTrueStdOutLogger: I am an error logDec 16 2022 06:29:45,649 EST [main] INFO o.e.s.l.UnTargetedLogger [{}] In UnTargetedLogger: I am an info logDec 16 2022 06:29:45,649 EST [main] WARN o.e.s.l.UnTargetedLogger [{}] In UnTargetedLogger: I am an warning logDec 16 2022 06:29:45,649 EST [main] ERROR o.e.s.l.UnTargetedLogger [{}] In UnTargetedLogger: I am an error log
Console output of Log4j2Scratch testing file
Dec 16 2022 06:29:45,648 EST [main] ERROR o.e.s.l.AdditivityFalseStdOutErrorLogger [{}] In AdditivityFalseStdOutErrorLogger: I am an error logDec 16 2022 06:29:45,648 EST [main] INFO o.e.s.l.AdditivityTrueStdOutLogger [{}] In AdditivityTrueStdOutLogger: I am an info logDec 16 2022 06:29:45,648 EST [main] WARN o.e.s.l.AdditivityTrueStdOutLogger [{}] In AdditivityTrueStdOutLogger: I am an warning logDec 16 2022 06:29:45,648 EST [main] ERROR o.e.s.l.AdditivityTrueStdOutLogger [{}] In AdditivityTrueStdOutLogger: I am an error log
You can see the app.log
file contains the logs for all the classes except the AdditivityFalseStdOutErrorLogger
and everything is printed at an INFO
level (see log level docs). The console includes both the AdditivityTrueStdOutLogger
and AdditivityFalseStdOutErrorLogger
logs but only at an ERROR level for AdditivityFalseStdOutErrorLogger
.
Links:
- Log4j2 docs: Architecture / Configuration / Appenders / Layouts / Filters
- ANSI: https://notes.burke.libbey.me/ansi-escape-codes/