[Java/日誌] 日誌框架列印應用程式日誌程式碼的執行情況

千千寰宇發表於2024-10-16

0 引言

  • 我常以為 配置 INFO 日誌級別時, 應用程式程式碼中日誌器(logger) debug 級的日誌程式碼,不會被執行(比如,實驗1中的printTestLog函式)。但今天線上的問題,證實了這個思路是錯的。

1 驗證實驗

  • 版本資訊
  • jdk : 1.8
  • 日誌元件
  • slf4j.version : 1.7.25
  • log4j.version : 2.20.0
<!-- log [start] -->
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>${slf4j.version}</version>
</dependency>
<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-api</artifactId>
	<version>${log4j.version}</version>
</dependency>
<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-core</artifactId>
	<version>${log4j.version}</version>
</dependency>
<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-slf4j-impl</artifactId>
	<version>${log4j.version}</version>
</dependency>
<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-jul</artifactId>
	<!--<version>2.13.3</version>-->
	<version>${log4j.version}</version>
	<scope>compile</scope>
</dependency>
<!-- log [end] -->

實驗1:日誌框架列印應用程式日誌程式碼的執行情況

日誌配置策略: log4j2.properties

  • log4j2.properties
## 日誌的等級(自定義配置項)
##property.log.level=ALL,TRACE,DEBUG,INFO,WARN,ERROR,FATAL,OFF
property.log.level=DEBUG

# ------------------- [1.1] 定義 RootLogger 等 全域性性配置(不可隨意修改) ------------------- #
## rootLogger, 根記錄器,所有記錄器的父輩
## 指定根日誌的級別 | All < Trace < Debug < Info < Warn < Error < Fatal < OFF
rootLogger.level=${log.level}

... //略

應用程式程式碼: LogTest

  • LogTest
package test.java.lang;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class LogTest {
    public static String printTestLog(){
        return "HelloWorld";//關鍵程式碼行
    }

    public static void main(String[] args) {
        log.debug( "log:{}", printTestLog() );
    }
}

實驗結果

  • log.level=INFO
關鍵程式碼行 : 被執行

日誌輸出結果: 空
  • log.level=DEBUG
關鍵程式碼行 : 被執行

日誌輸出結果: 
[20XX/10/16 16:01:28.585] [TID: N/A] [DEBUG] [main] [LogTest.java:12 main] log:HelloWorld

最終結論

  • 無論 應用程式日誌程式碼 logger 使用何種日誌級別列印日誌,程式碼行中的程式均會被執行,只是最終輸出時由日誌框架根據配置logger所屬class的日誌級別決定是否輸出(appender)

  • 解決方法1:應用程式中,如無必要,刪除這類日誌程式碼。

  • 解決方法2:log.isDebugEnabled(...)/isInfoEnabled(...)/isWarnEnabled(...)/isErrorEnabled(...)/...

    public static void main(String[] args) {
        if(log.isDebugEnabled()){//將會根據 使用者所配置的日誌級別(log.level),決定是否執行 IF 內的程式碼
            log.debug( "log:{}", printTestLog() );
        }
    }

X 參考文獻

相關文章