详谈异步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>
以上为个人经验,希望能给大家一个参考,也希望大家多多支持猪先飞。
原文出处:https://blog.csdn.net/kavu1/article/details/83650763
相关文章
- 这篇文章主要介绍了C#中异步和多线程的相关资料,帮助大家更好的理解和学习c#,感兴趣的朋友可以了解下...2021-01-16
- 多线程和异步操作两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性。甚至有些时候我们就认为多线程和异步操作是等同的概念。但是,多线程和异步操作还是有一些区别的。而这些区别造成了使用多线程和异步操作的时机的区别...2020-06-25
- 本篇文章主要介绍了C# Socket异步通信,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
- 这篇文章主要给大家介绍了关于JS异步的执行原理和回调的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-08
- 这篇文章主要给大家介绍了关于c# winform异步不卡界面的实现方法,文中通过示例代码介绍的非常详细,对大家学习或者使用c#具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-06-25
- 这篇文章主要介绍了JQuery基于FormData异步提交数据文件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-09-02
如何使用PHP+jQuery+MySQL实现异步加载ECharts地图数据(附源码下载)
ECharts地图主要用于地理区域数据的可视化,展示不同区域的数据分布信息,通过本文给大家介绍如何使用PHP+jQuery+MySQL实现异步加载ECharts地图数据,需要的朋友参考下吧...2016-02-26- 这篇文章主要介绍了JQuery异步提交表单与文件上传功能,结合实例形式分析了jQuery表单提交及文件传输操作的相关实现技巧,需要的朋友可以参考下...2017-01-16
- 这篇文章主要介绍了C#异步的世界(下),对异步感兴趣的同学,可以参考下...2021-04-26
c#异步操作后台运行(backgroundworker类)示例
这篇文章主要介绍了c#异步操作后台运行(backgroundworker类)示例,需要的朋友可以参考下...2020-06-25- 这篇文章主要介绍了ASP.Net中的async+await异步编程的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
- 这篇文章主要介绍了Spring @Async无法实现异步的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-02
- 这篇文章主要介绍了又拍云异步上传实例教程详解的相关资料,需要的朋友可以参考下...2016-04-23
- 这篇文章主要介绍了NodeJs并发异步的回调处理的相关资料,需要的朋友可以参考下...2015-12-24
- 这篇文章主要给大家介绍了关于C#异步方法返回void与Task的区别的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-04
- 本篇文章主要介绍了Yii2.0中使用js异步删除示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 ...2017-03-12
- 这篇文章主要介绍了C#实现异步发送邮件的方法,涉及C#异步操作与邮件发送的技巧,非常具有实用价值,需要的朋友可以参考下...2020-06-25
- 下面小编就为大家分享一篇asp.net使用H5新特性实现异步上传的示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-09-22
- 这篇文章主要介绍了php实现异步将远程链接上内容(图片或内容)写到本地的方法,涉及php基于curl进行远程文件传输的相关操作技巧,需要的朋友可以参考下...2016-12-02
- 这篇文章主要介绍了JAVA同步、异步、阻塞和非阻塞之间的区别,文中讲解非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-08-01