Spring Boot之整合logback日志

前言

本文使用的項目代碼,是基于之前文章使用的Spring Boot項目:

日志系統分為兩部分,一部分是日志抽象層,一部分是日志實現層。

常見日志抽象層:
  • JCL
  • SLF4J
  • JBoss-Logging
常見日志實現層有:
  • logback
  • log4j
  • log4j2
  • JUL

每種Logger都可以通過配置使用控制臺或者文件輸出日志內容,logback是log4j框架的作者開發的新一代日志框架,它效率更高、能夠適應諸多的運行環境,同時天然支持slf4j,而Spring Boot 默認使用slf4j + logback作為日志系統,廣泛應用于Spring Boot項目。今天我們就一起來學學如何使用slf4j + logback日志系統。

整合logback日志步驟

1. 添加依賴?
2. 創建日志配置文件;
3. 編寫日志配置文件;
4. 日志配置文件介紹;
5. 日志實例;
6. 日志效果。

1. 添加依賴?

如果要使用logback,原則上是需要添加dependency依賴的,但也如前言所說,logback是Spring Boot 默認的日志實現層,因此只要項目中只要有使用了spring-boot-starter或者spring-boot-starter-web依賴,默認已經包含logback的相關依賴:

#無需再次引用以下logback依賴:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
</dependency>

2. 創建日志配置文件;

在項目src/main/resources底下創建日志配置文件,如:logback-spring.xml;

注意:能夠被Spring Boot自動識別的logback日志配置文件名:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy。

如果換成其他名字,如logging-config.xml,那么需要在application.properties文件內額外指定文件名,如:

logging.config=classpath:logging-config.xml
官方推薦優先使用帶有“-spring”文件名的文件作為日志配置文件,這樣Spring Boot會為它添加一些Spring Boot特有的配置項。
logback日志配置文件

3. 編寫日志配置文件;

<?xml version="1.0" encoding="UTF-8"?>

<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <contextName>logback</contextName>
    <!-- 定義日志的根目錄 -->
    <property name="LOG_PATH" value="logs"/>
    <property name="LOG_ARCHIVE" value="${LOG_PATH}/archive"/>

    <!--輸出到控制臺,即:ConsoleAppender-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <withJansi>true</withJansi>
        <encoder>
            <!--格式化輸出:
            %d:表示日期
            %thread:表示線程名
            %-5level:級別從左顯示5個字符寬度
            %msg:日志消息
            %n:是換行符-->
            <pattern>%red([%d{yyyy-MM-dd HH:mm:ss}]) %green([ %thread ]) %highlight([ %-5level ]) %boldMagenta([ %logger ]) - %cyan(%msg%n)
            </pattern>
            <charset>GBK</charset>
        </encoder>
        <!--日志過濾器,如配置則只有被配置的類型才會被記錄下來-->
        <!--<filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>-->
    </appender>

    <!--輸出到文件,即:RollingFileAppender-->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>${LOG_PATH}/current.log</File>
        <!--TimeBasedRollingPolicy: 最常用的滾動策略,它根據時間來制定滾動策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_ARCHIVE}/app.%d.%i.log.gz</fileNamePattern>
            <maxHistory>30</maxHistory>
            <totalSizeCap>20GB</totalSizeCap>
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!--文件達到最大10MB時會被壓縮和切割-->
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>[%d{yyyy-MM-dd HH:mm:ss}] [ %thread ] [ %-5level ] [ %logger ] - %msg%n</pattern>
            <charset>GBK</charset>M
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="console"/>
        <appender-ref ref="file"/>
    </root>

    <logger name="com.mycompany.sample.service.LeadService" level="warn">
        <appender-ref ref="file"/>
    </logger>
</configuration>

4. 日志配置文件介紹;

1. <property>節點:

用于定義變量,方便使用。有兩個屬性:name,value。<property>有兩個屬性:name、value,定義變量后,可以使用${}來使用變量,如:

  • 聲明變量:
<property name="LOG_PATH" value="logs"/>
<property name="LOG_ARCHIVE" value="${LOG_PATH}/archive"/>
  • 使用變量:
<File>${LOG_PATH}/current.log</File>
...
<fileNamePattern>${LOG_ARCHIVE}/app.%d.%i.log.gz</fileNamePattern>

2. <appender>節點:

用來格式化日志輸出的節點,<appender>有兩個屬性: name、class,name用于給該 appender 命名,class用于指定輸出策略,通常有兩種:

  • 控制臺輸出:
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
...
</appender>
  • 文件輸出:
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
...
</appender>

3. <filter>子節點:

<filter>日志過濾器或叫過濾策略,在此之前,我們需要先了解一些基礎知識:
過濾器的返回值只能是ACCEPT、DENY和NEUTRAL的其中一個:

  • 如果返回DENY,那么記錄事件立即被拋棄,不再經過剩余過濾器;
  • 如果返回NEUTRAL,那么有序列表里的下一個過濾器會接著處理記錄事件,下一個過濾器會繼續執行過濾,如無其他過濾器,則記錄日志;
  • 如果返回ACCEPT,那么記錄事件被立即處理,不再經過剩余過濾器。

