1. 程式人生 > >[轉]SpringBoot從入門到進階——學會Logback日誌的配置和搭建

[轉]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"?>
<!-- 設定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/>
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
<!--只輸出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