Apache Log4j 2 Tutorials
A simple log4j 2 hello world example.
Tested with
- Log4j 2.11.2
- Maven 3
- Java 8
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>
<?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.mkyong</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.mkyong.HelloWorld</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
3. log4j2.xml
3.1 Create a log4j2.xml in the project classpath.
<?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.mkyong" 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
package com.mkyong; 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
19:12:25.337 [main] DEBUG com.mkyong.HelloWorld - Hello from Log4j 2 19:12:25.340 [main] DEBUG com.mkyong.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
<Configuration status="DEBUG"> </Configuration>
6. Log4j 2 Appenders
Some of the common Log4j appenders.
6.1 ConsoleAppender
<?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.mkyong" level="debug" additivity="false"> <AppenderRef ref="LogToConsole"/> </Logger> <Root level="error"> <AppenderRef ref="LogToConsole"/> </Root> </Loggers> </Configuration>
6.2 FileAppender
<?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.mkyong" 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.
<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.mkyong" 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.
<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.
<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.mkyong" 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.
<dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.6.2</version> </dependency>
<?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.mkyong" 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.mkyong; 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
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
<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.mkyong 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.mkyong 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.mkyong" 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
From:一号门
Previous:JavaScript How to redirect a page
COMMENTS