已忽略Log4j Commons日志记录桥

3vpjnl9f  于 2022-11-06  发布在  其他
关注(0)|答案(2)|浏览(210)

我们的Web应用程序在tomcat 9容器中运行,并使用Log4j2.13.3作为日志记录系统。
这个web应用程序包含org.apache.xmlgraphics:fop 2.3,它使用apachecommons-logging(在我们的设置中是1.2版,而不是fop中最初使用的1.0.4版)。
这个组合已经使用log 4-jcl(CommonsLogging Bridge)运行了很多年,所有的公共日志输出都正确地进入了log4j配置的文件中。
然而,没有明显的原因,fop最近开始把它所有的(相当冗长的)日志写入stderr(也就是直接写入 Catalina .out),而不是写入配置好的日志文件,但这只是在我们的一些系统上。但仍有三分之一能正确记录。
我假设commons-logging没有找到log4j-jcl的org. apache. commons. logging. LogFactory实现。
使用 Configuration status=“trace” 调试log4j不会在log4j-jcl或其他地方提供任何失败提示。
我都快疯了有什么建议吗

idfiyjo8

idfiyjo81#

虽然您的回答解释了为什么没有选择Log4j 2.x作为JCL的后端,但有些细节并不合理:原来的commons-logging从来没有选择SLF 4j作为后端(参见源代码)。因此情况一定更加复杂:

  • 原始的commons-logging通过ServiceLoader实用程序发现替代的LogFactory实现。
  • 类路径中必须有两个替代LogFactory实现:log4j-jclspring-jcl。后者是标准commons-logging库的完全替代品(即它包含org.apache.commons.logging.LogFactory本身的副本),并具有一些复杂的后端选择规则(参见源代码),在您的情况下,它首选SLF 4J而不是Log4j 2.x。

由于类加载器从commons-loggingspring-jcl随机加载org.apache.commons.logging.LogFactory类,因此可能会出现两种问题:
1.如果选择了commons-logging版本,ServiceLoader将随机加载log4j-jcl的实现或spring-jcl的实现。2你已经在答案中解决了这个问题。
1.如果选择了spring-jcl的版本,则将使用SLF 4J后端。
为了解决所有这些潜在的问题,我会:
1.删除原始的commons-logging并保留克隆的spring-jcl。更好的是,我将两者都排除,并使用确定性的jcl-over-slf4j(完全的JCL替换,始终使用SLF 4J)
1.删除log4j-jcl,因为不再需要它(只有原来的commons-logging需要它),
1.添加log4j-slf4j-impl SLF 4J绑定。
这个解决方案在日志配置(JCL -〉SLF 4J-〉Log4j 2.x)中添加了一个额外的API,但保证了稳定性,这也是spring-boot-starter-log4j2的工作方式。

zzoitvuj

zzoitvuj2#

回答我自己的问题,以防对别人有帮助。
我需要在类路径中添加一个名为commons-logging.properties的文件,其中包含一行代码:

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

感谢Piotr关于设置org.apache.commons.logging.diagnostics.dest.的评论。
显然,如果没有显式指定类,则实际使用的LogFactory的实现取决于类加载器加载潜在候选对象的顺序(有些随机)。
在我的webapp中,maven依赖项将sl 4f沿着可传递依赖项,因此在某些系统上选择slf 4j而不是log4j,但slf 4没有有效配置,默认为STDERR。

相关问题