Table of Contents

 

一、引言

二、实现方案

三、方案的特点

四、存在的问题

五、终极解决办法(集群方案)

最后

 

一、引言

我们在日常工作中有没有遇到过这种情况,线上出了某个问题,需要看日志,但是发现线上INFO或者ERROR日志定位不了问题,需要看debug日志。此时我们通常的解决办法:

  1. 想办法在测试环境复现
  2. 将线上日志基本修改为debug日志(需要修改配置,然后重启,定位之后再改回来)
  3. 通过添加info日志来定位(需要提交代码,然后打包,再上线)

那么有么有一种办法,可以直接在线上正对某些机器开启debug日志,且无需重启或者发布尼?

本文将介绍一种”动态修改线上日志级别的方法“。

二、实现方案

其实我们的日志都是通过log4j实现的,而log4j本身支持通过代码来修改日志级别。具体代码如下:

//获取到需要修改日志级别的Logger,也可以直接通过字符串名称获取
Logger logger = LogManager.getLogger(TestService.class); 

//第一次获取到为null
System.out.println(logger.getLevel());

//打印名称
System.out.println(logger.getName());

//修改日志级别,如修改为DEBUG
logger.setLevel(Level.DEBUG);

所以,我们只需要在工程中实现一个LogController,其方法实现参考上述内容,即可实现一个能够动态修改日志的API。

/**
 * 修改日志级别API
 *
 * @author xbc
 * @date 2019-11-27
 */
@RestController
public class LogController {
    @RequestMapping("/chagneLogLevel")
    public String changeLogLevel(String logggerName, String logLevel) {
        Logger logger = LogManager.getLogger(logggerName);
        logger.setLevel(Level.toLevel(logLevel, Level.ERROR));
        return logger.getLevel().toString();
    }
}

在我们需要修改日志级别的时候,直接调用对应的API接口即可。在需要开启Debug日志的机器上,执行上述代码,就能够将这台机器的某个的日志基本修改为DEBUG。注意:当我们定位完问题之后,记得将线上日志基本修改回来。

三、方案的特点

修改方便快捷:直接线上执行,无需重启、上线等繁琐的操作。

可以精确修改:能够精确到某台机器上的某个Logger。

四、存在的问题

只能一台一台的修改,如果是集群环境会比较麻烦。

五、终极解决办法(集群方案)

针对上述单机方案的问题,这里提出一个终极方案,来达到可以一次性修改所有机器的日志级别的目的。

方案比较简单,一般使用了集群的公司都会有一个叫做”统一配置中心“的中间件,其功能就是统一管理集群中所有机器的配置。当修改配置的时候,只需要在配置中心修改,所有的配置都会准实时的下发到集群中所有的机器。如果实在没有接触过"统一配置中心"的同学,就去百度吧。或者等我后面专门写一篇文件来解析统一配置中心。

有了配置中心,我们就可以利用其能够将配置下发到集群中所有机器的能力来实现修改集群中所有机器的日志的功能。具体实现很简单,就是在定义一个配置项,其内容就是日志级别和日志名称,只要对其修改,就将这个配置项下发到集群中所有机器,当机器收到配置项的时候就根据其内容直接设置对应Logger的日志级别即可(具体设置方式和上面的代码类似)。当然使用完成之后也要就记得将日志修改回去,因为毕竟在线上开启DEBUG日志不是一件明智的事。

注:这里只提供方案思想,各位同学可以自由发挥代码实现。