最全的Logback快速實踐

木棉花開_發表於2019-02-12

簡介

logback是當下最受歡迎的log記錄工具,高效能,功能全,文件全,同時作者也log4j的系列的開發者, 本文從logback常用的元件和功能點進行介紹,並提供了簡單的例子參考,logback官網


java中如何使用logback

pom.xml中引入關鍵的兩個包

 <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>test</scope>
        </dependency>
複製程式碼

然後在resources目錄下建立一個logback.xml就可以了,請參考全量的可用配置檔案這個章節


日誌級別

推薦使用以下幾種,級別從高到低排列

Level 描述
ERROR 錯誤事件可能仍然允許應用程式繼續執行
WARN 指定具有潛在危害的情況
INFO 指定能夠突出在粗粒度級別的應用程式執行情況的資訊的訊息
DEBUG 指定細粒度資訊事件是最有用的應用程式除錯

Appender級別

What is an Appender?

Appender class dependency

appender

ConsoleAppender (將日誌輸出到控制檯)

將日誌資訊列印在控制檯中

配置 型別 描述
encoder Encoder 日誌輸出格式
target String 日誌輸出目標,可以是System.out或者System.err,預設是System.out
withJansi boolean 預設是false,這個使用不到,好像是開啟後輸出的ANSI會有顏色,具體看官網介紹

sample:

<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>
複製程式碼

FileAppender(將日誌輸出到檔案中)

FileAppender OutputStreamAppender的子類,將日誌輸出到指定檔案中。如果檔案已經存在,根據配置屬性來判斷在末尾追加或者重新生成檔案

配置 型別 描述
append boolean 預設為true,會將日誌追加到現有檔案末尾
encoder Encoder 日誌輸出格式
file String 檔名,可以帶路徑,如不過檔案或目錄不存在則會建立,例如: logs/info.log,該屬性沒有預設值
immediateFlush boolean 一旦有日誌產生立即重新整理到檔案,通過情況下把它設為false,以提高效能,因為會頻繁的flush buffer;

sample:

<configuration>
  <!-- 使用時間戳作為檔名 -->
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>testFile-${bySecond}.log</file>
    <append>true</append>
    <!-- set immediateFlush to false for much higher logging throughput -->
    <immediateFlush>true</immediateFlush>
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>
複製程式碼

RollingFileAppender(滾動式輸出)

RollingFileAppender繼承於FileAppender, 按照一些特定策略生成滾動檔案,例如與TimeBasedRollingPolicy策略搭配時,當檔案到達指定時間,會重新生成一個新的檔案,關於策略,後面章節會有具體詳細介紹。

配置 型別 描述
append boolean 看FileAppender配置
encoder Encoder 看FileAppender配置
file String 看FileAppender配置
rollingPolicy RollingPolicy 日誌滾動策略:配置這個選項會讓日誌檔案按照指定策略進行滾動
triggeringPolicy TriggeringPolicy 觸發滾動策略:通常搭配rollingPolicy一起使用,用於設定滾動的觸發條件

sample:

<appender name="errorAppender" class="ch.qos.logback.core.RollingFileAppender">
    <file>logs/error.log</file>
    <!-- 設定滾動策略 TimeBasedRollingPolicy 按日期滾動 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--設定日誌命名模式-->
        <fileNamePattern>errorFile.%d{yyyy-MM-dd}.log</fileNamePattern>
        <!--最多保留30天log-->
        <maxHistory>30</maxHistory>
    </rollingPolicy>
    <!-- 超過150MB時,立即觸發滾動策略,生成新的檔案 -->
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <maxFileSize>150</maxFileSize>
    </triggeringPolicy>
    <encoder>
        <pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
    </encoder>
</appender>
複製程式碼

日誌檔案策略 *Policy(常用)

TimeBasedRollingPolicy(按日期滾動策略)

TimeBasedRollingPolicy 可能是logback最受歡迎的滾動策略,基於時間的滾動,可以是一天也可以是一個月,這個較為常用,通常我們可以設定一天生成一個新的檔案,很好歸納,統計

配置 型別 描述
fileNamePattern String log檔案命名規則,通常使用%d來按天或按月輸出,例如errorFile.%d{yyyy-MM-dd}.log,生成出來的檔案類似於errorFile.2018-10-09.log,帶上日期後這樣每天生成的檔案就不會名字重複了,這個還支援選擇時區,例如%d{yyyy-MM-dd,UTC}
maxHistory int 日誌保留天數,超過該天數的歷史日誌檔案將會被logback非同步刪除
totalSizeCap int 歸檔檔案的總大小,優先應用maxHistory的策略。
cleanHistoryOnStart boolean 預設為false,觸發歸檔檔案立即刪除的動作。