日志級別由低到高: trace < debug < info < warm < error

常見過濾策略有:

  • ThresholdFilter: 臨界值過濾器。

過濾掉低于指定臨界值的日志,當日志級別等于或高于臨界值時,過濾器返回NEUTRAL;當日志級別低于臨界值時,日志會被拒絕,即不記錄。
例如,過濾掉所有低于INFO級別的日志:

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
    <level>INFO</level>
</filter>
  • LevelFilter:級別過濾器。

根據日志級別進行過濾。如果日志級別等于配置級別,過濾器會根據onMath 和 onMismatch接收或拒絕日志。
例如,當且僅當日志級別為ERROR時記錄日志,否則不記錄:

<filter class="ch.qos.logback.classic.filter.LevelFilter">
    <level>ERROR</level>
    <onMatch>ACCEPT</onMatch>
    <onMismatch>DENY</onMismatch>
</filter>
  • EvaluatorFilter:求值過濾器。

求值過濾器,評估、鑒別日志是否符合指定條件。需要額外的兩個JAR包,commons-compiler.jar和janino.jar,我也沒有嘗試,此處不做介紹。

4. <encoder>子節點:

用于設置日志格式化策略、字體等。

5. <rollingPolicy>子節點:

用于設置滾動策略,所謂的滾動,即自動停止在當前日志文件中打印日志,同時自動啟用新的日志文件進行記錄,我們可以設置一定的策略,使得這樣的過程在滿足該策略條件時,自動發生滾動操作。
最常用的滾動策略是TimeBasedRollingPolicy,它根據時間來制定滾動策略,如:

# 日志最多保留30天,且總保存量為20GB;
# 當文件達到10MB時,會進行壓縮和切割滾;
# 舊log以${log.path}/app.%d.%i.log.gz文件路徑滾動,如:logs/app.2020-08-10.0.log.gz,app.2020-08-10.1.log.gz;
# 新生成的日志文件一直還是logs/current.log。

<File>${LOG_PATH}/current.log</File>
<!--TimeBasedRollingPolicy: 最常用的滾動策略,它根據時間來制定滾動策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">            <fileNamePattern>${LOG_ARCHIVE}/app.%d.%i.log.gz</fileNamePattern>
    <maxHistory>30</maxHistory>
    <totalSizeCap>20GB</totalSizeCap>
    <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
        <!--文件達到最大10MB時會被壓縮和切割-->
        <maxFileSize>10MB</maxFileSize>
    </timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>

滾動實例如:

滾動實例

6. <root>節點:

root節點是必選節點,用來指定最基礎的日志輸出級別,如:

#低于warn(大小寫均可)級別的日志,將不被記錄。
<root level="warn">
    <appender-ref ref="console"/>
    <appender-ref ref="file"/>
</root>

7. <logger>節點:

logger節點用于單獨對某個類進行日志策略定制,如:

#對于com.mycompany.sample.service.LeadService類,最低紀錄日志界別為warn,記錄類型為文件型,低于warn級別的日志將不被記錄。
<logger name="com.mycompany.sample.service.LeadService" level="warn">
    <appender-ref ref="file"/>
</logger>

5. 日志實例;

  • 實例1:
package com.mycompany.sample;

import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * @author : dylanz
 * @since : 07/07/2020
 **/
@SpringBootApplication
@EnableSwagger2
@MapperScan(basePackages = "com.mycompany.sample.dao")
public class App {
    private static Logger logger = LoggerFactory.getLogger(App.class);

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
        logger.trace("This is trace logger...");
        logger.debug("This is debug logger...");
        logger.info("This is info logger...");
        logger.warn("This is warn logger...");
        logger.error("This is error logger...");
    }
}
//關鍵一行代碼:
//private static Logger logger = LoggerFactory.getLogger(App.class);
//getLogger()方法內要使用該類類名;
  • 實例2:
package com.mycompany.sample.service;

import com.mycompany.sample.dao.LeadDAO;
import com.mycompany.sample.domain.Lead;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author : dylanz
 * @since : 07/07/2020
 **/
@Service
public class LeadService {
    private static Logger logger = LoggerFactory.getLogger(LeadService.class);

    @Autowired
    private LeadDAO leadDAO;

    public Lead getLeadByLeadId(Long leadId) {
        logger.trace("This is trace logger in LeadService...");
        logger.debug("This is debug logger in LeadService...");
        logger.info("This is info logger in LeadService...");
        logger.warn("This is warn logger in LeadService...");
        logger.error("This is error logger in LeadService...");
        return leadDAO.getLeadByLeadId(leadId);
    }
}

6. 日志效果;

  • console日志;

  • file日志;

日志

碼字不容易,點贊需積極

謝謝!!!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。