logback.xml詳解

2022-10-16 15:28:26

介紹

之前博文有專門介紹過基於Log4j Appender 實現巨量資料平臺元件紀錄檔的採集, 本篇主要對java專案中經常會接觸到的logback.xml檔案的設定做一個介紹和總結.

logback.xml 設定

下面是一個logback設定demo, 常用的設定都有, 一一介紹下每個設定的作用.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<property name="LOG_HOME" value="d:/opt/module/logs" />
	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
		    <pattern>%msg%n</pattern>
		</encoder>
	</appender>
	<appender name="rollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
	    <file>${LOG_HOME}/app.log</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
		     <fileNamePattern>${LOG_HOME}/app.%d{yyyy-MM-dd}.log</fileNamePattern>
		</rollingPolicy>
		<encoder>
		    <pattern>%msg%n</pattern>
		</encoder>
	</appender>
	<!-- 將某一個包下紀錄檔單獨列印紀錄檔 -->
	<logger name="com.bigdata.logger.LoggerExample"
	level="INFO" additivity="false">
		<appender-ref ref="rollingFile" />
		<appender-ref ref="console" />
	</logger>
	<root level="error" additivity="false">
	    <appender-ref ref="console" />
	</root>
</configuration>

設定說明:

  • property
    定義屬性,類似全域性變數, 比如上面我們定義的LOG_HOME 紀錄檔寫入路徑檔案路徑, 下面的appender 可以直接參照

  • appender
    追加器,描述如何寫入到檔案中(寫在哪,格式,檔案的切分)
    ConsoleAppender--追加到控制檯
    RollingFileAppender--捲動追加到檔案
    encoder: 對紀錄檔進行格式化。
    rollingPolicy:當發生捲動時,決定RollingFileAppender的行為,涉及檔案移動和重新命名.TimeBasedRollingPolicy 是根據時間制定捲動策略,
    fileNamePattern:檔案輸出格式

  • logger
    控制器,描述如何選擇追加器
    注意:要是單獨為某個類指定的時候,要修改類的全限定名
    appender-ref: 參照前面定義的appender
    level="error": 定義輸出的紀錄檔級別, 低於此紀錄檔級別的紀錄檔不會輸出
    additivity="false": 這個稍微不太好理解, 下面我寫個程式碼, 實操下.

  • 紀錄檔級別
    TRACE->DEBUG ->INFO -> WARN -> ERROR -> FATAL
    從左到右, 由到高

  • root
    根級別紀錄檔

實戰code

專案結構:

maven 設定:

 <dependencies>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.6</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.6</version>
        </dependency>
    </dependencies>

測試程式碼:

public class LoggerExample {
    private static final Logger logger = LoggerFactory.getLogger(LoggerExample.class);
    public static void main(String[] args) {
        logger.info("Example log from {}", LoggerExample.class.getSimpleName());
        logger.error("Error log");
    }
}

直接執行的結果:


console和app.log檔案的結果一樣

修改 additivity="true

<logger name="com.bigdata.logger.LoggerExample" level="INFO" additivity="true">

再次執行結果:

可以看出app.log正常, 但是cosole 上列印了重複的紀錄檔, 說明命中了console appender兩次, log和root 各一次, 但是奇怪的是, 第一條info紀錄檔為什麼會重複, 因為root level="ERROR", 理論上info 紀錄檔級別比ERROR級別要低, 不應該在console裡出現才對.

我們看下logback相關的原始碼是如何處理的.

https://github.dev/qos-ch/logback/blob/master/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java


    /**
     * Invoke all the appenders of this logger.
     * 
     * @param event The event to log
     */
    public void callAppenders(ILoggingEvent event) {
        int writes = 0;
        for (Logger l = this; l != null; l = l.parent) {
            writes += l.appendLoopOnAppenders(event);
            if (!l.additive) {
                break;
            }
        }
        // No appenders in hierarchy
        if (writes == 0) {
            loggerContext.noAppenderDefinedWarning(this);
        }
    }

從程式碼我們可以看出, logback 的整個輸出是從logger子節點開始往上遍歷, 如果additive = false, 就直接break 迴圈直接結束, 如果break = true, 會繼續往上尋找父節點,直到最終 l == null. 同時會記錄writes, writes == 0,認為沒有定義appender輸出源

程式碼沒有關於紀錄檔級別的控制. 所以以後如果只希望列印紀錄檔到子節點的appeder, 父節點的appender忽略, 就設定additivity = false, 預設值為true, 這樣紀錄檔就不會重複了.

總結

主要對logback.xml 常用設定的作用介紹, 通過logback 的相關原始碼對additivity引數有了更深的認識. additivity 預設值為true, 如果不希望在某些場景下列印重複的紀錄檔, 可以設定為false, additivity 設定不受level設定的影響.