【经验】日志框架冲突排查与常规日志依赖梳理
背景
一次评论的需求上线,回归预发验证后,上线过程中总是偶发性的发布失败。
排查记录,略
排包提交清单:
- 强制指定 log4j-jcl 版本: 略
- 新引入包排包: 略
- 排除老包中 log4j-jcl依赖: 略
- 全局排除老包中 slf4j-log4j12 依赖: 略
异常结论
1. 迭代过程中引入新的依赖,导致依赖树发生变化
2. 历史隐藏的日志冲突导致偶发性的日志循环依赖启动异常(回归、预发启动正常,线上机器部分启动正常)
本次细节相关
- jcl-over-slf4j 和 log4j-jcl 不能同时存在,否则容易造成类找不到等问题。
- 高版本的 log4j-core 拿掉了 log4j-jcl,如果 log4j-core 和 log4j-jcl 不一致,会造成 ClassNotFound
- slf4j-log4j12 和 log4j-slf4j-imp 不能同时存在,否则容易出现循环依赖问题。
- 多绑定冲突: org.slf4j.spi.LoggerFactoryBinder 接口自己项目中查看实现类有多个
知识点
常规的日志框架如下,若以 log4j2 为主(绿色部分):
区分 log4j 和 log4j2
- log4j 主要实现在 log4j:log4j.jar
- log4j2 的依赖实现主要在 apache 的 log4j-api 和 log4j-core 两个包内
日志接口规范(slf4j)
- java 日志的通用 api: slf4j-api(Simple Logging Facade for Java)
- 绑定 slf4j 主要是通过实现 slf4j-api 里面定义的 org.slf4j.spi.LoggerFactoryBinder 接口
- log4j 绑定 slf4j: slf4j-log4j12(与 5 互斥)
- Log4j2 绑定slf4j: log4j-slf4j-impl(与 4 互斥)
主日志框架之外的日志框架桥接
- log4j 的 api 桥接到 Log4j2 输出: log4j-1.2-api
- 防止有些三方包使用了 log4j,将日志也桥接到 Log4j2
- log4j 桥接到 slf4j: log4j-over-slf4j
- log4j2 桥接到 slf4j: log4j-to-slf4j(如果以 log4j2 实现绑定 slf4j,则不需要桥接)
- jcl 桥接到 slf4j: jcl-over-slf4j
- jcl 全称为 Jakarta Commons Logging,是 Apache 提供的一个通用日志 API(commons-logging)
- commons-logging 可能有两个 jar,分别是 commons-logging: commons-logging 和 org.apache.commons:commons-logging,都需要排掉
- jul 桥接到 slf4j: jul-to-slf4j
- java.util.logging.Logger(JDK)
相关资料
- 公司日志框架各个包的作用: 公司文档-略
- 日志框架之间的桥接和依赖: https://codeantenna.com/a/aW5ov78Flk
- Jar包冲突检查工具: 公司文档-略
- 日志输出的疑难杂症: 公司文档-略
邀请标记你的阅读体验😉 | →