log4j2的使用

一. 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);
    }
}
上一篇:java – Log4j2找不到Sprint Boot的日志记录实现


下一篇:log4j2