滾動輸出支援自動壓縮,檔名以.gz或者.zip結尾即可,例如:/wombat/foo.%d.gz

sample:

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logFile.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- daily rollover -->
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>

      <!-- keep 30 days' worth of history capped at 3GB total size -->
      <maxHistory>30</maxHistory>
      <totalSizeCap>3GB</totalSizeCap>

    </rollingPolicy>

    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>
複製程式碼

SizeAndTimeBasedRollingPolicy(按大小和時間滾動策略)

這個應該是最常用的吧,按照指定時間和檔案大小的策略來滾動日誌。廢話不多說看下面的例子

<configuration>
  <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>mylog.txt</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <!-- rollover daily -->
      <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
       <!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
       <maxFileSize>100MB</maxFileSize>    
       <maxHistory>60</maxHistory>
       <totalSizeCap>20GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>


  <root level="DEBUG">
    <appender-ref ref="ROLLING" />
  </root>

</configuration>
複製程式碼

請注意除“%d”之外的“%i”轉換標記。 %i%d令牌都是強制性的。 每當當前日誌檔案在當前時間段結束之前達到maxFileSize時,它將以增加的索引存檔,從0開始


FixedWindowRollingPolicy(以固定的演算法策略生成滾動檔案 不常用)

這個策略不常用,我們就不多bb了,屬性和其他滾動策略是一樣的,通常檔案命名規範是這樣的:tests.%i.log,當到達條件觸發滾動時會生成檔案test1.log,test2.log,test3.log ...


SizeBasedTriggeringPolicy(根據大小觸發滾動的策略)

這個標籤裡的配置,用來觸發滾動時間的,例如檔案大小到了指定值,就是觸發滾動

sample:

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>test.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>test.%i.log.zip</fileNamePattern>
      <minIndex>1</minIndex>
      <maxIndex>3</maxIndex>
    </rollingPolicy>

    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <maxFileSize>5MB</maxFileSize>
    </triggeringPolicy>
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>
複製程式碼

fileNamePatten的一些規則(例子,按年,月,日,天,時,分,秒滾動)

例子 描述
/wombat/foo.%d 按天滾動,格式 年-月-日,都生成在一個資料夾中
/wombat/%d{yyyy/MM}/foo.txt 按月滾動,每個月生成一個相同的檔案,在不同的月份資料夾中,例如first: /wombat/2018/09/foo.txt,next: /wombat/2018/10/foo.txt
/wombat/foo.%d{yyyy-ww}.log 每週生成一次,每週的第一天開始重新生成
/wombat/foo%d{yyyy-MM-dd_HH}.log 每小時生成一次
/wombat/foo%d{yyyy-MM-dd_HH-mm}.log 每分鐘生成一次
/wombat/foo%d{yyyy-MM-dd_HH-mm, UTC}.log 按指定時區每分鐘生成一次
/foo/%d{yyyy-MM,aux}/%d.log 每天生成一次,按照年和月區分,例如,/foo/2018-09/中存在一個月的log,log名是每天的日期

pattern配置(日誌輸出格式化)

例子

下面會介紹一些常用的配置規則。

<encoder>
    <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
複製程式碼
  • %-4relative: 將輸出日誌記錄的時間,進行左對齊,寬度為4.
  • %thread: 將輸出記錄日誌的執行緒號
  • %-5level: 輸出5個日誌級別,進行左對齊。
  • %logger{35}: 輸出日誌記錄的logger名通常為類名,長度為35。
  • %msg%n: 輸出應用程式提供的資訊,並換行。

注意:所有關鍵字在使用的時候必須帶上%,如上,-為對其標誌

pattern表格

