我們的 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 或其他地方的任何失敗提示。
我沒腦子了 有什么建議?
uj5u.com熱心網友回復:
回答我自己的問題,以防對其他人有幫助。
我需要在類路徑中添加一個名為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。
uj5u.com熱心網友回復:
雖然您的回答解釋了為什么沒有選擇 Log4j 2.x 作為 JCL 的后端,但有些細節并沒有增加:原始版本commons-logging 從不選擇 SLF4j 作為后端(參見源代碼)。因此,情況必須更加復雜:
- 原件通過實用程式
commons-logging發現替代LogFactory實作ServiceLoader。 - 您
LogFactory的類路徑中必須有兩個替代實作:log4j-jcl和spring-jcl. 后者是標準庫的完全替代品commons-logging(即它包含org.apache.commons.logging.LogFactory自身的副本)并具有一些復雜的后端選擇規則(參見源代碼),在您的情況下,它更喜歡 SLF4J 而不是 Log4j 2.x。
由于類加載器隨機加載org.apache.commons.logging.LogFactory類,commons-logging否則spring-jcl您可能會遇到兩種問題:
- 如果
commons-logging選擇了版本,則ServiceLoader隨機加載log4j-jcl的實作或spring-jcl的實作。您已經在回答中解決了這個案例。 - 如果
spring-jcl選擇了 的版本,則將使用 SLF4J 后端。
為了解決所有這些潛在的問題,我會:
- 洗掉原始
commons-logging并保留克隆spring-jcl。更好的是,我會排除兩者并使用確定性jcl-over-slf4j(始終使用 SLF4J 的完整 JCL 替換) - 洗掉,
log4j-jcl因為不再需要它(只有原始需要commons-logging), - 添加
log4j-slf4j-implSLF4J 系結。
此解決方案向您的日志記錄配置(JCL -> SLF4J -> Log4j 2.x)添加了一個額外的 API,但保證了穩定性。這也是作業的方式spring-boot-starter-log4j2。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/359087.html
標籤:爪哇 公猫 日志4j apache-commons-日志记录
上一篇:Log4j2記憶體泄漏
