我们的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或其他地方提供任何失败提示。
我都快疯了有什么建议吗
2条答案
按热度按时间idfiyjo81#
虽然您的回答解释了为什么没有选择Log4j 2.x作为JCL的后端,但有些细节并不合理:原来的
commons-logging
从来没有选择SLF 4j作为后端(参见源代码)。因此情况一定更加复杂:commons-logging
通过ServiceLoader
实用程序发现替代的LogFactory
实现。LogFactory
实现:log4j-jcl
和spring-jcl
。后者是标准commons-logging
库的完全替代品(即它包含org.apache.commons.logging.LogFactory
本身的副本),并具有一些复杂的后端选择规则(参见源代码),在您的情况下,它首选SLF 4J而不是Log4j 2.x。由于类加载器从
commons-logging
或spring-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
的工作方式。zzoitvuj2#
回答我自己的问题,以防对别人有帮助。
我需要在类路径中添加一个名为commons-logging.properties的文件,其中包含一行代码:
感谢Piotr关于设置org.apache.commons.logging.diagnostics.dest.的评论。
显然,如果没有显式指定类,则实际使用的LogFactory的实现取决于类加载器加载潜在候选对象的顺序(有些随机)。
在我的webapp中,maven依赖项将sl 4f沿着可传递依赖项,因此在某些系统上选择slf 4j而不是log4j,但slf 4没有有效配置,默认为STDERR。