Learn to configure log4j2.xml file to output the log statements to console, rolling files etc. Learn to configure log4j2 appenders, levels and patterns.
Apache Log4j2 is an upgrade to Log4j 1.x that provides significant improvements over its predecessor such as performance improvement, automatic reloading of modified configuration files, Java 8 lambda support and custom log levels.
If not upgraded already, it is highly recommended to upgrade Log4j2 to the latest version 2.16.0 which has the fix for a recently found vulnerability CVE-2021-45046. Read the latest updates to the library here.
1. Log4j2 Dependencies
Find the latest version from this link. Please note that using Log4j2 with SLF4J is recommended approach.
1.1. Maven
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.16.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.16.0</version>
</dependency>
1.2 Gradle
dependencies {
implementation 'org.apache.logging.log4j:log4j-api:2.16.0'
implementation 'org.apache.logging.log4j:log4j-core:2.16.0'
}
2. Console Appender – Logs to Cosole
We can use below log4j2.xml
file logging output into console. Please note that if no configuration file could be located then DefaultConfiguration
will be used. The default configuration causes logging output to go to the console.
<?xml version="1.0" encoding="UTF-8"?>
<!-- Extra logging related to initialization of Log4j.
Set to debug or trace if log4j initialization is failing. -->
<Configuration status="warn">
<Appenders>
<!-- Console appender configuration -->
<Console name="console" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</Console>
</Appenders>
<Loggers>
<!-- Root logger referring to console appender -->
<Root level="info" additivity="false">
<AppenderRef ref="console" />
</Root>
</Loggers>
</Configuration>
3. Rolling File Appender – Logs to File
We can use the below log4j2.xml file logging output with time and size based rolling files.
The given configuration rolls over the log everyday, or when the log file size gets greater than 10 MB. It also deletes all log files older than 30 days.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Properties>
<Property name="basePath">C:/temp/logs</Property>
</Properties>
<Appenders>
<RollingFile name="fileLogger"
fileName="${basePath}/app.log"
filePattern="${basePath}/app-%d{yyyy-MM-dd}.log">
<PatternLayout>
<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
<SizeBasedTriggeringPolicy size="10MB" />
</Policies>
<!-- Max 10 files will be created everyday -->
<DefaultRolloverStrategy max="10">
<Delete basePath="${basePathr}" maxDepth="10">
<!-- Delete all files older than 30 days -->
<IfLastModified age="30d" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info" additivity="false">
<appender-ref ref="fileLogger" />
</Root>
</Loggers>
</Configuration>
4. Configuring Multiple Appenders
Use this simple log4j2.xml
for quick reference to log statements in multiple log files.
This configuration logs different levels of logs (debug
, info
etc.) to different files, using LevelRangeFilter
, so that our logs are clean and separated for easy debugging and reporting purposes.
Change the configuration as per your requirements.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30">
<!-- Logging Properties -->
<Properties>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} %p %m%n</Property>
<Property name="APP_LOG_ROOT">c:/temp/logs</Property>
</Properties>
<Appenders>
<!-- Console Appender -->
<Console name="Console" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
<!-- File Appenders on need basis -->
<RollingFile name="frameworkLog" fileName="${APP_LOG_ROOT}/app-framework.log"
filePattern="${APP_LOG_ROOT}/app-framework-%d{yyyy-MM-dd}-%i.log">
<LevelRangeFilter minLevel="ERROR" maxLevel="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="10MB" />
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
<RollingFile name="debugLog" fileName="${APP_LOG_ROOT}/app-debug.log"
filePattern="${APP_LOG_ROOT}/app-debug-%d{yyyy-MM-dd}-%i.log">
<LevelRangeFilter minLevel="DEBUG" maxLevel="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="10MB" />
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
<RollingFile name="infoLog" fileName="${APP_LOG_ROOT}/app-info.log"
filePattern="${APP_LOG_ROOT}/app-info-%d{yyyy-MM-dd}-%i.log" >
<LevelRangeFilter minLevel="INFO" maxLevel="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="10MB" />
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
<RollingFile name="errorLog" fileName="${APP_LOG_ROOT}/app-error.log"
filePattern="${APP_LOG_ROOT}/app-error-%d{yyyy-MM-dd}-%i.log" >
<LevelRangeFilter minLevel="ERROR" maxLevel="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="10MB" />
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
<RollingFile name="perfLog" fileName="${APP_LOG_ROOT}/app-perf.log"
filePattern="${APP_LOG_ROOT}/app-perf-%d{yyyy-MM-dd}-%i.log" >
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="10MB" />
</Policies>
<DefaultRolloverStrategy max="1"/>
</RollingFile>
<RollingFile name="traceLog" fileName="${APP_LOG_ROOT}/app-trace.log"
filePattern="${APP_LOG_ROOT}/app-trace-%d{yyyy-MM-dd}-%i.log" >
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="10MB" />
</Policies>
<DefaultRolloverStrategy max="1"/>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="com.howtodoinjava.app.pref" additivity="false" level="trace">
<AppenderRef ref="traceLog" />
<AppenderRef ref="Console" />
</Logger>
<Logger name="com.howtodoinjava.app" additivity="false" level="debug">
<AppenderRef ref="debugLog" />
<AppenderRef ref="infoLog" />
<AppenderRef ref="errorLog" />
<AppenderRef ref="Console" />
</Logger>
<Logger name="org.framework.package" additivity="false" level="info">
<AppenderRef ref="perfLog" />
<AppenderRef ref="Console"/>
</Logger>
<Root level="warn">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
5. log4j2.xml
File Location
We should put log4j2.xml
anywhere in the application’s classpath. Log4j will scan all classpath locations to find out this file and then load it.
We can find this file mostly placed in the ‘src/main/resources‘ folder.

