SpringBoot從入門到進階——學會Logback日誌的配置和搭建

內容html

  從實際項目需求出發,以最快的速度實現SpringBoot下Logback的配置。而後前後實踐測試了SpringBoot內置的基礎配置(SizeBasedTriggeringPolicy)、按時間劃分日誌文件的配置(TimeBasedRollingPolicy) 、同時按時間和大小劃分日誌文件的配置(SizeAndTimeBasedRollingPolicy)、不一樣級別日誌輸出到不一樣日誌文件四種狀況。java

版本git

  IDE:IDEA 2017.2.2 x64github

​  JDK:1.8.0_171spring

  manve:3.3.3app

  SpringBoot:1.5.9.RELEASEide

  Logback:1.1.11(SpringBoot中適配的版本)post

適合人羣測試

  Java開發人員idea

說明

  轉載請說明出處:SpringBoot從入門到進階——學會Logback日誌的配置和搭建

  GitHub倉庫:https://github.com/leo-zz/SpringBootDemo

參考

  官方文檔中filters內容: https://Logback.qos.ch/manual/filters.html

  官方文檔中appenders內容:https://Logback.qos.ch/manual/appenders.html

注意

  修改過電腦時間後,intelij idea的光標沒法聚焦到代碼區,須要重啓 intelij idea才能繼續編寫代碼。

步驟

快速配置出項目所需的Logback

項目對於日誌的要求:

  一般,咱們對於項目的日誌會有以下要求:

  一、時效性:保存30天

  二、按時間分割:每一個小時生成1個文件夾

  三、按大小分割:每一個日誌文件大小不超過50MB

  四、限定體積:日誌文件總大小20GB

  五、按級別分割:不一樣級別的日誌保存到不一樣的文件中

  下面,咱們先基於這些常見的需求,搭建出一個SpringBoot項目。

Logback配置:

application.yaml
#其餘配置
... 
#指明日誌存放位置,在jar包所在路徑下的logs文件夾中
logging:
  file: logs/application-gatewayservice-${server.port}.logs
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
     <!-- 引入SpringBoot的默認配置文件defaults.xml -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
    <!-- 引入SpringBoot中內置的控制檯輸出配置文件console-appender.xml -->
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
    <!-- 引入自定義的文件輸出配置文件logback-spring-file-level.xml -->
    <include resource="logback-spring-file-level.xml" />
    
    <!-- 設置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/>
</configuration>
logback-spring-file-level.xml
<?xml version="1.0" encoding="UTF-8"?>
<included>
    <!--只輸出INFO Level到日誌文件的appender-->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--日誌文件輸出的文件名,%i用來標記分割日誌的序號 -->
            <fileNamePattern>${LOG_FILE}.INFOLevel.%d{yyyy-MM-dd_HH}.%i.log</fileNamePattern>
            <!-- 單個日誌文件最大50MB, 保存30天的日誌, 日誌文件空間爲20GB -->
            <maxFileSize>50MB</maxFileSize>
            <maxHistory>30</maxHistory>
            <totalSizeCap>20GB</totalSizeCap>
        </rollingPolicy>
        <!--配置日誌的級別過濾器,只保留INFO Level的日誌-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度,%msg:日誌消息,%n是換行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>

    <!--只輸出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>
</included>

  項目啓動後,日誌文件會保留在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"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <jmxConfigurator/>
</configuration>

  其中的base.xml,引自SpringBoot的jar包中的基礎配置:

1540955132065

base.xml

  能夠看到base.xml中引入了defaults.xml,以及控制檯輸出日誌配置文件console-appender.xml和文件輸出日誌配置文件file-appender.xml。

<?xml version="1.0" encoding="UTF-8"?>
<!--Base logback configuration provided for compatibility with Spring Boot 1.1-->
<included>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
    <include resource="org/springframework/boot/logging/logback/file-appender.xml"/>
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </root>
</included>

  defaults.xml和console-appender.xml在本示例中不作討論。

file-appender.xml

  經過文件輸出日誌配置文件,能夠看到默認狀況下SpringBoot的日誌系統限定單個文件大小爲10MB。

<?xml version="1.0" encoding="UTF-8"?>
<included>
    <appender name="FILE" class="ch.qos.Logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
        <file>${LOG_FILE}</file>
        <rollingPolicy class="ch.qos.Logback.core.rolling.FixedWindowRollingPolicy">
            <fileNamePattern>${LOG_FILE}.%i</fileNamePattern>
        </rollingPolicy>
        <triggeringPolicy class="ch.qos.Logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>
</included>

打印日誌的測試接口

@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"?>
<configuration><include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" /><include resource="logback-spring-file.xml" /><root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    </root>
    <jmxConfigurator/>
</configuration>

logback-spring-file.xml

<?xml version="1.0" encoding="UTF-8"?>
<included>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 此處的${LOG_FILE}是yaml文件中配置的logging.file屬性 %d{yyyy-MM-dd_HH}區分了年月日以及小時-->
            <FileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd_HH}.log</FileNamePattern>
            <!-- 日誌文件保留近3天,而且最大容量爲20MB -->
            <MaxHistory>3</MaxHistory>
            <totalSizeCap>20MB</totalSizeCap>
        </rollingPolicy>
        <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>
