Spring Boot 整合 Logback 日誌

luis林威發表於2023-03-01

Spring Boot 支援 Java Util Logging,Log4J,Log4J2 和 Logback 等日誌框架,預設採用 Logback 日誌。

在實際 Spring Boot 專案中使用 Spring Boot 預設日誌配置是不能夠滿足實際生產及開發需求的,需要選定適合的日誌輸出框架,靈活調整日誌輸出級別、日誌輸出格式等。

此處主要講述如何進行 Spring Boot 專案的 Logback 預設日誌詳細配置。

強烈建議使用預設的 Logback 日誌配置,因為它比 log4j 效能好很多!

  1. Spring Boot 自動整合了 logback 和 log4j2,所以無需引入相關依賴。

  2. 在 resources 目錄下,新建日誌配置檔案 logback-spring.xml

    首先,官方推薦使用的 xml 名字的格式為:logback-spring.xml 而不是 logback.xml,至於為什麼,因為帶 spring 字尾的可以使用 <springProfile> 這個標籤(PS:這個標籤用於切換“開發環境”和“生產環境”)。

    下面配置可看情況自行修改!

    本文配置參考:傳送門

    <?xml version="1.0" encoding="UTF-8" ?>
    <!--
        scan:當此屬性設定為true時,配置檔案如果發生改變,將會被重新載入,預設值為true
        scanPeriod:設定監測配置檔案是否有修改的時間間隔,如果沒有給出時間單位預設單位是毫秒,當scan為true時此屬性生效,預設時間間隔為1分鐘
        debug:當此屬性設定為true時,將列印出logback內部日誌資訊,實時檢視logback執行狀態,預設值為false
     -->
    <configuration scan="true" scanPeriod="2 seconds">
        <!--
         	定義滾動記錄檔案appender 作用:滾動記錄檔案,先將日誌記錄到指定檔案,當符合某個條件時,將日誌記錄到其他檔案
            RollingFileAppender class="ch.qos.logback.core.rolling.RollingFileAppender"
           	 引數:
                <append>:如果是true日誌被追加到檔案結尾,如果是false清空現存檔案,預設是true
                <file>:被寫入的檔名,可以是相對目錄也可以是絕對目錄,如果上級目錄不存在會自動建立,沒有預設值
                <rollingPolicy>:當發生滾動時,決定RollingFileAppender的行為,涉及檔案移動和重新命名
                <triggeringPolicy>:告知RollingFileAppender合適啟用滾動
                <prudent>:當為true時不支援FixedWindowRollingPolicy支援TimeBasedRollingPolicy,但是有兩個限制:1不支援也不允許檔案壓縮,2不能設定file屬性必須留空
        -->
        <appender name="fileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 如果是true,日誌被追加到檔案結尾,如果是false,清空現存檔案.預設是true -->
            <prudent>true</prudent>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- 每天滾動一次的日誌 只保留30天內的日誌檔案 -->
                <fileNamePattern>logs/%d{yyyy-MM-dd}/springboot_%i.log</fileNamePattern>
                <maxHistory>30</maxHistory>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>10MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                <!-- 對日誌進行格式化 -->
                <pattern>%date %level [%thread] %logger{10}.%class{0}#%method[%file:%line] %n%msg%n</pattern>
                <charset>utf-8</charset>
            </encoder>
        </appender>
    
        <appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <prudent>true</prudent>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>logs/%d{yyyy-MM-dd}/springboot-error_%i.log</fileNamePattern>
                <maxHistory>30</maxHistory>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>10MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <encoder>
                <pattern>%date %level [%thread] %logger{10}.%class{0}#%method[%file:%line] %n%msg%n</pattern>
                <charset>utf-8</charset>
            </encoder>
            <!--
                 配置日誌級別過濾器 作用:根據日誌級別進行過濾,如果日誌級別等於配置級別過濾器會根據onMath和onMismatch接收或拒絕日誌
                 引數:
                 <level>:設定過濾級別
                 <onMatch>:用於配置符合過濾條件的操作
                 <onMismatch>:用於配置不符合過濾條件的操作
                                           此處配置為只接收ERROR日誌級別資訊
             -->
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>ERROR</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
        </appender>
    
        <!-- 定義控制檯appender 作用:把日誌輸出到控制檯 class="ch.qos.logback.core.ConsoleAppender" -->
        <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%date %level [%thread] %logger{10}.%class{0}#%method[%file:%line] %n%msg%n</pattern>
            </layout>
        </appender>
    
        <!-- 將root的列印級別設定為"error",指定了名字為"console","fileAppender","errorAppender"的appender -->
        <root level="error">
            <appender-ref ref="console"/>
            <appender-ref ref="fileAppender"/>
            <appender-ref ref="errorAppender"/>
        </root>
    
        <!--
            logger用來設定某一個包的日誌列印級別
            <loger> 僅有一個name屬性,一個可選的level和一個可選的addtivity屬性
                    name:用來指定受此loger約束的某一個包或者具體的某一個類
                    level:用來設定列印級別,大小寫無關:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
                    addtivity:是否向上級loger傳遞列印資訊。預設是true,會將資訊輸入到root配置指定的地方,可以包含多個appender-ref,標識這個appender會新增到這個logger
        -->
        <logger name="com.xcbeyond.springboot" level="debug"/>
    </configuration>
    
  3. 兩種方式使用日誌:

    1. 直接在需要使用日誌列印的類上新增 lombok 的註解 @Slf4j 即可!

      PS:注意需要新增 Lombok 依賴!

      <!-- lombok -->
      <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <optional>true</optional>
      </dependency>
      

      示例:

      @SpringBootTest
      @Slf4j
      class RedisMysqlDemoApplicationTests {
      
          @Test
          void contextLoads() {
      
              // 日誌級別從低到高分為 TRACE < DEBUG < INFO < WARN < ERROR < FATAL
              log.trace("================ trace =================");
              log.debug("================ debug =================");
              log.info("================ info =================");
              log.warn("================ warn =================");
              log.error("================ error =================");
          }
      }
      
    2. 宣告日誌類

      PS:注意 LoggerLoggerFactory 導的哪個包!

      import org.junit.jupiter.api.Test;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      import org.springframework.boot.test.context.SpringBootTest;
      
      @SpringBootTest
      class RedisMysqlDemoApplicationTests {
      
          private static final Logger log = LoggerFactory.getLogger(RedisMysqlDemoApplicationTests.class);
      
          @Test
          void contextLoads() {
      
              // 日誌級別從低到高分為 TRACE < DEBUG < INFO < WARN < ERROR < FATAL
              log.trace("================ trace =================");
              log.debug("================ debug =================");
              log.info("================ info =================");
              log.warn("================ warn =================");
              log.error("================ error =================");
          }
      }
      

相關文章