Skip to content

Ferdinand Agyei-Yeboah

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 threads
log4j2.isThreadContextMapInheritable=true
# custom xml file location
log4j2.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 />
<SizeBasedTriggeringPolicy
size="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 class
log.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 classes
AdditivityFalseStdOutErrorLogger 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 our Console 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 the INFO 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.
      • AdditivityFalseStdOutErrorLogger.
        • The AdditivityFalseStdOutErrorLogger refers to our Console Appender meaning events from this class will also be logged to the console.
        • It is set to ERROR meaning it will only log events at ERROR level or below (much less INFO 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.

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 log
Dec 16 2022 06:29:45,648 EST [main] WARN o.e.s.l.AdditivityTrueStdOutLogger [{}] In AdditivityTrueStdOutLogger: I am an warning log
Dec 16 2022 06:29:45,648 EST [main] ERROR o.e.s.l.AdditivityTrueStdOutLogger [{}] In AdditivityTrueStdOutLogger: I am an error log
Dec 16 2022 06:29:45,649 EST [main] INFO o.e.s.l.UnTargetedLogger [{}] In UnTargetedLogger: I am an info log
Dec 16 2022 06:29:45,649 EST [main] WARN o.e.s.l.UnTargetedLogger [{}] In UnTargetedLogger: I am an warning log
Dec 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 log
Dec 16 2022 06:29:45,648 EST [main] INFO o.e.s.l.AdditivityTrueStdOutLogger [{}] In AdditivityTrueStdOutLogger: I am an info log
Dec 16 2022 06:29:45,648 EST [main] WARN o.e.s.l.AdditivityTrueStdOutLogger [{}] In AdditivityTrueStdOutLogger: I am an warning log
Dec 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:


Software Engineering Tutorials & Best Practices