詳談異步log4j2中的location信息打印問題
異步log4j2的location信息打印問題
背景:項(xiàng)目改造過程中將log4j2改成異步,發(fā)現(xiàn)行號(hào)沒有打印,于是扒了下官方文檔,大概陳述下:
先說一下這個(gè)問題是怎么解決的,然后稍微擴(kuò)展一下其他配置,有興趣的可以往下看或者溜一遍官方文檔
說下解決
在<AsyncLogger>標(biāo)簽中配置includeLocation="true",
擴(kuò)展:
1、additivity:這個(gè)屬性的意思是需不需要打印此logger繼承的父logger,如果是false則只打印當(dāng)前l(fā)ogger;如果是true則繼續(xù)打印上一層的logger,直到root。
2、實(shí)現(xiàn)error日志打印雙份:info.log中打印一份(即info中包括info和error日志),error.log中打印一份(只包括error日志),這樣的好處是能根據(jù)error日志出現(xiàn)的上下文快速定位到程序bug出現(xiàn)的位置,這個(gè)功能需要使用過濾器實(shí)現(xiàn),比如:
<RollingFile name="error" fileName="${log_home}/error.log" immediateFlush="false" append="true"
filePattern="/history/error-%d{yyyy-MM-dd}.log.gz">
<Filters>
<!--只允許級(jí)別為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>
<!--默認(rèn)打印周期為一天-->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<!--保存日志個(gè)數(shù)為15個(gè)-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
log4j2的異步形式大概分為兩種:全異步和同步異步混合。
1、全異步
實(shí)現(xiàn)方式:將系統(tǒng)屬性log4j2.contextSelector設(shè)置 為org.apache.logging.log4j.core.async.AsyncLoggerContextSelector,即
System.setProperty("log4j2.contextSelector, "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
或者在啟動(dòng)時(shí)設(shè)置:
-Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
官方給出了一個(gè)不需要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實(shí)現(xiàn)全異步,那么配置中就要使用<root>和<logger> 。如果配置了這個(gè)屬性,并且使用了<asyncRoot>和<asyncLogger>,那么程序?qū)?huì)產(chǎn)生兩個(gè)線程:日志數(shù)據(jù)首先傳遞給線程A,然后線程A再傳遞給線程B,最后再輸出到磁盤,這樣是可行的,但是中間多了一步線程交互的過程,這是不必要的。
同步異步混合
相比起全異步,混合異步可能會(huì)花費(fèi)更多的性能,
官方給出了一個(gè)混合異步的配置例子:
<?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>
對(duì)于location信息:
默認(rèn)情況下,異步日志記錄器不會(huì)將location信息傳遞給I/O線程,如果你的layouts或custom過濾器需要location信息,你需要在所有相關(guān)日志記錄器(包括根日志記錄器)的配置中設(shè)置“includeLocation=true”
如果其中一個(gè)layouts配置了關(guān)于位置的信息,比如HTML locationInfo,或者表達(dá)式%C或%class、%F或%file、%l或%location、%L或%line、%M或%method,log4j2將會(huì)獲取堆棧的快照(snapshot),并遍歷堆棧跟蹤以查找位置信息,因此會(huì)消耗較多的時(shí)間。
比同步logger慢1.3到5倍,同步日志記錄器在獲取堆??煺罩皶?huì)等待盡可能長(zhǎng)的時(shí)間,如果不需要位置,那么快照將永遠(yuǎn)不會(huì)被捕獲。
了解更多請(qǐng)?jiān)L問官方文檔:Apache Log4j2 Async 官方文檔
log4j2支持異步打印提高打印輸出速度
pom依賴添加
<!--log4j2異步支持-->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
</dependency>
全局模式2兩種
第一種:resources 下創(chuàng)建屬性文件 log4j2.component.properties
# log4j2異步支持 Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
第二種:springboot啟動(dòng)main方法添加代碼
System.setProperty("Log4jContextSelector","org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
或者采用啟動(dòng)參數(shù)
-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>
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SSH框架網(wǎng)上商城項(xiàng)目第24戰(zhàn)之Struts2中處理多個(gè)Model請(qǐng)求的方法
這篇文章主要為大家詳細(xì)介紹了SSH框架網(wǎng)上商城項(xiàng)目第24戰(zhàn)之Struts2中處理多個(gè)Model請(qǐng)求的方法,感興趣的小伙伴們可以參考一下2016-06-06
Java兩整數(shù)相除向上取整的方式詳解(Math.ceil())
在調(diào)外部接口獲取列表數(shù)據(jù)時(shí),需要判斷是否已經(jīng)取完了所有的值,因此需要用到向上取整,下面這篇文章主要給大家介紹了關(guān)于Java兩整數(shù)相除向上取整的相關(guān)資料,需要的朋友可以參考下2022-06-06
SpringBoot中整合Ehcache實(shí)現(xiàn)熱點(diǎn)數(shù)據(jù)緩存的詳細(xì)過程
這篇文章主要介紹了SpringBoot中整合Ehcache實(shí)現(xiàn)熱點(diǎn)數(shù)據(jù)緩存,SpringBoot 中使用 Ehcache 比較簡(jiǎn)單,只需要簡(jiǎn)單配置,說白了還是 Spring Cache 的用法,合理使用緩存機(jī)制,可以很好地提高項(xiàng)目的響應(yīng)速度,需要的朋友可以參考下2023-04-04
SpringCloud創(chuàng)建多模塊項(xiàng)目的實(shí)現(xiàn)示例
,Spring Cloud作為一個(gè)強(qiáng)大的微服務(wù)框架,提供了豐富的功能和組件,本文主要介紹了SpringCloud創(chuàng)建多模塊項(xiàng)目的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-02-02
Java?Collection接口中的常用方法總結(jié)
這篇文章將大概用代碼案例簡(jiǎn)單總結(jié)一下?Collection?接口中的一些方法,我們會(huì)以他的實(shí)現(xiàn)類?Arraylist?為例創(chuàng)建對(duì)象。快一起來看看吧2022-12-12

