开发log4j配置_从 log4j 迁移到 logback

本文介绍了如何将项目中的日志框架从log4j平稳过渡到logback,包括基于slf4j的无痛迁移步骤、直接迁移的注意事项、解决死循环问题的方法,以及在迁移过程中遇到的jcl问题和解决方案。
摘要由CSDN通过智能技术生成

最近把项目的日志框架从 log4j 迁移到 logback,过程里遇到很多坑,记录下来

目标

本次迁移的目标就是用 slf4j+logback 的日志框架来取代目前的 slf4j+log4j

如何迁移

基于 slf4j+log4j 的无痛迁移

如果项目本身是采用的 slf4j+log4j 日志架构,迁移到 logback 就比较简单

第一步:修改依赖

原本是 slf4j+log4,依赖如下

org.slf4j  slf4j-apiorg.slf4j  slf4j-log4j12log4j  log4j

迁移到 slf4j+logback,依赖如下

org.slf4j  slf4j-apich.qos.logback  logback-classic

第二步:修改日志配置

logback 的配置文件为 logback.xml,替换掉 log4j.xml,以下示例,配置了输出日志到控制台及异步输出到文件,日志文件按日期滚动;同时支持使用 mdc 打印会话唯一标识 sid

<?xml version="1.0" encoding="UTF-8"?>%date{HH:mm:ss.SSS} [%-5level] [%logger:%L] %mdc{sid:--} - %msg%nUTF-8DEBUG${log.path}/${app.name}.log${log.path}/${app.name}.log.%d{yyyy-MM-dd}%date{HH:mm:ss.SSS} [%-5level] [%logger] %mdc{sid:--} - %msg%nUTF-8DEBUG0

第三步:web 项目初始化日志

增加如下依赖

org.logback-extensions logback-ext-spring 0.1.5

在 web.xml 里增加如下监听器

logbackConfigLocationclasspath:config/logback.xmlch.qos.logback.ext.spring.web.LogbackConfigListener

直接从 log4j 迁移

项目里依赖了其他一些库,可以用 maven 命令 mvn dependency:tree 来查看下,都有哪些库还用到了 log4j,如果这些库也是 slf4j+log4j 的架构那就万事大吉,但也有的库直接用的 log4j,这样就有点小麻烦了

根据 slf4j 的文档(http://www.slf4j.org/legacy.html),使用 log4j 桥接器 log4j-over-slf4j 来替换 log4j 依赖:即在所有依赖到 log4j 的库上排除 log4j 的依赖,并添加 log4j-over-slf4j 依赖,如下

com.refusea.framework framework-service compile       log4j       log4jorg.slf4j log4j-over-slf4j

其他日志框架(jul/jcl/log4j2/...) 和 log4j 类似,slf4j 为其他日志框架提供了 xxx-over-slf4j 桥接器,比如 jcl-over-slf4j,如果用到了对应的日志框架,只需要在依赖里排除该日志框架依赖,并添加对应的桥接器即可


这里要特别提一下 jul(java.util.logging),由于这个日志框架内置在 jdk 内,无法通过置换依赖的方式来桥接,所以需要项目自己调用一下桥接器的方法,在项目初始化时执行如下代码即可

SLF4JBridgeHandler.removeHandlersForRootLogger();SLF4JBridgeHandler.install();

也许是因为这个原因,jul 的桥接器名字是 jul-to-slf4j 而不是 jul-over-sl4fj

小心死循环

使用 slf4j 桥接方式时,需要注意避免死循环,以桥接 log4j 为例说明


slf4j+log4j 要用到 slf4j-log4j12,这个库的作用是将 log4j 适配到 slf4j,其调用逻辑如下图

2a222d5ce2a41740ad23cc8e515ba198.png

sl4fj+log4j

如果在桥接 log4j 时系统里还存在 slf4j-log4j12 库,就会导致如下的调用逻辑

bfb3816ac1bc08a5dff8fb2ada196aad.png

slf4j+log4j+log4j桥接死循环

可以发现这样会导致死循环,解决的办法很简单:从所有依赖里排除 slf4j-log4j12 库

maven-enforcer-plugin

现在你排除了所有可能导致死循环的依赖,但是某天你引入了一个新的依赖,一时疏忽,没有排查这个新的依赖是否传递了 slf4j-logj12,那就存在死循环的风险;另一方面,就算你能保证自己每次都不会疏忽,但是你能保证项目里的其他开发人员也会在引入新依赖时进行检查吗?

这种情况,可以使用 maven 插件 maven-enforcer-plugin 来帮我们检查,把你想要排除的依赖配置一次即可

org.apache.maven.pluginsmaven-enforcer-plugin3.0.0-M2enforceenforce3.2.5maven version must be 3.2.5 or above1.7log4j:*org.apache.logging.log4j:*commons-logging:commons-loggingorg.slf4j:slf4j-log4j12org.slf4j:slf4j-jclorg.slf4j:slf4j-jdk14DO NOT use any other logger framework beyond slf4j+logback

jcl 的坑

jcl,即 The Apache Commons Logging,也是广泛应用的日志框架,在迁移的过程中,我们会排除该日志组件并用 jcl-over-slf4j 来取代它,并通过 maven-enforcer-plugin 来避免将可能导致死循环的依赖打包

问题是这一套看上去无懈可击的流程有漏洞:没有 jcl,maven-assembly-plugin 这个插件无法工作;而且这个插件会把 jcl 强行塞到最终输出的 zip 里,并不会触发 maven-enforcer-plugin 配置的排除规则

经过一番研究,发现把 jcl 的 scope 设为 provided 可以解决这个问题

commons-logging    commons-logging    1.2provided
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值