详谈异步log4j2中的location信息打印问题

 更新时间:2021年12月22日 17:00:16   作者:KeepTing  
这篇文章主要介绍了详谈异步log4j2中的location信息打印问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

异步log4j2的location信息打印问题

背景:项目改造过程中将log4j2改成异步,发现行号没有打印,于是扒了下官方文档,大概陈述下:

先说一下这个问题是怎么解决的,然后稍微扩展一下其他配置,有兴趣的可以往下看或者溜一遍官方文档

说下解决

在<AsyncLogger>标签中配置includeLocation="true",

扩展:

1、additivity:这个属性的意思是需不需要打印此logger继承的父logger,如果是false则只打印当前logger;如果是true则继续打印上一层的logger,直到root。

2、实现error日志打印双份:info.log中打印一份(即info中包括info和error日志),error.log中打印一份(只包括error日志),这样的好处是能根据error日志出现的上下文快速定位到程序bug出现的位置,这个功能需要使用过滤器实现,比如:

 <RollingFile name="error" fileName="${log_home}/error.log" immediateFlush="false" append="true"
                     filePattern="/history/error-%d{yyyy-MM-dd}.log.gz">
      <Filters>
         <!--只允许级别为error的日志通过-->
          <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
       </Filters>
       <PatternLayout charset="UTF-8">
          <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} #| %p #| %t #| %c{-1}:%L #| %m%n</Pattern>
       </PatternLayout>
       <Policies>
          <!--默认打印周期为一天-->
          <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
       </Policies>
       <!--保存日志个数为15个-->
       <DefaultRolloverStrategy max="15"/>
</RollingFile>

log4j2的异步形式大概分为两种:全异步和同步异步混合。

1、全异步

实现方式:将系统属性log4j2.contextSelector设置 为org.apache.logging.log4j.core.async.AsyncLoggerContextSelector,即

System.setProperty("log4j2.contextSelector, "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");

或者在启动时设置:

-Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

官方给出了一个不需要location信息的配置文件示例:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <!-- Async Loggers will auto-flush in batches, so switch off immediateFlush. -->
    <RandomAccessFile name="RandomAccessFile" fileName="async.log" immediateFlush="false" append="false">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m %ex%n</Pattern>
      </PatternLayout>
    </RandomAccessFile>
  </Appenders>
  <Loggers>
   <!--不需要打印location信息-->
    <Root level="info" includeLocation="false">
      <AppenderRef ref="RandomAccessFile"/>
    </Root>
  </Loggers>
</Configuration>

注意:

如果用AsyncLoggerContextSelector实现全异步,那么配置中就要使用<root>和<logger> 。如果配置了这个属性,并且使用了<asyncRoot>和<asyncLogger>,那么程序将会产生两个线程:日志数据首先传递给线程A,然后线程A再传递给线程B,最后再输出到磁盘,这样是可行的,但是中间多了一步线程交互的过程,这是不必要的。

同步异步混合

相比起全异步,混合异步可能会花费更多的性能,

官方给出了一个混合异步的配置例子:

<?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>

对于location信息:

默认情况下,异步日志记录器不会将location信息传递给I/O线程,如果你的layouts或custom过滤器需要location信息,你需要在所有相关日志记录器(包括根日志记录器)的配置中设置“includeLocation=true”

如果其中一个layouts配置了关于位置的信息,比如HTML locationInfo,或者表达式%C或%class、%F或%file、%l或%location、%L或%line、%M或%method,log4j2将会获取堆栈的快照(snapshot),并遍历堆栈跟踪以查找位置信息,因此会消耗较多的时间。

比同步logger慢1.3到5倍,同步日志记录器在获取堆栈快照之前会等待尽可能长的时间,如果不需要位置,那么快照将永远不会被捕获。

了解更多请访问官方文档:Apache Log4j2 Async 官方文档

log4j2支持异步打印提高打印输出速度

pom依赖添加

<!--log4j2异步支持-->
<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
</dependency>

全局模式2两种

第一种:resources 下创建属性文件 log4j2.component.properties

# log4j2异步支持
Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

第二种:springboot启动main方法添加代码

System.setProperty("Log4jContextSelector","org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");

或者采用启动参数

-DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

局部模式 AsyncLogger

<Loggers>
        <AsyncLogger name="com.meituan.Main" level="trace" additivity="false">
            <appender-ref ref="RollingFile"/>
        </AsyncLogger>
        <AsyncLogger name="RollingFile2" level="trace" additivity="false">
            <appender-ref ref="RollingFile2"/>
        </AsyncLogger>
        <Root level="debug">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="RollingFile"/>
        </Root>
</Loggers>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SSH框架网上商城项目第24战之Struts2中处理多个Model请求的方法

    SSH框架网上商城项目第24战之Struts2中处理多个Model请求的方法

    这篇文章主要为大家详细介绍了SSH框架网上商城项目第24战之Struts2中处理多个Model请求的方法,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • 基于Java中两种jersey文件上传方式

    基于Java中两种jersey文件上传方式

    这篇文章主要介绍了基于Java中两种jersey文件上传方式的相关资料,需要的朋友可以参考下
    2016-01-01
  • Java两整数相除向上取整的方式详解(Math.ceil())

    Java两整数相除向上取整的方式详解(Math.ceil())

    在调外部接口获取列表数据时,需要判断是否已经取完了所有的值,因此需要用到向上取整,下面这篇文章主要给大家介绍了关于Java两整数相除向上取整的相关资料,需要的朋友可以参考下
    2022-06-06
  • SpringBoot中整合Ehcache实现热点数据缓存的详细过程

    SpringBoot中整合Ehcache实现热点数据缓存的详细过程

    这篇文章主要介绍了SpringBoot中整合Ehcache实现热点数据缓存,SpringBoot 中使用 Ehcache 比较简单,只需要简单配置,说白了还是 Spring Cache 的用法,合理使用缓存机制,可以很好地提高项目的响应速度,需要的朋友可以参考下
    2023-04-04
  • Java并发工具类Phaser详解

    Java并发工具类Phaser详解

    这篇文章主要介绍了Java并发工具类Phaser详解,Phaser(阶段协同器)是一个Java实现的并发工具类,用于协调多个线程的执行,它提供了一些方便的方法来管理多个阶段的执行,可以让程序员灵活地控制线程的执行顺序和阶段性的执行,需要的朋友可以参考下
    2023-11-11
  • redis分布式锁的实现原理详解

    redis分布式锁的实现原理详解

    这篇文章主要为大家详细介绍了redis分布式锁,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • Jenkins任务批量修改的技巧分享

    Jenkins任务批量修改的技巧分享

    这篇文章主要给大家介绍了关于Jenkins任务批量修改的一些技巧,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-03-03
  • Java去除字符串空格的几种方法简单举例

    Java去除字符串空格的几种方法简单举例

    在Java中要去掉字符串中的空格,可以使用多种方法,这篇文章主要给大家介绍了关于Java去除字符串空格的几种方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • SpringCloud创建多模块项目的实现示例

    SpringCloud创建多模块项目的实现示例

    ,Spring Cloud作为一个强大的微服务框架,提供了丰富的功能和组件,本文主要介绍了SpringCloud创建多模块项目的实现示例,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • Java Collection接口中的常用方法总结

    Java Collection接口中的常用方法总结

    这篇文章将大概用代码案例简单总结一下 Collection 接口中的一些方法,我们会以他的实现类 Arraylist 为例创建对象。快一起来看看吧
    2022-12-12

最新评论