一. log4j2简介
log4j2是log4j 1.x 的升级版,参考了logback的一些优秀的设计,并且修复了一些问题,因此带来了一些重大的提升。
- 性能提升, log4j2相较于log4j 1和logback都具有很明显的性能提升,支持异步日志处理。
- 自动重载配置,参考了logback的设计,当然会提供自动刷新参数配置,在生产上可以动态的修改日志的级别而不需要重启应用。
- log4j2不再支持properties文件了,只支持xml,json或是yaml。
二. SpringBoot2.x集成Log4j2
spring boot 默认采用lobback作为日志实现框架,需要排除logback的依赖。
1.pom文件添加
<!-- 集成Log4j2日志 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
2.application.properties文件添加
logging.config=classpath:log4j2.xml
3.resources文件夹下编辑log4j2.xml文件
?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<!-- <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> -->
<PatternLayout pattern=".%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%file:%line]
%-5level %logger{36} - %msg %n"/>
</Console>
<RollingFile name="RollingFile" fileName="logs/app.log"
filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log">
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%file:%line] %-5level %logger{35} - %msg %n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="102400KB"/>
</Policies>
<DefaultRolloverStrategy fileIndex="max" max="2"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="STDOUT"/>
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
三.异步日志
log4j2最大的特点就是异步日志,增加消息队列作为缓存,Log4j2提供了两种实现日志的方式,一个是通过AsyncAppender,一个是通过AsyncLogger,分别对应前面我们说的Appender组件和Logger组件。
AsyncAppender方式
默认使用 java.util.concurrent.ArrayBlockingQueue实现。 在多线程的环境下阻塞队列容易受到锁争用的影响,这可能会对性能产生影响。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
<Appenders>
<File name="MyFile" fileName="logs/app.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
<Async name="Async">
<AppenderRef ref="MyFile"/>
</Async>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Async"/>
</Root>
</Loggers>
</Configuration>
AsyncLogger方式
官方推荐的异步方式,速度更快,分为全局异步和混合异步,采用disruptor非阻塞消息队列。
- 全局异步
所有的日志都异步的记录,在系统初始化的时候,增加全局参数配置:
System.setProperty("log4j2.contextSelector, "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
也可以加载JVM启动参数里设置:
java -Dog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
- 混合异步
在应用中同时使用同步日志和异步日志,这使得日志的配置方式更加灵活。
<?xml version="1.0" encoding="UTF-8"?>
<!-- No need to set system property "log4j2.contextSelector" to any value
when using <asyncLogger> or <asyncRoot>. -->
<Configuration status="WARN">
<Appenders>
<!-- Async Loggers will auto-flush in batches, so switch off immediateFlush. -->
<RandomAccessFile name="RandomAccessFile" fileName="asyncWithLocation.log"
immediateFlush="false" append="false">
<PatternLayout>
<Pattern>%d %p %class{1.} [%t] %location %m %ex%n</Pattern>
</PatternLayout>
</RandomAccessFile>
</Appenders>
<Loggers>
<!-- pattern layout actually uses location, so we need to include it -->
<AsyncLogger name="com.foo.Bar" level="trace" includeLocation="true">
<AppenderRef ref="RandomAccessFile"/>
</AsyncLogger>
<Root level="info" includeLocation="true">
<AppenderRef ref="RandomAccessFile"/>
</Root>
</Loggers>
</Configuration>
异步日志注意事项
- 不要同时使用AsyncAppender和AsyncLogger。
- 不要在开启了全局同步的情况下,仍然使用AsyncAppender和AsyncLogger。
- 如果不是确实需要,不要打印location信息,比如pattern模式里的%C or $class, %F or %file, %l or %location, %L or %line, %M or %method, 等,对于性能来说是个极大的损耗。
- 不管是同步异步,都设置immediateFlush为false,这会对性能提升有很大帮助。
四.注解@Slf4j的使用
如果不想每次都写private final Logger logger = LoggerFactory.getLogger(当前类名.class); 可以用注解@Slf4j。
1.eclipse安装lombok插件
2.在pom文件加入lombok的依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
</dependency>
3.类上面添加@Sl4j注解,然后使用log打印日志。
@Slf4j
class LogTest {
@Test
void testLog() {
String testInfo = "Free flying flowers are like dreams";
log.info("The test info is :{}", testInfo);
}
}