详谈异步log4j2中的location信息打印问题
作者:KeepTing 发布时间:2023-12-22 05:53:31
异步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>
来源:https://blog.csdn.net/kavu1/article/details/83650763


猜你喜欢
- Spring AOP后置通知修改响应httpstatus1.定义Aspect/** * 响应体切面 * 后置通知修改httpstatus *
- 本文实例为大家分享了Android SurfaceView画板操作的具体代码,供大家参考,具体内容如下画板—&m
- 请求参数解析客户端请求在handlerMapping中找到对应handler后,将会继续执行DispatchServlet的doPatch(
- 本篇内容通过操作软键盘的函数着手详细分析了隐藏或者显示软键盘的实现方法,并且对其中重要的代码做了详细分析。一、开篇如果有需要用到输入的地方,
- 1. 介绍结合上面的ReentrantLock类图,ReentrantLock实现了Lock接口,它的内部类Sync继承自AQS,绝大部分使
- 本文为大家分享了如何使用eclipse创建java项目,供大家参考,具体内容如下首先,打开Eclipse,在工具栏依次点击【File】>
- 最近在开发中遇到了这样一个问题,在下拉刷新组件中包含了一个轮播图组件,当左右滑动的图片时很容易触发下拉刷新,如下图所示:如图中红色箭头所示方
- Thread生命周期生命周期概述Java的线程状态描述放在Thread类里面的枚举类State中.总共包含了6中状态(从出生到死亡)。pub
- 弃用内容先来纠正一个误区。主要之前在版本更新介绍的时候,存在一些表述上的问题。导致部分读者认为这次的更新是Datasource本身初始化的调
- 前面文章介绍了如何使用JAVA的反射机制来调用蓝牙的隐藏API,本文继续来练习JAVA的反射机制,探秘TelephonyManager在Fr
- 由Lombok的@AllArgsConstructor注解引发的错误需求:在Service实现中写了一个方法调用第三方接口同步数据。 功能代
- TCP异步Socket模型C#的TCP异步Socket模型是通过Begin-End模式实现的。例如提供BeginConnect、BeginA
- 本文实例讲述了Android获取当前已连接的wifi信号强度的方法,是Android程序开发中非常常见的重要技巧。分享给大家供大家参考之用。
- 如何下载并配置JDK 15进入官网下载JDK 15。官网地址:https://www.oracle.com/index.html脚本之家下载
- yaml语法注解配置文件两种形式application.properties和.yaml第一种语法 key=value第二种key:空格va
- 如何实现?1.)首先实现全屏第一种:继承主题特定主题在Android API 19以上可以使用****.TranslucentDecor**
- 1.上原图 前几天在 Hencoder 征稿看到的Filpboard 里的的动画效果:Filipboard.gif先bb一句:在看本文的同时
- 本文实例讲述了C#事件用法。分享给大家供大家参考。具体分析如下:EventHandler<TEventArgs>的定义如下pub
- 数据表及数据准备:create table Member(MemberId int primary key identity(1,1),Me
- 目录类划分时关于内聚性的问题静态类的设计高内聚类的设计附:面向过程编程中模块的内聚性偶然内聚或巧合内聚(Coincidental)逻辑内聚(