</included>

  注意:file-appender的配置,位置必定要放在<ROOT>標籤以前,不然報以下錯誤:

  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日三天的日誌。

1541143729656

  再將日期改爲11月10日,調用日誌測試接口生成日誌,日誌系統會清除11月2日的日誌文件,保留10月30日、10月31日、11月10日三天的日誌。因而可知MaxHistory只是限定保存日誌的天數,而不是限定保存最近天然日日誌的天數,

1540971323304

  經過上面的觀察能夠發現,在新的日誌計時週期到來時,若是全部日誌文件大小之和超過totalSizeCap,或日誌記錄天數超過MaxHistory。日誌系統會優先刪除最近日期的日誌文件,使的日誌大小在totalSizeCap內,且日誌記錄天數在MaxHistory內。

  項目源碼地址:TimeBasedConfig

同時按時間和大小劃分日誌文件的配置

  配置文件application.yaml不變。

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--<include resource="org/springframework/boot/logging/logback/base.xml"/>-->
    <!--測試按照時間分割日誌文件-->
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
    <include resource="logback-spring-file.xml" />
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    </root>
    <jmxConfigurator/>
</configuration>

Logback-spring-file.xml

<?xml version="1.0" encoding="UTF-8"?>
<included>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- %i用來標記分割日誌的序號 -->
            <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd_HH}.%i.log</fileNamePattern>
            <!-- 單個日誌文件最大10MB, 保存3天的歷史日誌, 全部日誌文件最大50MB -->
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>3</maxHistory>
            <totalSizeCap>50MB</totalSizeCap>
        </rollingPolicy>
        <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>
</included>

SizeAndTimeBasedRollingPolicy測試

​   項目啓動後的日誌信息:

1540973544860

測試maxFileSize:

  調用日誌測試接口生成日誌,當單個日誌文件大小超過10MB時,會新建日誌文件存儲超過10MB部分的日誌內容,而且新日誌文件的序號大於舊日誌文件的序號(序號規則與Spring內置使用的SizeBasedTriggeringPolicy相反)。

1540974375988

測試maxHistory:

  分別更改系統日期爲10月30日,10月31日,11月1日,11月2日並調用日誌測試接口生成日誌。

1541061122949

  當記錄11月2日的日誌時,日誌系統會清除11月1日的日誌文件,保留10月30日,10月31日,11月2日三天的日誌。

1541147624399

測試totalSizeCap:

  調用日誌測試接口生成日誌,使全部日誌文件大小之和超過50MB。此時日誌仍然在記錄,日誌文件大小還在增加。1541148062409

  將系統時間調至1小時後,繼續調用日誌測試接口生成日誌,日誌文件大小超過60MB,此時日誌仍然在記錄,日誌文件大小還在增加。

1541151848427

  將系統時間調至1天后,日誌系統進行了日誌文件的清理,日誌系統清除了11月2日的日誌文件,保留10月30日,10月31日,11月3日三天的日誌,並使的日誌文件大小在50MB範圍內。

1541152118166

  可見此示例中SizeAndTimeBasedRollingPolicy清理的週期(一天)與TimeBasedRollingPolicy不一樣(一個小時)。

  項目源碼地址:SizeAndTimeBasedConfig

 

按日誌級別輸出到不一樣的文件中

  配置文件application.yaml不變。

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--測試按照時間分割日誌文件-->
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
    <include resource="logback-spring-file-level.xml" /><root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="INFO_FILE" />
        <appender-ref ref="WARN_FILE" />
        <appender-ref ref="ERROR_FILE" />
    </root>
    <jmxConfigurator/>
</configuration>

logback-spring-file-level.xml

<?xml version="1.0" encoding="UTF-8"?>
<included>
    <!--只保留INFO Level的日誌-->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- %i用來標記分割日誌的序號 -->
            <fileNamePattern>${LOG_FILE}.INFOLevel.%d{yyyy-MM-dd_HH}.%i.log</fileNamePattern>
            <!-- 單個日誌文件最大10MB, 保存3天的歷史日誌, 全部日誌文件最大50MB -->
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>3</maxHistory>
            <totalSizeCap>50MB</totalSizeCap>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</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><!--只保留 WARN Level的日誌-->
    <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>
            <!-- 單個日誌文件最大10MB, 保存3天的歷史日誌, 全部日誌文件最大50MB -->
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>3</maxHistory>
            <totalSizeCap>50MB</totalSizeCap>
        </rollingPolicy>
        <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 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>
            <!-- 單個日誌文件最大10MB, 保存3天的歷史日誌, 全部日誌文件最大50MB -->
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>3</maxHistory>
            <totalSizeCap>50MB</totalSizeCap>
        </rollingPolicy>
        <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>
</included>

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/logInfohttp://localhost:7081/logWarnhttp://localhost:7081/logError,分別記錄INFO、WARN、ERRER級別的日誌。

1540979202660

  INFO日誌

1540979424835

  WARN日誌

1540979390962

  ERRER日誌

1540979340871

  可見,經過定義多個Appender,結合filter實現了不一樣級別的日誌輸出到不一樣文件中。

  項目源碼地址:LevelConfig

相關文章
相關標籤/搜索