一个简单的log4j 2 hello world示例。
经过测试
- Log4j 2.11.2
- Maven 3
- Java 8
注意
最快的Java日志记录框架 Apache Log4j 2,对其前身Log4j 1.x进行了重大改进。
1.项目目录
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在项目类路径中创建一个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.mkyong" level="debug" additivity="false">
<AppenderRef ref="LogToConsole"/>
</Logger>
<Root level="error">
<AppenderRef ref="LogToConsole"/>
</Root>
</Loggers>
</Configuration>
对于其他格式
4. Hello Log4j 2
4.1阅读此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;
}
}
输出量
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配置
5.1我们可以将状态更改为“跟踪”,“调试”,“信息”,“警告”,“错误”和“致命”以启用内部Log4j事件,它将显示Log4j组件的许多有用日志。 阅读此内容以了解Log4j配置
<Configuration status="DEBUG">
</Configuration>
6. Log4j 2追加者
一些常见的Log4j附加程序。
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
–每天或在文件大小> 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>
默认情况下,它将在同一天最多创建7个档案。
我们可以使用DefaultRolloverStrategy
覆盖默认的7个归档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
–与RollingFileAppender
类似,但速度更快。
<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
–使追加器异步。 提高性能。
<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
–需要javax.mail
发送电子邮件。
<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>
模拟错误
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!");
}
}
电子邮件样本
注意
始终参考此官方Log4j附录
7.异步记录器
7.1要使所有记录器异步,我们需要做两件事:
-
disruptor 3
位于项目类路径中。 - 设置系统属性
log4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
7.2如果我们尝试配置log4j2.contextSelector
,但在类路径中不存在disruptor
器,它将提示以下错误消息:
$ 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要修复此问题,请添加disruptor
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.4.2</version>
</dependency>
7.4再次运行它,并且Log4j 2配置处于debug
状态。
异步记录器
$ 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
同步记录器
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.混合同步和异步记录器
<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>
下载源代码
$ git clone https://github.com/mkyong/java-logging.git
$ cd log4j2
$ mvn清洁包
$ java -Dlog4j2.contextSelector = org.apache.logging.log4j.core.async.AsyncLoggerContextSelector -jar target \ log4j2-1.0.jar