關鍵字 描述
c{length}
lo{length}
輸出logger所屬的類目,通常就是所在類的全名,引數為logger名保留長度,預設不填為全名.
%logger com.util.StringUtils com.util.StringUtils
%logger{0} com.util.StringUtils StringUtils
%logger{10} com.util.StringUtils c.u.StringUtils
C{length}
class{length}
和上面用法類似,輸出呼叫者的全名,效能較差,不推薦配置。
contextName
cn|
輸出上下文名稱
d{pattern}
date{pattern}
輸出日誌的列印時間,和java中的日期格式化類似
%d 2019-02-12 18:00:00,000
%date 2019-02-12 18:00:00,000
%date{ISO8601} 2019-02-12 18:00:00,000
%date{HH:mm:ss,SSSS} 18:00:00,000
%date{yyyy-MM-dd HH:mm:ss,SSSS} 2019-02-12 18:00:00,000
caller{depth} 輸出日誌呼叫者的呼叫棧深度資訊,值越大,輸出的棧資訊越多
%caller{2} [main]-[INFO]: log test
Caller+0 at com.util.StringUtil.subString(StringUtil.java :22)
Caller+1 at com.util.Main.exec(Main.java :17)
L
line
輸出日誌事件的發生位置,包括類目名、發生的執行緒,以及在程式碼中的行數。如不考慮效能問題,可以使用
m
msg
message
應用程式提供的資訊
M
method
輸出執行日誌記錄的方法名效能較差,如不考慮效能問題,可以使用
n 輸出一個回車換行符,Windows平臺為“/r/n”,Unix平臺為“/n”
p
le
level
輸出日誌級別,即DEBUG,INFO,WARN,ERROR,FATAL
t
thread
輸出列印日誌的執行緒名
replace(msg){r,t} msg為日誌內容,r是正規表示式,將msg中符合r的內容替換成t。
例如:%replace(%msg){'\s',""}
r
relative
輸出自應用啟動到輸出該log資訊耗費的毫秒數

配置:

<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日期 [執行緒] [class類]-[日誌級別] log內容 回車符號 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n</pattern>
        </encoder>

    </appender>

    <!-- 輸出INFO及以上的日誌 -->
    <root level="INFO">
        <!-- 讓自定義的appender生效 -->
        <appender-ref ref="STDOUT"/>
    </root>

</configuration>

複製程式碼

控制檯輸出:

2018-10-09 14:27:55 [main] [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping]-[INFO] Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-10-09 14:27:55 [main] [org.springframework.jmx.export.annotation.AnnotationMBeanExporter]-[INFO] Registering beans for JMX exposure on startup
2018-10-09 14:27:55 [main] [org.apache.coyote.http11.Http11NioProtocol]-[INFO] Starting ProtocolHandler ["http-nio-6677"]
2018-10-09 14:27:55 [main] [org.apache.tomcat.util.net.NioSelectorPool]-[INFO] Using a shared selector for servlet write/read
2018-10-09 14:27:55 [main] [org.springframework.boot.web.embedded.tomcat.TomcatWebServer]-[INFO] Tomcat started on port(s): 6677 (http) with context path ''
2018-10-09 14:27:55 [main] [com.xj.plugins.Springboot2AnalyzeApplication]-[INFO] Started Springboot2AnalyzeApplication in 2.014 seconds (JVM running for 3.949)

複製程式碼

控制檯輸出的log配置顏色

格式 描述
%black 黑色
%red 紅色
%green 綠色
%yellow 黃色
%blue 藍色
%magenta 品紅
%cyan 青色
%white 白色
%gray 灰色
%highlight 高亮色
%bold 更鮮豔色顏色,強化以上所有的顏色,例如%boldRed,%boldBlack

例子:

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日期 [執行緒] [class類]-[日誌級別] log內容 回車符號 -->
            <pattern>%blue(%d{yyyy-MM-dd HH:mm:ss,SSS}) [%cyan(%t)] [%yellow(%c)]-[%highlight(%p)] %m%n</pattern>&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;
        </encoder>
    </appender>

    <!-- 輸出INFO及以上的日誌 -->
    <root level="INFO">
        <!-- 讓自定義的appender生效 -->
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>
複製程式碼

配置過後的控制檯輸出

增加色彩輸出


日誌定向輸出

logback.xml中如何需要將某中日誌輸出到檔案中可以使用過濾器,類似於以下這個例子

xml配置過濾器,例如將error日誌輸出到error.log中

    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
           <encoder>
               <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%c]-[%p] %m%n</pattern>
           </encoder>

           <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
               <!-- rollover daily -->
               <fileNamePattern>${LOG_HOME}/error-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
               <!-- 檔案最大30MB,保留60天,總大小20GB -->
               <maxFileSize>30MB</maxFileSize>
               <maxHistory>60</maxHistory>
               <totalSizeCap>20GB</totalSizeCap>
           </rollingPolicy>

           <!-- 過濾器,只寫入error級別log -->
           <filter class="ch.qos.logback.classic.filter.LevelFilter">
               <level>ERROR</level>
               <onMatch>ACCEPT</onMatch>
               <onMismatch>DENY</onMismatch>
           </filter>

       </appender>
複製程式碼

如果有需要特殊log需要定向輸出的話可以重寫 Filter方法

public class MyLogFilter extends Filter<ILoggingEvent> {
       @Override

