A simple log4j 2 hello world example.
Tested with
- Log4j 2.11.2
- Maven 3
- Java 8
Note
Apache Log4j 2, the fastest Java logging framework, provides significant improvements over its predecessor, Log4j 1.x.
1. Project Directory

2. Maven
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.11.2</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.11.2</version> </dependency>
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.favtuts</groupId> <artifactId>log4j2</artifactId> <version>1.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> <log4j.version>2.11.2</log4j.version> <disruptor.version>3.4.2</disruptor.version> </properties> <dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j.version}</version> </dependency> <!-- https://logging.apache.org/log4j/2.x/manual/async.html --> <dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>${disruptor.version}</version> </dependency> <!-- slf4j bridge to log4j <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j.version}</version> </dependency> --> <!-- SMTPAppender need this --> <dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.6.2</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.0</version> <executions> <!-- Attach the shade into the package phase --> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.favtuts.HelloWorld</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
3. log4j2.xml
3.1 Create a log4j2.xml
in the project classpath.
src/resources/log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="LogToConsole" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Logger name="com.favtuts" level="debug" additivity="false"> <AppenderRef ref="LogToConsole"/> </Logger> <Root level="error"> <AppenderRef ref="LogToConsole"/> </Root> </Loggers> </Configuration>
For other format
4. Hello Log4j 2
4.1 Read this Log4j 2 API
HelloWorld.java
package com.favtuts; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class HelloWorld { private static final Logger logger = LogManager.getLogger(HelloWorld.class); public static void main(String[] args) { logger.debug("Hello from Log4j 2"); // in old days, we need to check the log level to increase performance /*if (logger.isDebugEnabled()) { logger.debug("{}", getNumber()); }*/ // with Java 8, we can do this, no need to check the log level logger.debug("{}", () -> getNumber()); } static int getNumber() { return 5; } }
Output
23:11:44.976 [main] DEBUG com.favtuts.HelloWorld - Hello from Log4j 2
23:11:44.981 [main] DEBUG com.favtuts.HelloWorld - 5
5. Log4j 2 Configuration
5.1 We can change the status to “trace”, “debug”, “info”, “warn”, “error” and “fatal” to enable the internal Log4j events, it will display many useful logs for the Log4j components. Read this for Log4j configuration
src/resources/log4j2.xml
<Configuration status="DEBUG"> </Configuration>
6. Log4j 2 Appenders
Some of the common Log4j appenders.
6.1 ConsoleAppender
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="DEBUG"> <Appenders> <Console name="LogToConsole" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <!-- avoid duplicated logs with additivity=false --> <Logger name="com.favtuts" level="debug" additivity="false"> <AppenderRef ref="LogToConsole"/> </Logger> <Root level="error"> <AppenderRef ref="LogToConsole"/> </Root> </Loggers> </Configuration>
6.2 FileAppender
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="DEBUG"> <Appenders> <Console name="LogToConsole" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> <File name="LogToFile" fileName="logs/app.log"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> </File> </Appenders> <Loggers> <Logger name="com.favtuts" level="debug" additivity="false"> <AppenderRef ref="LogToFile"/> <AppenderRef ref="LogToConsole"/> </Logger> <Logger name="org.springframework.boot" level="error" additivity="false"> <AppenderRef ref="LogToConsole"/> </Logger> <Root level="error"> <AppenderRef ref="LogToFile"/> <AppenderRef ref="LogToConsole"/> </Root> </Loggers> </Configuration>
6.3 RollingFileAppender
– Rotate log files daily or when the file size > 10MB.
log4j2.xml
<Configuration status="DEBUG"> <Appenders> <Console name="LogToConsole" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> <RollingFile name="LogToRollingFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="10 MB"/> </Policies> </RollingFile> </Appenders> <Loggers> <!-- avoid duplicated logs with additivity=false --> <Logger name="com.favtuts" level="debug" additivity="false"> <AppenderRef ref="LogToRollingFile"/> </Logger> <Root level="error"> <AppenderRef ref="LogToConsole"/> </Root> </Loggers> </Configuration>
By default, it will create up to 7 archives on the same day.


We can override the default 7 archives with this DefaultRolloverStrategy
<RollingFile name="LogToRollingFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="10 MB"/> </Policies> <DefaultRolloverStrategy max="10"/> </RollingFile>
6.4 RollingRandomAccessFileAppender
– Similar to the RollingFileAppender
, but faster.
log4j2.xml
<RollingRandomAccessFile name="LogToRollingRandomAccessFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="1 MB"/> </Policies> <DefaultRolloverStrategy max="10"/> </RollingRandomAccessFile>
6.5 AsyncAppender
– Make appender asynchronous. Increase performance.
log4j2.xml
<Configuration status="DEBUG"> <Appenders> <Console name="LogToConsole" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> <RollingRandomAccessFile name="LogToRollingRandomAccessFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="1 MB"/> </Policies> <DefaultRolloverStrategy max="10"/> </RollingRandomAccessFile> <Async name="Async"> <!-- reference to other appenders --> <AppenderRef ref="LogToRollingRandomAccessFile"/> </Async> </Appenders> <Loggers> <!-- avoid duplicated logs with additivity=false --> <Logger name="com.favtuts" level="debug" additivity="false"> <AppenderRef ref="Async"/> </Logger> <Root level="error"> <AppenderRef ref="LogToConsole"/> </Root> </Loggers> </Configuration>
6.6 SMTPAppender
– Need javax.mail
to send email.
pom.xml
<dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.6.2</version> </dependency>
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <RollingRandomAccessFile name="LogToRollingRandomAccessFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="1 MB"/> </Policies> <DefaultRolloverStrategy max="10"/> </RollingRandomAccessFile> <SMTP name="LogToMail" subject="Error Log From Log4j" from="from@DOMAIN" to="to@DOMAIN" smtpHost="smtp.mailgun.org" smtpPort="25" smtpUsername="abc" smtpPassword="123" bufferSize="100"> </SMTP> </Appenders> <Loggers> <Logger name="com.favtuts" level="debug" additivity="false"> <AppenderRef ref="LogToRollingRandomAccessFile"/> <AppenderRef ref="LogToConsole"/> </Logger> <Root level="error"> <AppenderRef ref="LogToMail"/> </Root> </Loggers> </Configuration>
Simulate an error
package com.favtuts; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class HelloWorldError { private static final Logger logger = LogManager.getLogger(HelloWorldError.class); public static void main(String[] args) { try { System.out.println(getData()); } catch (IllegalArgumentException e) { logger.error("{}", e); } } static int getData() throws IllegalArgumentException { throw new IllegalArgumentException("Sorry IllegalArgumentException!"); } }
Sample email

Note
Always refer to this official Log4j appenders
7. Asynchronous Loggers
7.1 To enable all loggers to asynchronous, we need 2 things :
- The
disruptor 3
is present in project class path. - Set system property
log4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
7.2 If we try to configure log4j2.contextSelector
and the disruptor
is not present in the classpath, it will prompt the following error message :
$ mvn clean package
$ mvn -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector -jar target\log4j2-1.0.jar
java.lang.NoClassDefFoundError: com/lmax/disruptor/EventTranslatorVararg
at java.lang.ClassLoader.defineClass1 (Native Method)
at java.lang.ClassLoader.defineClass (ClassLoader.java:1009)
at java.security.SecureClassLoader.defineClass (SecureClassLoader.java:174)
at java.net.URLClassLoader.defineClass (URLClassLoader.java:545)
at java.net.URLClassLoader.access$100 (URLClassLoader.java:83)
at java.net.URLClassLoader$1.run (URLClassLoader.java:453)
7.3 To fix it, add disruptor
pom.xml
<dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.4.2</version> </dependency>
7.4 Run it again, with Log4j 2 configuration in debug
status.
Asynchronous Loggers
$ java -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector -jar target\log4j2-1.0.jar
2019-03-25 21:11:23,919 main DEBUG Registering MBean org.apache.logging.log4j2:type=AsyncContext@464bee09
2019-03-25 21:11:23,921 main DEBUG Registering MBean org.apache.logging.log4j2:type=AsyncContext@464bee09,component=AsyncLoggerRingBuffer
2019-03-25 21:11:23,921 main DEBUG Registering MBean org.apache.logging.log4j2:type=AsyncContext@464bee09,component=StatusLogger
2019-03-25 21:11:23,922 main DEBUG Registering MBean org.apache.logging.log4j2:type=AsyncContext@464bee09,component=ContextSelector
2019-03-25 21:11:23,923 main DEBUG Registering MBean org.apache.logging.log4j2:type=AsyncContext@464bee09,component=Loggers,name=
2019-03-25 21:11:23,923 main DEBUG Registering MBean org.apache.logging.log4j2:type=AsyncContext@464bee09,component=Loggers,name=com.favtuts
2019-03-25 21:11:23,924 main DEBUG Registering MBean org.apache.logging.log4j2:type=AsyncContext@464bee09,component=Appenders,name=LogToConsole
2019-03-25 21:11:23,924 main DEBUG Registering MBean org.apache.logging.log4j2:type=AsyncContext@464bee09,component=Appenders,name=LogToRollingFile
//...
2019-03-25 21:11:24,020 pool-1-thread-1 DEBUG Stopped LoggerContext[name=AsyncContext@464bee09, org.apache.logging.log4j.core.async.AsyncLoggerContext@45fd9a4d] with
Synchronous Loggers
2019-03-25 21:12:49,432 main DEBUG Registering MBean org.apache.logging.log4j2:type=57baeedf,component=StatusLogger
2019-03-25 21:12:49,433 main DEBUG Registering MBean org.apache.logging.log4j2:type=57baeedf,component=ContextSelector
2019-03-25 21:12:49,433 main DEBUG Registering MBean org.apache.logging.log4j2:type=57baeedf,component=Loggers,name=
2019-03-25 21:12:49,434 main DEBUG Registering MBean org.apache.logging.log4j2:type=57baeedf,component=Loggers,name=com.favtuts
2019-03-25 21:12:49,435 main DEBUG Registering MBean org.apache.logging.log4j2:type=57baeedf,component=Appenders,name=LogToConsole
2019-03-25 21:12:49,435 main DEBUG Registering MBean org.apache.logging.log4j2:type=57baeedf,component=Appenders,name=LogToRollingFile
//...
2019-03-25 21:12:49,449 pool-1-thread-1 DEBUG Stopped LoggerContext[name=57baeedf, org.apache.logging.log4j.core.LoggerContext@4ed5eb72] with status true
8. Mixing Synchronous and Asynchronous Loggers
<Configuration status="WARN"> <Appenders> <Console name="LogToConsole" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> <RollingRandomAccessFile name="LogToRollingRandomAccessFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="1 MB"/> </Policies> <DefaultRolloverStrategy max="10"/> </RollingRandomAccessFile> </Appenders> <Loggers> <!-- asynchronous loggers --> <AsyncLogger name="com.favtuts" level="debug" additivity="false"> <AppenderRef ref="LogToRollingRandomAccessFile"/> <AppenderRef ref="LogToConsole"/> </AsyncLogger> <!-- synchronous loggers --> <Root level="error"> <AppenderRef ref="LogToConsole"/> </Root> </Loggers> </Configuration>
Read this Asynchronous Loggers for Low-Latency Logging
Download Source Code
$ git clone https://github.com/favtuts/java-core-tutorials-examples.git
$ cd log4j2
$ mvn clean package
$ java -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector -jar target\log4j2-1.0.jar