簡體   English   中英

Log4j Commons Logging Bridge 被忽略

[英]Log4j Commons Logging Bridge ignored

我們的 Web 應用程序在 tomcat 9 容器中運行,並使用Log4j 2.13.3 作為日志系統。

Web 應用程序包括 org.apache.xmlgraphics:fop 2.3,它使用 apache commons-logging (在我們的設置中是 1.2 版,而不是最初在 fop 中使用的 1.0.4 版)。

這種組合已經使用 log4-jcl、Commons Logging Bridge 運行了多年,並且所有 commons-logging 輸出都正確地進入了 log4j 配置的文件中。 配置相當簡單,如this SO answer中所述

然而,沒有明顯的原因,fop 最近開始將其所有(相當冗長的)日志寫入 stderr(即直接寫入 catalina.out)而不是配置的日志文件,但僅限於我們的某些系統。 我們有大約 50 個 tomcat 實例運行基本相同的軟件和相同的系統配置; 其中三分之一仍然正確記錄。

我假設 commons-logging 沒有找到 log4j-jcl 的 org.apache.commons.logging.LogFactory 實現。

使用Configuration status="trace"調試 log4j 不會提供 log4j-jcl 或其他地方的任何失敗提示。

我沒腦子了有什么建議?

回答我自己的問題,以防對其他人有幫助。

我需要在類路徑中添加一個名為commons-logging.properties的文件,其中包含一行:

org.apache.commons.logging.LogFactory=org.apache.logging.log4j.jcl.LogFactoryImpl

感謝 Piotr 關於設置 org.apache.commons.logging.diagnostics.dest 的評論。

顯然,如果未明確指定類,則實際使用的 LogFactory 的實現取決於類加載器加載潛在候選者的(有點隨機)順序。

我的 webapp 一個 maven 依賴項帶來了 sl4f 作為傳遞依賴項,因此在某些系統上選擇了 slf4j 而不是 log4j,但 slf4 沒有有效配置並默認為 STDERR。

雖然您的回答解釋了為什么沒有選擇 Log4j 2.x 作為 JCL 的后端,但有些細節並沒有增加:原始的commons-logging從不選擇 SLF4j 作為后端(參見源代碼)。 因此,情況必須更加復雜:

  • 原始的commons-logging通過ServiceLoader實用程序發現替代的LogFactory實現。
  • 您的類路徑中必須有兩個替代的LogFactory實現: log4j-jclspring-jcl 后者是標准commons-logging庫的完整替代品(即它包含org.apache.commons.logging.LogFactory本身的副本)並具有一些復雜的后端選擇規則(參見源代碼),在您的情況下更喜歡基於 Log4j 2.x 的 SLF4J。

由於類加載器從commons-loggingspring-jcl隨機加載org.apache.commons.logging.LogFactory類,因此您可能會遇到兩種問題:

  1. 如果選擇了commons-logging版本,則ServiceLoader隨機加載log4j-jcl的實現或spring-jcl的實現。 您已經在回答中解決了這個案例。
  2. 如果選擇spring-jcl的版本,將使用 SLF4J 后端。

為了解決所有這些潛在的問題,我會:

  1. 刪除原始的commons-logging並保留克隆spring-jcl 更好的是,我會排除兩者並使用確定性jcl-over-slf4j (始終使用 SLF4J 的完整 JCL 替換)
  2. 刪除log4j-jcl因為不再需要它(只有原始commons-logging需要它),
  3. 添加log4j-slf4j-impl SLF4J 綁定。

此解決方案向您的日志記錄配置(JCL -> SLF4J -> Log4j 2.x)添加了一個額外的 API,但保證了穩定性。 這也是spring-boot-starter-log4j2工作方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM