Java动态日志级别变更框架源码实现(支持:Log4j/JDK Logger/Logback等),教你如何开启线上debug日志

350 阅读3分钟

这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战

一、前言

在实际开发运维过程中,对于日志我们都会遇到如下痛点。我们尝尝会遇到,突然线上出了某个问题。然后大家首先会想这个问题愈发测试环境可以复现么?如果不能复现,大家就会提出一个戳中大家痛点的问题”线上可以看debug日志么?“。然后大家都会想,要是线上能开debug日志就好了。然后想象是没好的, 现实是骨感的。为什么线上不能开debug想必就不用我在此哔哔了吧。

虽然现实是骨感的,但是这确实是我们的一个痛点。这个问题也一直困扰我很久了。于是在很久之前我写了文章”如何实现Log4j在线修改日志级别(集群)“,该文章给大家提出了解决上述痛点的基本思路。

然而思路仅仅是思路,就像Linux大牛Linus Torvalds(Linux创始人)说的一样”Talk is cheap. Show me the code.“。于是我终于将上述思路实现了出来,并在线上正式运行。Now, it 's show time!

二、实现架构

其实实现架构很简单,直接来张图。核心就是连接配置中心,配置中心大家根据自己公司实际的使用就OK了。配置(哪些日志需要开启什么级别的日志)通过管理端发送到配合中心,由配置中心将配置推送给应用集群中的动态日志框架即可。

动态日志框架主要也就两部分内容,配置监听器和日志级别修改器。配置监听器:作为观察者动态监听配置规则的变化。日志级别修改器,则根据配置动态对日志基本进行修改。

关于配置:

至于配置中心的配置有哪些内容,在需要看大家需要将动态日志框架设计的多复杂。楼主目前的配置就只有一个logName的列表。表示哪些logName需要开启debug日志。

如果我们需要实现复杂一点,你甚至可以做成能够对那些logName开启什么日志,开启多久的时间。甚至可以限制哪些ip或者ip段可以开启这些日志等等。

总之基础框架实现了,大家就可以任意发挥了。

三、实现源码

大家也应该能够看出类这个动态日志框架最核心的代码就是日志级别修改器。因为配置监听是根据大家使用的不同配置中心决定的。所以这里就不做过多介绍。我们重点来看看日志级别修改器。

总体思路就是拿到配置之后,根据不同的日志框架(如Log4j, Logback、JDK Logger等)动态修改对应LogName的日志级别即可。所以我们总体就分两块内容:1、支持所有日志框架;2、调用对应日志框架的底层代码动态修改日志级别。

1、支持所有日志框架

我们如何能够支持所有的日志框架呢?关键点就是如何判断这个日志系统正在被使用。很多同学都会想,最简单的办法就是每次修改直接循环调用所有日志框架的代词代码修改即可。这种方法真的可行么?当然不行,因为如果某个日志框架没有被使用,那么通常他对应的jar包就不存在,直接调用会报类找不到的错误。于是大家可能会说,那我可以让我们日志框架导入这些需要的jar包,这样允许的时候就不会报错了。这样也不行,以为现在通常的框架如spring boot等,都是通过检查应用引入了什么jar包来决定用那种日志框架的。所以如果你帮应用把所以日志框架都引入了可能导致使用者日志混乱。同时这也不是一种很好的实现。当然另外还有一种方法,那就是执行的时候try catch,报错就说明不支持。这到也是一种办法,但是不是很完美。

那么遇到这种场景,完美且通用的办法如下图。即在静态块中,通过Class.forName来判断必要类是否存在,如果存在则将当前Modifier注册到日志修改引擎中。这样日志引擎中注册的Modifier肯定是Jar存在的,执行的时候也就不会报错了。

日志引擎在初始化的时候调用各个Modifier的Load方法来加载注册可用的Modifier。

当日志变更的时候,我们直接遍历执行日志引擎中的所有Modifier即可。

2、动态修改日志级别

通过上面的代码,我们已经知道日志修改的时候如何调用到对应日志框架的Modifier方法了。接下来咱们看看每种日志框架如何动态修改日志级别。

JDK Logger

这个比较简单,直接贴代码就好了。 

Log4j

Logback 

Logging Log4j

​ 这个一定要特殊注意下。 如果咱们动态修改的LogName在log4j的配置文件中没有显示配置过,通过config.getLoggerConfig是无法获取到该LogName对应的LoggerConfig,底层会返回root的LoggerConfig,所以直接修改会导致root的日志级别被修改。

所以这里如果判断获取到的是root,则为该LogName重新创建一个LoggerConfig即可。

目前只实现了上述的日志框架,如果还有其他框架大家按照这个模式自己实现对应的Modifier即可。

四、惯例

如果你对本文有任何疑问或者高见,欢迎添加公众号lifeofcoder共同交流探讨。