If we are using an external log4j2 configuration file, then we can provide the path of the configuration file using the application startup parameter or system property log4j.configurationFile
. Note that this property value is not restricted to a location on the local file system and may contain a URL.
-Dlog4j2.configurationFile=file:/home/lokesh/log4j2.xml
A commonly seen approach is to set the log4j.configurationFile
property in the method annotated with @BeforeAll in the junit test class. This will allow an arbitrarily named file to be used during the test.
6. Demo
Let’s write a java class and write a few log statements to verify that logs are appreaing in the console and log file as well. It logs different log levels to different logs
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(final String[] args)
{
Logger logger = LoggerFactory.getLogger(Main.class);
logger.debug("Debug Message Logged !!!");
logger.info("Info Message Logged !!!");
logger.error("Error Message Logged !!!", new NullPointerException("NullError"));
}
}
Now when you run the above program, you will get the below logs in the console and log file.
2021-12-14 14:26:32.737 DEBUG [main] [com.howtodoinjava.demo.slf4j.Main.main (Main.java:10)] - Debug Message Logged !!!
2021-12-14 14:26:32.739 INFO [main] [com.howtodoinjava.demo.slf4j.Main.main (Main.java:11)] - Info Message Logged !!!
2021-12-14 14:26:32.739 ERROR [main] [com.howtodoinjava.demo.slf4j.Main.main (Main.java:12)] - Error Message Logged !!!
java.lang.NullPointerException: NullError
at com.howtodoinjava.demo.slf4j.Main.main (Main.java:12) [classes/:?]
If you change the system date and run the application again, you will find two log files in the configured location where the second file is rolled over file.
Happy Learning !!
Hi,
I wanted to log the org.springframework logs , but even after giving this package in logger.name option , I still get the logs of my application package com.test.log4jtesting . I havn’t added logger for my application package.
Any suggestions ?
For bullet #2 above, is the root level set to “debug” by default? I want it to be “INFO”, how can I accomplish this?
Hi,
How to use different xml file name (mylog4j.xml instead of log4j2.xml) and that should be in different location.
Use framework specific overrides. For example, in spring boot, use property override in
application.properties.
i have to read the log4j2.xml which is present in the web-inf folder of my war.Can you please share the code ?Please make sure it uses the latest log4j2.11.1.jar
Is there some examples that explain how rotate stdout and stderr?
Thanks.
How to read the configuration file from a directory(C:\config)?
how to log into console with json format?
Hello Lokesh,
I copied exactly the xml file and the java code and run the project on Eclipse using Run-Debug.
I could see the log lines on the Eclipse console but the file was empty.
Thank you, Tal
<Logger name="com.howtodoinjava"
In the logger name, replace "com.howtodoinjava" by the package of your class.
After changing the package “com.howtodoinjava” to mine I am still getting the log messages to display only on the console and not on the file.
Yes same happened to me . I got console messages but didn’t get file either by .properties file or .xml file
Happen to me as well. Did you have any solution to why this occurs? Thanks!