这是我在重审项目的日志体系时,发现的问题,感觉非常经典,有必要展开详细说一下。
历史说明
- 项目最开始用的是
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 对象。