这是我在重审项目的日志体系时,发现的问题,感觉非常经典,有必要展开详细说一下。
历史说明
- 项目最开始用的是
log4j
,其配置文件是log4j.xml
- 用的方法是使用了一个日志工厂,返回
log4j
对象(下面详细说)
- 用的方法是使用了一个日志工厂,返回
log4j
出问题了,项目转向logback
日志体系,其配置文件是logback-spring.xml
(将原来log4j
的配置文件删除了)
工厂类获取(最开始使用的方法)
模块中获取 log
1 | public class HandleChangeService<T> { |
LogFactory 的核心方法
1 | import org.apache.logging.log4j.Level; |
从这个代码上看,LogFactory
返回的是 log4j
的对象,但是,log4j
和 logback
的配置文件并不能互通。所以,理论上 log4j
不能按照 logback-spring.xml
的配置输出。
但是,实际情况下,LogFactory
返回的日志对象,就是按照 logback-spring.xml
输出的。
问题解决
经过大规模排查,最终找到问题所在。
首先,在配置文件中,指出
1 | logging: |
当运行 Log4jWrapper
中获取 LogManager.getLogger(clazz)
时,最后发现返回的对象是 ch.qos.logback.classic.LoggerContext[logback]
。
询问,chatgpt
后,其给出了这样的解释
问题:使用 log4j
的 LogManager.getLogger
,最后返回的却是 logback
chatgpt
:如果你使用 Log4j
的 LogManager.getLogger
方法,但最终返回的是 Logback
日志记录器,通常是因为项目的类路径中同时存在 Log4j
和 Logback
的依赖,或者因为存在冲突的日志框架依赖。
在这种情况下,Java
类加载器可能会选择其中一个日志框架来处理日志记录,导致混淆。
所以,Log4jWrapper
因为 logback-spring.xml
的配置,导致日志进行了混淆,最后 java
类加载器返回的是 logback
对象。