1. 程式人生 > >SpringBoot 非同步輸出 Logback 日誌

SpringBoot 非同步輸出 Logback 日誌

一、介紹

1.1 Logback

  Logback是由log4j創始人設計的另一個開源日誌元件,它分為下面下個模組:

  1. logback-core:其它兩個模組的基礎模組
  2. logback-classic:它是log4j的一個改良版本,同時它完整實現了slf4j API使你可以很方便地更換成其它日誌系統如log4j或JDK14 Logging
  3. logback-access:訪問模組與Servlet容器整合提供通過Http來訪問日誌的功能

1.2 日誌級別

包括:TRACEDEBUGINFOWARNERROR

1.2.1 TRACE

特別詳細的系統執行完成資訊,業務程式碼中,不要使用。(除非有特殊用意,否則請使用DEBUG

級別替代)

1.2.2 DEBUG

  1. 可以填寫所有的想知道的相關資訊(但不代表可以隨便寫,debug資訊要有意義,最好有相關引數);
  2. 生產環境需要關閉DEBUG資訊
  3. 如果在生產情況下需要開啟DEBUG,需要使用開關進行管理,不能一直開啟。

1.2.3 INFO

  • 系統執行資訊

    1. Service方法中對於系統/業務狀態的變更;
    2. 主要邏輯中的分步驟。
  • 外部介面部分

    1. 客戶端請求引數(REST/WS);
    2. 呼叫第三方時的呼叫引數和呼叫結果。
  • 說明

  1. 並不是所有的service都進行出入口打點記錄,單一、簡單service是沒有意義的;
  2. 對於複雜的業務邏輯,需要進行日誌打點,以及埋點記錄,比如電商系統中的下訂單邏輯,以及OrderAction操作(業務狀態變更);
  3. 對於整個系統的提供出的介面(REST/WS),使用INFO記錄入參;
  4. 如果所有的service為SOA架構,那麼可以看成是一個外部介面提供方,那麼必須記錄入參;
  5. 呼叫其他第三方服務時,所有的出參和入參是必須要記錄的(因為你很難追溯第三方模組發生的問題)。

1.2.4 WARN

  • 不應該出現但是不影響程式、當前請求正常執行的異常情況:

    1. 有容錯機制的時候出現的錯誤情況;
    2. 找不到配置檔案,但是系統能自動建立配置檔案;
  • 即將接近臨界值的時候,例如:快取池佔用達到警告線;
  • 業務異常的記錄,比如:當介面丟擲業務異常時,應該記錄此異常。

1.2.5 ERROR

影響到程式正常執行、當前請求正常執行的異常情況:

  1. 開啟配置檔案失敗;
  2. 所有第三方對接的異常(包括第三方返回錯誤碼);
  3. 所有影響功能使用的異常,包括:SQLException和除了業務異常之外的所有異常(RuntimeExceptionException)。

不應該出現的情況:
如果進行了丟擲異常操作,請不要記錄ERROR日誌,由最終處理方進行處理:

反例(不要這麼做):

try{
    ....
}catch(Exception ex){
  String errorMessage=String.format("Error while reading information of user [%s]",userName);
  logger.error(errorMessage,ex);
  throw new UserServiceException(errorMessage,ex);
}

1.3 SpringBoot 中 logback

  1. SpringBoot工程自帶logbackslf4j的依賴,所以重點放在編寫配置檔案上,需要引入什麼依賴,日誌依賴衝突統統都不需要我們管了;
  2. logback框架會預設載入classpath下命名為logback-springlogback的配置檔案。
  3. 將所有日誌都儲存在一個檔案中檔案大小也隨著應用的執行越來越大並且不好排查問題,正確的做法應該是將ERROR日誌和其他日誌分開,並且不同級別的日誌根據時間段進行記錄儲存。

二、logback 配置

2.1 配置檔案logback-spring.xml示例

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <!-- 屬性檔案:在配置檔案中找到對應的配置項 -->
    <springProperty scope="context" name="logPath" source="logging.path"/>

    <!-- 輸出到控制檯 -->
    <appender name="CONSOLE-LOG" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>[%d{yyyy-MM-dd' 'HH:mm:ss.sss}] [%C] [%t] [%L] [%-5p] %m%n</pattern>
        </layout>
    </appender>

    <!-- 獲取比info級別高(包括info級別)但除error級別的日誌 -->
    <appender name="INFO-LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 指定過濾策略 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
        <encoder>
            <!-- 指定日誌輸出格式 -->
            <pattern>[%d{yyyy-MM-dd' 'HH:mm:ss.sss}] [%C] [%t] [%L] [%-5p] %m%n</pattern>
        </encoder>

        <!-- 指定收集策略:滾動策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 指定生成日誌儲存地址 -->
            <fileNamePattern>${logPath}/info.%d.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>

    <appender name="ERROR-LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 指定過濾策略 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <!-- 指定日誌輸出格式 -->
            <pattern>[%d{yyyy-MM-dd' 'HH:mm:ss.sss}] [%C] [%t] [%L] [%-5p] %m%n</pattern>
        </encoder>
        <!-- 指定收集策略:滾動策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--指定生成日誌儲存地址 -->
            <fileNamePattern>${logPath}/error.%d.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>

    <!-- 非同步輸出 -->
    <appender name="ASYNC-INFO" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丟失日誌.預設的,如果佇列的80%已滿,則會丟棄TRACT、DEBUG、INFO級別的日誌 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改預設的佇列的深度,該值會影響效能.預設值為256 -->
        <queueSize>256</queueSize>
        <!-- 新增附加的appender,最多隻能新增一個 -->
        <appender-ref ref="INFO-LOG"/>
    </appender>

    <appender name="ASYNC-ERROR" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丟失日誌.預設的,如果佇列的80%已滿,則會丟棄TRACT、DEBUG、INFO級別的日誌 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改預設的佇列的深度,該值會影響效能.預設值為256 -->
        <queueSize>256</queueSize>
        <!-- 新增附加的appender,最多隻能新增一個 -->
        <appender-ref ref="ERROR-LOG"/>
    </appender>

    <!-- 指定最基礎的日誌輸出級別 -->
    <root level="info">
        <appender-ref ref="CONSOLE-LOG" />
        <appender-ref ref="INFO-LOG" />
        <appender-ref ref="ERROR-LOG" />
    </root>

</configuration>

專案配置檔案中配置日誌輸出地址

logging:
  path: ./logs
    

2.2 標籤說明

  • <root>標籤:指定最基礎的日誌輸出級別;
    • <appender-ref>標籤,新增append
  • <appender>標籤:指定日誌的收集策略
    1. name屬性指定appender命名
    2. class屬性指定輸出策略,通常有兩種,控制檯輸出和檔案輸出,檔案輸出就是將日誌進行一個持久化。ConsoleAppender將日誌輸出到控制檯。
  • <filter>標籤:指定過濾策略
    • <level>:指定過濾的型別。
  • <encoder>標籤:使用該標籤下的<pattern>標籤指定日誌輸出格式。

  • <rollingPolicy>標籤:指定收集策略,比如基於時間進行收集

三、 原始碼

Github 示例源