       public FilterReply decide(ILoggingEvent event) {
           
           if(event.getMessage() != null
                   && (event.getMessage().startsWith("test")
                   || event.getMessage().startsWith("demo"))) {
               return FilterReply.ACCEPT;
           } else {
               return FilterReply.DENY;
           }
       }
   }
複製程式碼

然後將filter加入到你的appender中

<!-- 過濾器,寫入test和demo開頭的日誌 -->
<filter class="xx.xxx.xxxx.MyLogFilter" />
複製程式碼

關閉類中某個級別的log輸出

在logback.xml中加入以下配置

OFF表示全部關閉,可以配置指定級別如INFO,DEBUG...

<logger name="xx.xx.class" level="OFF" />
複製程式碼

logback.xml讀取環境變數

logback.xml支援兩種讀取方式,從系統環境中讀取,從spring配置檔案中讀取

讀取系統環境變數 通過${envName}方式獲取

<!-- 從系統環境變數讀取日誌輸出目錄 -->
<property name="LOG_HOME" value="${log.dir}"/>
複製程式碼

讀取spring配置檔案的方式

<!-- 從context中讀取所以不需要使用${}獲取 -->
<springProperty scope="context" name="LOG_HOME" source="logback.dir"/>
複製程式碼

預設值設定

如果在環境變數中沒有取到LOG_HOME 的值,則會使logs作為預設值,和Shell語法中設定預設值類似

<file>${LOG_HOME:-logs}/test/test-info.log</file>
複製程式碼

-

全量的可用配置檔案

以下配置會生成三個日誌檔案,具體的策略是:每天會生成一個新的檔案,當天日誌檔案達到指定大小會自動壓縮,並且生成新的檔案進行記錄。

  • main.log(只記錄info級別及以上的日誌輸出)
  • warn.log(只記錄warn級別的日誌輸出)
  • error.log(只記錄error級別的日誌輸出)
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!-- 從spring中獲取配置,如獲取不到會使用預設值 -->
    <springProperty scope="context" name="LOG_HOME" source="logging.path"/>
    <springProperty scope="context" name="LOG_LEVEL" source="logging.output.level"/>
    <springProperty scope="context" name="LOG_MAX_SIZE" source="logging.file.max-size"/>
    <springProperty scope="context" name="LOG_TOTAL_SIZE_CAP" source="logging.file.total-size-cap"/>
    <springProperty scope="context" name="LOG_MAX_HISTORY" source="logging.file.max-history"/>
    <!-- 輸出樣式 -->
    <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%logger{10}]-[%p] %m%n"/>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%blue(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%cyan(%t)] [%yellow(%logger{10})]-[%highlight(%p)] %m%n</pattern>
        </encoder>
    </appender>

    <appender name="Main-Log" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME:-logs}/logback/main.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME:-logs}/logback/main-%d{yyyy-MM-dd}_%i.log.zip</FileNamePattern>
            <MaxHistory>${LOG_MAX_HISTORY:-30}</MaxHistory>
            <MaxFileSize>${LOG_MAX_SIZE:-10MB}</MaxFileSize>
            <totalSizeCap>${LOG_TOTAL_SIZE_CAP:-10GB}</totalSizeCap>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>


    <appender name="Error-Log" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME:-logs}/logback/error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME:-logs}/logback/error-%d{yyyy-MM-dd}_%i.log.zip</FileNamePattern>
            <MaxHistory>${LOG_MAX_HISTORY:-30}</MaxHistory>
            <MaxFileSize>${LOG_MAX_SIZE:-10MB}</MaxFileSize>
            <totalSizeCap>${LOG_TOTAL_SIZE_CAP:-10GB}</totalSizeCap>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>

        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="Warn-Log" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME:-logs}/logback/warn.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME:-logs}/logback/warn-%d{yyyy-MM-dd}_%i.log.zip</FileNamePattern>
            <MaxHistory>${LOG_MAX_HISTORY:-30}</MaxHistory>
            <MaxFileSize>${LOG_MAX_SIZE:-10MB}</MaxFileSize>
            <totalSizeCap>${LOG_TOTAL_SIZE_CAP:-10GB}</totalSizeCap>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
        <!-- log filter -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    
    <!-- 關閉類中某個級別的輸出 OFF全部關閉 , INFO,DEBUG ...
    <logger name="x.x.Constants">
        <level value="OFF"/>
    </logger> 
    -->

    <!-- log output level -->
    <root level="${LOG_LEVEL:-INFO}">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="Main-Log"/>
        <appender-ref ref="Warn-Log"/>
        <appender-ref ref="Error-Log"/>
    </root>

</configuration>
複製程式碼

相關文章