详谈异步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
猜你喜欢
- 前言xxljob 是采用 java 开发的开源的任务调度系统,架构上分为调度管理器、执行器,目前除了官方提供的 java 执行器外,也有 g
- 最近一段时间,大家在用 Spring Security OAuth2 时可能发现有很多类过期了。大家在选择 OAuth2 依赖的时候,可能也
- 介绍责任链模式是一种行为型设计模式,其目的是将请求从一个对象传递到另一个对象,直到找到能够处理该请求的对象为止.再责任链模式中,每个对象都持
- 实时代码模板(Live Templates)我们先来看一个gif图:大兄弟,你看清我的操作了么?这个就是实时代码模板的功能。我们来看一下怎么
- 下面给大家介绍下mybatis结果生成键值对的实例代码,具体内容如下所示:在实际应用中我们经常会遇到这样的情况,需要给下拉框赋值,这个时候就
- Maven修改打包文件名称对Maven打出的jar包名称不满意:想通过修改配置给jar包改名,查询找到了方法:pom.xml的<bui
- 一个比较常见的改进用户体验的方案是用Redo/Undo来取代确认对话框,由于这个功能比较常用,本文简单的给了一个在C#中通过Command模
- 使用通配符增强泛型1.题目泛型是JAVA重要的特性,使用泛型编程,可以使代码复用率提高。实现:在泛型方法中使用通配符2.解题思路创建一个类:
- 一、网络爬虫的基本知识网络爬虫通过遍历互联网络,把网络中的相关网页全部抓取过来,这体现了爬的概念。爬虫如何遍历网络呢,互联网可以看做是一张大
- 今天有朋友问我Struts2中Action必须实现execute方法吗?顺利的回答出来了。其实分两种情况:1)如果你的Action类是继承自
- 匿名类类型类可以是匿名的 - 也就是说,可以在没有 identifier 的情况下声明类。在将类名称替换为 typedef 名称时,这会很有
- 最近在做项目的时候,一直用一个叫做API的东西,controller注解我会写,这个东西我也会用,但是我确实不知道这个东西是个什么,有点神奇
- 文件流输出文件名中文不显示response返回文件流 用response.setHeader(“Content-disp
- 本文实例为大家分享了Java实现分页功能的具体代码,供大家参考,具体内容如下不用根据改变SQL的形式去查询; 直接查询所有的数据,根据页码自
- 引言一个复杂的分布式系统,用户发起一个请求,这个请求可能调用几十到几百个服务,经过很多业务层,而每个业务又是多个机器集群,一个请求具体被随机
- 对这种懒加载问题,最后的做法是利用Spring提供的一个针对Hibernate的一个支持类,其主要意思是在发起一个页面请求时打开Hibern
- 问题引出:最近开了新项目,项目中用到了数据字典,列表查询数据返回的时候需要手动将code转换为name,到前台展示。项目经理表示可以封装一个
- SpringBoot starter用了springboot 那么久了居然都还没自定义过starter,想想都觉得羞愧,所以今天来玩一下。S
- Lucene从今天开始,我们要开始介绍Lucene中索引构建的流程。因为索引构建的逻辑涉及到的东西非常多,如果从构建入口IndexWrite
- 前言这里主要简单介绍如何使用Camera+SurfaceView自定义相机拍照,如果是Camera2或者是TextureView的可以前往主