[轉]SpringBoot從入門到進階——學會Logback日誌的配置和搭建
原文連結 作者: 比腳更長的路
內容
從實際專案需求出發,以最快的速度實現SpringBoot下Logback的配置。然後先後實踐測試了SpringBoot內建的基礎配置(SizeBasedTriggeringPolicy)、按時間劃分日誌檔案的配置(TimeBasedRollingPolicy) 、同時按時間和大小劃分日誌檔案的配置(SizeAndTimeBasedRollingPolicy)、不同級別日誌輸出到不同日誌檔案四種情況。
版本
IDE:IDEA 2017.2.2 x64
JDK:1.8.0_171
manve:3.3.3
SpringBoot:1.5.9.RELEASE
Logback:1.1.11(SpringBoot中適配的版本)
適合人群
Java開發人員
說明
轉載請說明出處:SpringBoot從入門到進階——學會Logback日誌的配置和搭建
參考
注意
修改過電腦時間後,intelij idea的游標無法聚焦到程式碼區,需要重啟 intelij idea才能繼續編寫程式碼。
步驟
快速配置出項目所需的Logback 專案對於日誌的要求: 通常,我們對於專案的日誌會有如下要求:
1、時效性:儲存30天
2、按時間分割:每個小時生成1個資料夾
3、按大小分割:每個日誌檔案大小不超過50MB
4、限定體積:日誌檔案總大小20GB
5、按級別分割:不同級別的日誌儲存到不同的檔案中
下面,我們先基於這些常見的需求,搭建出一個SpringBoot專案。
Logback配置: application.yaml #其他配置 … #指明日誌存放位置,在jar包所在路徑下的logs資料夾中 logging: file: logs/application-gatewayservice-${server.port}.logs logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>logback-spring-file-level.xml <?xml version="1.0" encoding="UTF-8"?> ${LOG_FILE}.INFOLevel.%d{yyyy-MM-dd_HH}.%i.log 50MB 30 20GB INFO ACCEPT DENY %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n<!-- 設定root logger的級別為INFO,並將控制檯輸出和檔案輸出中的appender都新增到root logger下 --> <root level="INFO"> <appender-ref ref="CONSOLE" /> <appender-ref ref="INFO_FILE" /> <appender-ref ref="WARN_FILE" /> <appender-ref ref="ERROR_FILE" /> </root> <jmxConfigurator/>
<!--只輸出WARN Level到日誌檔案的appender-->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- %i用來標記分割日誌的序號 -->
<fileNamePattern>${LOG_FILE}.WARNLevel.%d{yyyy-MM-dd_HH}.%i.log</fileNamePattern>
<!-- 單個日誌檔案最大50MB, 儲存30天的日誌, 日誌檔案空間為20GB -->
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<!--配置日誌的級別過濾器,只保留WARN Level的日誌-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!--只輸出ERROR Level到日誌檔案的appender-->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- %i用來標記分割日誌的序號 -->
<fileNamePattern>${LOG_FILE}.ERRORLevel.%d{yyyy-MM-dd_HH}.%i.log</fileNamePattern>
<!-- 單個日誌檔案最大50MB, 儲存30天的日誌, 日誌檔案空間為20GB -->
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<!--配置日誌的級別過濾器,只保留ERROR Level的日誌-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
專案啟動後,日誌檔案會保留在jar包所在路徑下的logs資料夾中,並且按照日誌級別,輸出到不同的檔案中。
同時,每小時會生成一個日誌檔案,如果當日志文件的大小超過50MB時,會分割日誌檔案。日誌系統會保留30天的日誌檔案,且當所有日誌檔案的大小超過20GB時,日誌系統會在下一天的0時,刪除部分日誌檔案,使日誌檔案總體的大小控制在20GB以內。
專案原始碼地址:FastConfig
SpringBoot內建的基礎配置: application.yaml #指明日誌存放位置 logging: file: logs/application-gatewayservice-${server.port}.logs logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> 其中的base.xml,引自SpringBoot的jar包中的基礎配置:1540955132065
base.xml 可以看到base.xml中引入了defaults.xml,以及控制檯輸出日誌配置檔案console-appender.xml和檔案輸出日誌配置檔案file-appender.xml。
<?xml version="1.0" encoding="UTF-8"?> defaults.xml和console-appender.xml在本示例中不做討論。file-appender.xml 通過檔案輸出日誌配置檔案,可以看到預設情況下SpringBoot的日誌系統限定單個檔案大小為10MB。
<?xml version="1.0" encoding="UTF-8"?> ${FILE_LOG_PATTERN} ${LOG_FILE} ${LOG_FILE}.%i 10MB 列印日誌的測試介面 @Controller public class LogController { Logger logger=Logger.getLogger("LogController"); @GetMapping("/log") @ResponseBody public String testLog(){ for (int i=0;i<1000;i++) logger.info(String.valueOf(i)); return "999"; } } SizeBasedTriggeringPolicy的測試 使用Postman進行日誌介面的重複呼叫,此處請求100次"/log"。1540956372674
日誌檔案超過10MB,日誌系統會自動分割日誌檔案,使得單個檔案大小在10MB以內。
1540956468416
配置檔案的fileNamePattern{LOG_FILE}.%i中的i為序號。
通過本例的測試可知,最早的日誌檔案,序號越大,每次分割檔案時,所有日誌檔案的序號都會更新。最早的日誌檔案序號始終是最大的。
如果刪除了舊的日誌檔案,會發生什麼呢?
1540956737704
使用Postman再次呼叫日誌測試介面生成日誌,可以看到日誌系統會重新編號。
1540956900748
觀察大小10MB的日誌檔案,其中大約9.6W行資料。因此平均一行的日誌大概104個位元組。
1540956057238
專案原始碼地址:DefaultConfig
按時間劃分日誌檔案 SpringBoot內建的日誌系統使用SizeBasedTriggeringPolicy將日誌檔案在佔用空間的維度進行分割。下面我們使用TimeBasedRollingPolicy,將日誌檔案按時間維度進行分割,示例保留了3天的日誌,並且日誌檔案的最大容量為20MB。
專案配置檔案application.yaml不變。
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> logback-spring-file.xml <?xml version="1.0" encoding="UTF-8"?> ${LOG_FILE}.%d{yyyy-MM-dd_HH}.log 3 20MB %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 注意:file-appender的配置,位置一定要放在標籤之前,否則報如下錯誤:java.lang.IllegalStateException: Logback configuration error detected:
Could not find an appender named [FILE]. Did you define it below instead of above in the configuration file?
TimeBasedRollingPolicy測試 測試totalSizeCap 開啟專案後執行一段時間,可以觀察到日誌檔案會按照FileNamePattern中規定的最小時間週期HH(小時)分割日誌檔案。
1540968935404
使用Postman呼叫日誌測試介面生成日誌,使單個日誌檔案的大小超過20MB。
1540969062304
整點過後,發現13點和14點的日誌檔案被刪除,剩餘日誌檔案的大小保持在20MB以內。
1540969597549
由此測試可知配置檔案中totalSizeCap的含義:所有日誌檔案的大小在一個計時週期內(小時HH)可以超過totalSizeCap設定的容量,但是在下一個計時週期開始時,日誌系統會清理日誌檔案,確保日誌檔案總體的大小在totalSizeCap以內。
測試MaxHistory 當日志容量不超過totalSizeCap時,更改系統日期為10月30日,10月31日,11月1日,11月2日,並呼叫日誌測試介面生成日誌。
1541057233143
當記錄11月2日的日誌時,日誌系統會清除11月1日的日誌檔案,保留10月30日、10月31日、11月2日三天的日誌。
再將日期改成11月10日,呼叫日誌測試介面生成日誌,日誌系統會清除11月2日的日誌檔案,保留10月30日、10月31日、11月10日三天的日誌。由此可見MaxHistory只是限定儲存日誌的天數,而不是限定儲存最近自然日日誌的天數,
通過上面的觀察可以發現,在新的日誌計時週期到來時,如果所有日誌檔案大小之和超過totalSizeCap,或日誌記錄天數超過MaxHistory。日誌系統會優先刪除最近日期的日誌檔案,使的日誌大小在totalSizeCap內,且日誌記錄天數在MaxHistory內。
專案原始碼地址:TimeBasedConfig
同時按時間和大小劃分日誌檔案的配置 配置檔案application.yaml不變。
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> Logback-spring-file.xml <?xml version="1.0" encoding="UTF-8"?> ${LOG_FILE}.%d{yyyy-MM-dd_HH}.%i.log 10MB 3 50MB %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n SizeAndTimeBasedRollingPolicy測試 專案啟動後的日誌資訊:測試maxFileSize: 呼叫日誌測試介面生成日誌,當單個日誌檔案大小超過10MB時,會新建日誌檔案儲存超過10MB部分的日誌內容,並且新日誌檔案的序號大於舊日誌檔案的序號(序號規則與Spring內建使用的SizeBasedTriggeringPolicy相反)。
測試maxHistory: 分別更改系統日期為10月30日,10月31日,11月1日,11月2日並呼叫日誌測試介面生成日誌。
當記錄11月2日的日誌時,日誌系統會清除11月1日的日誌檔案,保留10月30日,10月31日,11月2日三天的日誌。
測試totalSizeCap: 呼叫日誌測試介面生成日誌,使所有日誌檔案大小之和超過50MB。此時日誌仍然在記錄,日誌檔案大小還在增長。
將系統時間調至1小時後,繼續呼叫日誌測試介面生成日誌,日誌檔案大小超過60MB,此時日誌仍然在記錄,日誌檔案大小還在增長。
將系統時間調至1天后,日誌系統進行了日誌檔案的清理,日誌系統清除了11月2日的日誌檔案,保留10月30日,10月31日,11月3日三天的日誌,並使的日誌檔案大小在50MB範圍內。
可見此示例中SizeAndTimeBasedRollingPolicy清理的週期(一天)與TimeBasedRollingPolicy不同(一個小時)。
專案原始碼地址:SizeAndTimeBasedConfig
按日誌級別輸出到不同的檔案中 配置檔案application.yaml不變。
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> logback-spring-file-level.xml <?xml version="1.0" encoding="UTF-8"?> ${LOG_FILE}.INFOLevel.%d{yyyy-MM-dd_HH}.%i.log 10MB 3 50MB INFO ACCEPT DENY %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n ${LOG_FILE}.WARNLevel.%d{yyyy-MM-dd_HH}.%i.log 10MB 3 50MB WARN ACCEPT DENY %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n ${LOG_FILE}.ERRORLevel.%d{yyyy-MM-dd_HH}.%i.log 10MB 3 50MB ERROR ACCEPT DENY %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n Controller @Controller public class TestLogController { Logger logger=Logger.getLogger("TestLogController"); @GetMapping("/logInfo") @ResponseBody public String testLog(){ for (int i=0;i<1000;i++) logger.info(String.valueOf(i)); return "999"; } @GetMapping("/logWarn") @ResponseBody public String testLogWarn(){ for (int i=0;i<1000;i++) logger.warning(String.valueOf(i)); return "999"; } @GetMapping("/logError") @ResponseBody public String testLogError(){ for (int i=0;i<1000;i++) logger.severe(String.valueOf(i)); return "999"; } } 按日誌級別輸出到不同檔案的測試: 先後呼叫測試介面 http://localhost:7081/logInfo、http://localhost:7081/logWarn、http://localhost:7081/logError,分別記錄INFO、WARN、ERRER級別的日誌。INFO日誌
WARN日誌
ERRER日誌
可見,通過定義多個Appender,結合filter實現了不同級別的日誌輸出到不同檔案中。
專案原始碼地址:LevelConfig