logback-spring.xml配置詳解
本文來(lái)寫說(shuō)下logback-spring.xml相關(guān)的知識(shí)與概念
概述
對(duì)于xml日志文件的配置,大多數(shù)人第一次接觸時(shí)有一種望而生畏的感覺,其實(shí)如果仔細(xì)分析,會(huì)發(fā)現(xiàn)核心的部分只有三個(gè)元素:appender、logger、root。
通過(guò)上圖我們可以清晰的了解整個(gè)xml文件的元素及功能。
其中configuration是根元素,必須的;logger和root可視為同一類,都是日志組件;logger定義日志從哪里(包)獲取以及級(jí)別;appender配置日志格式、如何過(guò)濾、文件處理等。property和contextName元素,分別用來(lái)定義變量和應(yīng)用上下文名稱,非必須。
先通過(guò)一個(gè)簡(jiǎn)單的日志模板,從視覺上感受一下:
<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level % logger{36} - %msg%n</pattern> </encoder> </appender> <logger name="chapters.configuration" level="INFO"/> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration>
上述實(shí)例定義了控制臺(tái)輸出debug級(jí)別日志的配置。下面對(duì)相關(guān)的元素進(jìn)行逐一講解。
configuration元素
logback.xml配置文件的基本結(jié)構(gòu)可以描述為configuration元素,包含零個(gè)或多個(gè)appender元素,后跟零個(gè)或多個(gè)logger元素,后跟最多一個(gè)root元素(也可以沒有)。
根元素configuration有三個(gè)屬性:
- debug:默認(rèn)為false,若設(shè)置為true,則打印出logback內(nèi)部日志信息。
- scan:默認(rèn)值為true,若設(shè)置為true,配置文件如果發(fā)生改變,將會(huì)被重新加載。
- scanPeriod:與scan配合使用,當(dāng)scan為true時(shí),此屬性生效,默認(rèn)的時(shí)間間隔為1分鐘,設(shè)置監(jiān)測(cè)配置文件是否有修改的時(shí)間間隔,如果沒有給出時(shí)間單位,默認(rèn)單位是毫秒。如可以設(shè)置為scanPeriod="30 seconds"每30秒檢測(cè)一次。
定義上下文名稱
contextName元素,每一個(gè)日志組件(logger)都會(huì)關(guān)聯(lián)到日志上下文,默認(rèn)上下文名稱是’default’,用于標(biāo)識(shí)應(yīng)用,如果多個(gè)應(yīng)用輸出到同一個(gè)地方,就有必要使用%contextName來(lái)區(qū)別。
上線文的配置直接在configuration元素下:
<configuration> <contextName>HelloWorld-log</contextName> </configuration>
經(jīng)過(guò)定義之后,在其他property屬性或appender中便可通過(guò)“%contextName”來(lái)獲取和使用該上下文名稱了。
定義變量
通過(guò)property元素可定義變量。它有name和value兩個(gè)屬性。變量可以使“${name}”來(lái)使用變量。作用類似于代碼中的常量字符串,定義之后公共地方便可以統(tǒng)一使用。如日志文件名稱前綴、日志路徑、日志輸出格式等。
<configuration> <property name="log.path" value="./log" /> </configuration>
上面便是定義了日志的根路徑的變量。
如果是在Spring或SpringBoot項(xiàng)目當(dāng)中,想讓value值是通過(guò)配置文件獲取,可使用springProperty來(lái)定義。
<springProperty scope="context" name="log.path" source="catalina.base"/>
其中source指定的catalina.base便是在application.properties當(dāng)中配置變量。此配置還是比較常用的,可以做到靈活區(qū)分環(huán)境。
appender組件
appender組件用來(lái)定義日志輸出格式,日志如何過(guò)濾以及日志文件的處理。appender的結(jié)構(gòu)如下:
appender的屬性有name和class。name指定appender名稱,后面使用該appender是也是通過(guò)名稱來(lái)指定。
class屬性指定要實(shí)例化的appender類的完全限定名稱。appender類默認(rèn)有以下幾種:
- ConsoleAppender:日志輸出到控制臺(tái),類名ch.qos.logback.core.ConsoleAppender。
- FileAppender:日志輸入到文件,類名ch.qos.logback.core.FileAppender。
- RollingFileAppender:滾動(dòng)記錄文件,F(xiàn)ileAppender的子類,當(dāng)符合條件(大小、時(shí)間),日志進(jìn)行切分處理。類名:ch.qos.logback.core.rolling.RollingFileAppender。
appender元素可以包含零個(gè)或一個(gè)layout元素,零個(gè)或多個(gè)encoder元素以及零個(gè)或多個(gè)filter元素。
實(shí)戰(zhàn)中ConsoleAppender及RollingFileAppender使用較多,若需要自定義如把日志輸出到消息隊(duì)列,可以自定義實(shí)現(xiàn)AppenderBase接口。
ConsoleAppender上面已經(jīng)有示例,主要作用就是將日志輸出到控制臺(tái),并通過(guò)pattern元素指定了輸出的格式。下面重點(diǎn)看一下RollingFileAppender的配置。
RollingFileAppender配置
RollingFileAppender是FileAppender的子類,擴(kuò)展了FileAppender,具有翻轉(zhuǎn)日志文件的功能。
例如,RollingFileAppender可以記錄到名為log.txt文件的文件,并且一旦滿足某個(gè)條件,就將其日志記錄目標(biāo)更改為另一個(gè)文件。
RollingFileAppender通常包括File、filter,rollingPolicy,encoder和layout元素。
encoder用來(lái)指定日志的輸出格式及編碼等:
<!-- 文件輸出日志格式 --> <property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n" /> <appender> <!--日志文件輸出格式--> <encoder> <pattern>${FILE_LOG_PATTERN}</pattern> <charset class="java.nio.charset.Charset">UTF-8</charset> </encoder> </appender>
file元素用來(lái)配置日志的路徑和名稱,一般把路徑和文件名前綴定義到變量(property中)。
<encoder> <!-- 正在記錄的日志文件的路徑及文件名 --> <file>${log.path}/log_error.log</file> </appender>
${log.path}獲取的便是前面屬性中定義的變量。
appender中可以有多個(gè)filter元素,比如用ThresholdFilter來(lái)過(guò)濾低于指定臨界值的日志;用LevelFilter來(lái)過(guò)濾日志級(jí)別。以LevelFilter為例:
<!-- 過(guò)濾器,只記錄debug級(jí)別的日志 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>DEBUG</level> <OnMismatch>DENY</OnMismatch> <OnMatch>ACCEPT</OnMatch> </filter>
其中l(wèi)evel指定日志級(jí)別,onMath指定符合過(guò)濾條件的操作接收(ACCEPT),onMismatch指定不符合條件的拒絕(DENY)。
如果需要將不同級(jí)別的日志輸出到不同的日志文件,那么就需要配置多個(gè)filter,每個(gè)filter像上面一樣指定level級(jí)別:DEBUG,INFO,WARN和ERROR。
通常情況下,日志輸出會(huì)配置三個(gè),一個(gè)控制臺(tái)輸出用于開發(fā)階段;一個(gè)INFO及以上級(jí)別的日志輸出,可追蹤相應(yīng)的生產(chǎn)日志;一個(gè)單獨(dú)ERROR級(jí)別的日志輸出,方便快速檢查出異常日志。
rollingPolicy用于配置滾動(dòng)策略,支持TimeBasedRollingPolicy、SizeAndTimeBasedRollingPolicy、FixedWindowRollingPolicy、SizeBasedTriggeringPolicy。
分別是基于時(shí)間滾動(dòng)、基于大小和時(shí)間滾動(dòng)、固定窗口滾動(dòng)和大小觸發(fā)。其中FixedWindowRollingPolicy一般和SizeBasedTriggeringPolicy同時(shí)使用。下面以TimeBasedRollingPolicy為例,以天為單位輸出日志,每天一個(gè)日志。
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 日志輸出格式 --> <fileNamePattern>${log.path}/debug.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 日志保留天數(shù) --> <maxHistory>30</maxHistory> </rollingPolicy>
fileNamePattern指定日志的路徑及名稱,此處是按日期輸出,即%d{yyyy-MM-dd}格式。maxHistory表示日志最多保留天數(shù),存活超過(guò)30天的日志會(huì)被刪除。
logger配置
logger用來(lái)設(shè)置某一個(gè)類或者某個(gè)包的日志輸出級(jí)別、以及關(guān)聯(lián)的appender。
logger包含三個(gè)屬性:
- name:要輸出日志的包名或者類名,比如com.secbro2。必選項(xiàng)。
- level:設(shè)置日志級(jí)別,允許一個(gè)不區(qū)分大小寫的字符串值TRACE,DEBUG,INFO,WARN,ERROR,ALL或OFF。如果未設(shè)置,則logger會(huì)向上繼承最近一個(gè)非空級(jí)別。可選項(xiàng)。
- additivity:是否將日志向上級(jí)傳遞,默認(rèn)為 true??蛇x項(xiàng)。
logger通過(guò)1個(gè)或多個(gè)子節(jié)點(diǎn)appender-ref來(lái)控制日志的輸出。
<logger name="org.springframework" level="WARN"/> <logger name="com" level="debug" />
上面示例表示org.springframework包下的日志以warn級(jí)別輸出,com包下的日志以debug級(jí)別輸出。
<logger name="com.secbro2" level="info" additivity="true"> <appender-ref ref="CONSOLE" /> </logger>
上面的示例對(duì)指定包指定appender進(jìn)行日志控制,由于設(shè)置了info級(jí)別,additivity為true,而且關(guān)聯(lián)CONSOLE的appender,因此info以上級(jí)別的日志會(huì)輸出到控制臺(tái)。
同時(shí)會(huì)把日志上傳到父級(jí),即root。若root也有配置CONSOLE的輸出的話,會(huì)在控制臺(tái)輸出兩次。additivity為false,則不會(huì)。
root配置
root元素配置根記錄器。它是一個(gè)特殊的logger,是所有l(wèi)ogger的根節(jié)點(diǎn),只有一個(gè)屬性level,默認(rèn)為DEBUG 。
<root level="info"> <appender-ref ref="CONSOLE" /> <appender-ref ref="LOGSTASH" /> <appender-ref ref="INFO_FILE" /> <appender-ref ref="ERROR_FILE" /> </root>
level屬性的值可以是不區(qū)分大小寫的字符串TRACE,DEBUG,INFO,WARN,ERROR,ALL或OFF之一。root元素可以包含零個(gè)或多個(gè)appender-ref元素;被引用的每個(gè)appender都被添加到根記錄器中。
如果是基于SpringBoot項(xiàng)目,針對(duì)不同環(huán)境(profile)有不同的日志輸出,比如開發(fā)(dev)環(huán)境只輸出CONSOLE的,生產(chǎn)環(huán)境(prod)只輸入info和error,那則可用到Spring支持的profile機(jī)制。對(duì)應(yīng)的元素為springProfile。
profile的值與springboot中配置文件的spring.profiles.active值進(jìn)行對(duì)照。
<!-- 開發(fā)環(huán)境 --> <springProfile name="dev"> <logger name="com" level="debug" /> <root level="info"> <appender-ref ref="CONSOLE" /> </root> </springProfile> <!-- 測(cè)試環(huán)境+生產(chǎn)環(huán)境 --> <springProfile name="test,prod"> <logger name="com" level="info" /> <root level="info"> <appender-ref ref="INFO_FILE" /> <appender-ref ref="ERROR_FILE" /> </root> </springProfile>
當(dāng)引入了springProfile,我們可以看到root元素可以出現(xiàn)多次了,但還是保證了一個(gè)環(huán)境只有一個(gè)root元素的要求。springProfile的name對(duì)應(yīng)spring.profiles.active的值,多個(gè)值用逗號(hào)分隔。
ELK的配置
如果項(xiàng)目中的日志采用的是基于ELK(Elasticsearch,Logstash,Kibana三個(gè)開源軟件的縮寫)來(lái)進(jìn)行日志管理。則可以在pom文件中引入logstash-logback-encoder依賴。
<dependency> <groupId>net.logstash.logback</groupId> <artifactId>logstash-logback-encoder</artifactId> <version>5.1</version> </dependency>
然后在logback-spring.xml中配置對(duì)應(yīng)的appender:
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>debug</level> </filter> <destination>192.168.0.11:5061</destination> <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder"> <customFields>{"project": "springboot-logback-elk"}</customFields> </encoder> </appender>
該appender的使用與其他appender的使用無(wú)異。主要使用了LogstashTcpSocketAppender類來(lái)完成與Logstash的通信。其中destination為L(zhǎng)ogstash提供的服務(wù)地址。customFields為自定義的參數(shù),便于Logstash識(shí)別日志是從哪個(gè)業(yè)務(wù)系統(tǒng)傳輸過(guò)來(lái)的。
輸出logback狀態(tài)數(shù)據(jù)
某些時(shí)候?yàn)榱肆私鈒ogback配置文件加載情況,配置中對(duì)應(yīng)的appender、logger的裝載情況等,我們需要啟用logback狀態(tài)數(shù)據(jù)的輸出。這也是logback官網(wǎng)強(qiáng)烈推薦的,可以幫助我們排除診斷一些問(wèn)題。
啟用狀態(tài)數(shù)據(jù)輸出有兩種方式:
- 在根元素(configuration) 中設(shè)置屬性debug=“true”。
- 添加元素(statusListener),class使用OnConsoleStatusListener。如下:
<!-- 輸出logback的本身狀態(tài)數(shù)據(jù) --> <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
兩種方式選其一即可。第一種方式的debug與配置文件中的日志級(jí)別沒有關(guān)系,只用于表示輸出狀態(tài)數(shù)據(jù)。
異步輸出日志
前面講到的appender,日志輸出到文件是同步輸出的,即每次輸出都會(huì)直接寫IO到磁盤文件。對(duì)于高并發(fā)的應(yīng)用,會(huì)產(chǎn)生一定的阻塞,造成不必要的性能損耗。
logback提供了日志異步輸出的AsyncAppender。處理方式也很簡(jiǎn)單,添加一個(gè)基于異步寫日志的appender,并指向原配置的appender即可:
<!-- 異步輸出 --> <appender name="ASYNCDEBUG" class="ch.qos.logback.classic.AsyncAppender"> <!-- 默認(rèn)如果隊(duì)列的80%已滿,則會(huì)丟棄TRACT、DEBUG、INFO級(jí)別的日志,若要保留全部日志,設(shè)置為0 --> <discardingThreshold>0</discardingThreshold> <!-- 更改默認(rèn)的隊(duì)列的深度,該值會(huì)影響性能.默認(rèn)值為256 --> <queueSize>1024</queueSize> <!-- 添加附加的appender,最多只能添加一個(gè) --> <appender-ref ref="DEBUGFILE"/> <includeCallerData>true</includeCallerData> </appender> <!-- 異步輸出關(guān)聯(lián)到root --> <root level="DEBUG"> <appender-ref ref="STDOUT"/> <appender-ref ref="ASYNCDEBUG" /> //... </root>
AsyncAppender的實(shí)現(xiàn)原理是通過(guò)阻塞隊(duì)列(BlockingQueue)來(lái)避免日志直接輸出到文件,先把日志事件輸出到BlockingQueue中,然后啟動(dòng)一個(gè)新的worker線程,主線程不阻塞,worker線程則從隊(duì)列中獲取需要寫的日志,異步輸出到對(duì)應(yīng)的位置。
代碼中的日志格式
在日常使用日志時(shí),可以通過(guò)最開始的示例定義Logger對(duì)象,然后調(diào)用其對(duì)應(yīng)級(jí)別的日志輸出。當(dāng)然,如果采用Lombok的情況下,可直接類上使用@Slf4j注解來(lái)自動(dòng)注入log屬性,不用再聲明:
private static final Logger log = LoggerFactory.getLogger(LogbackController.class);
替換為:
@Slf4j @RestController public class LogbackController { }
其他內(nèi)容不變。
而在日志輸出格式也有多種,其中最不可取的形式是如下模式的日志輸出:
Object entry = new SomeObject(); logger.debug("The entry is " + entry);
這種模式會(huì)導(dǎo)致即使采用info基本輸出,debug中的對(duì)象toString和字符串拼裝依舊會(huì)處理。建議采用如下模式輸出:
Object entry = new SomeObject(); logger.debug("The entry is {}.", entry);
此時(shí),如果日志輸出級(jí)別為info,則不會(huì)處理對(duì)象的toString和字符串的拼接。
logback作者進(jìn)行測(cè)試得出:第一種和第二種寫法輸出結(jié)果相同。但在禁用日志記錄語(yǔ)句的情況下,第二種將比第一種寫法優(yōu)于至少30倍。
本文小結(jié)
到此,關(guān)于logback日志框架的講解告一段落,如果你還想了解更多底層原理和一些表達(dá)式,建議看一下官方的手冊(cè),雖然是英文的,但還是比較全面的。
本文用巨大篇幅,描述了logback日志常見的使用場(chǎng)景,想必讀到此處時(shí),原來(lái)在那復(fù)雜的日志配置文件已經(jīng)變得十分簡(jiǎn)單吧。趕快嘗試一下吧。用了兩天寫完這篇文章,多多支持,你懂得該怎么做的。
到此這篇關(guān)于logback-spring.xml詳解的文章就介紹到這了,更多相關(guān)logback-spring.xml內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java求10到100000之間的水仙花數(shù)算法示例
這篇文章主要介紹了Java求10到100000之間的水仙花數(shù)算法,結(jié)合實(shí)例形式分析了水仙花數(shù)的概念及相應(yīng)的java算法實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-10-10Java中Lombok的@Builder注解注意事項(xiàng)
這篇文章主要介紹了Java中Lombok的@Builder注解注意事項(xiàng),使用Lombok也會(huì)造成很多問(wèn)題,尤其@Builder 有個(gè)很大的坑,已經(jīng)見過(guò)好幾次由于使用@Builder注解導(dǎo)致默認(rèn)值失效的問(wèn)題,如果測(cè)試時(shí)沒有在意這個(gè)問(wèn)題,就很容易引發(fā)線上問(wèn)題,需要的朋友可以參考下2023-12-12Springboot整合nacos報(bào)錯(cuò)無(wú)法連接nacos的解決
這篇文章主要介紹了Springboot整合nacos報(bào)錯(cuò)無(wú)法連接nacos的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06springboot2.0如何通過(guò)fastdfs實(shí)現(xiàn)文件分布式上傳
這篇文章主要介紹了springboot2.0如何通過(guò)fastdfs實(shí)現(xiàn)文件分布式上傳,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12java多線程通過(guò)CompletableFuture組裝異步計(jì)算單元
這篇文章主要為大家介紹了java多線程通過(guò)CompletableFuture組裝異步計(jì)算單元,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04javamail實(shí)現(xiàn)注冊(cè)激活郵件
這篇文章主要為大家詳細(xì)介紹了javamail實(shí)現(xiàn)注冊(cè)激活郵件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04SpringBoot+Vue項(xiàng)目部署實(shí)現(xiàn)傳統(tǒng)方式
我們?cè)谶M(jìn)行前后端分離開發(fā)的時(shí)候,一般是將前端項(xiàng)目部署到nginx服務(wù)器上,與后端項(xiàng)目分開部署,這篇文章主要給大家介紹了關(guān)于SpringBoot+Vue項(xiàng)目部署實(shí)現(xiàn)傳統(tǒng)方式的相關(guān)資料,需要的朋友可以參考下2024-01-01將InputStream轉(zhuǎn)化為base64的實(shí)例
這篇文章主要介紹了將InputStream轉(zhuǎn)化為base64的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12