动态修改日志级别

在日常编程中,为了方便我们定位问题我们时常会打印日志,在测试开发和生产各个环境中的日志级别可能都不一样,在自己自己开发过程中为了方便调试打印了很多日志,但是生产中为了性能这些日志我们可能需要屏蔽掉,只保留一些必要的日志;

我们知道在Log4j中的日志级别,优先级从高到低依次为:OFF,ERROR,WARN,INFO,DEBUG,TRACE; 这边博客主要讲解如何动态的修改日志的级别,不需要重启项目直接给日志降级或者升级;

Spring Boot 1.5 开始,Spring Boot Actuator 组件就已提供动态修改日志级别的能力;

废话不多说了,亮出代码吧!

代码编写

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
@RestController
public class TestController {

private static final Logger LOGGER = LoggerFactory.getLogger(TestController.class);

@GetMapping("/test")
public String simple() {
LOGGER.debug("这是一个debug日志...");
return "test loggers";
}
}
#由于Spring Boot 2.x默认只暴露 /health 以及 /info 端点,而日志控制需要用到 /loggers 端点,故而需要设置#将其暴露。当然把loggers替换成*也是可以的;开启所有!
server:
port: 9090

management:
endpoints:
web:
exposure:
include: 'loggers'

代码就是验证效果使用;很简单!

测试

/loggers 端点提供了 查看 以及 修改 日志级别的能力

查看当前应用各包/类的日志级别!

在浏览器中键入 http://localhost:9090/actuator/loggers 会看到如下:

le

这里列出了所有的包以及类的日志级别;这里我只截出了一部分。

查看指定包/类日志详情

访问 localhost:9090/actuator/loggers/cn.haoxiaoyong.loggers.TestController ,可看到类似如下的结果:

{"configuredLevel":"INFO","effectiveLevel":"INFO"}

修改日志级别

在上面的示例TestController中打印了一条日志LOGGER.debug("这是一个debug日志...");而上面的测试显示我们现在的日志级别为INFO,根据日志级别,这个DEBUG日志是不会打印的;经过测试也正如我们所愿没有打印,不信的话可以自己试一下;

下面我们就把日志级别修改为DEBUG,修改方式如下:

使用postman获取其他工具输入地址 localhost:9090/actuator/loggers/cn.haoxiaoyong.loggers.TestController

image-20201230142643185

如果实在没有工具直接用命令行吧

curl -X POST http://localhost:9090/actuator/loggers/cn.haoxiaoyong.loggers.TestController \
-H "Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8" \
--data '{"configuredLevel":"debug"}'

Content-Type:application/josn也可以!这都不是重点!重点我们看看修改成功没有?

使用上面的测试方法:访问 localhost:9090/actuator/loggers/cn.haoxiaoyong.loggers.TestController

{"configuredLevel":"DEBUG","effectiveLevel":"DEBUG"}

打印了这个说明成功了! 这时候我们再去访问TestController这就日志就会打印了!

你觉得这样就结束了吗?我不要你觉得我要我觉得!下面我们要看一下原理是什么?

分析原理

Actuator有约定, /actuator/xxx 端点的定义代码在 xxxEndpoint。故而,找到类 org.springframework.boot.actuate.logging.LoggersEndpoint ,可看到类似如下的代码:

@Endpoint(id = "loggers") 用来描述Spring Boot Actuator 的端点,这样就会产生一个/actuator/loggers 的路径,它类似于Spring MVC的 @RequestMapping("loggers")@WriteOperation 表示这是一个写操作,它类似于Spring MVC的 @PostMapping 。Spring Boot Actuator还提供了其他操作,如下表:

Operation HTTP method
@ReadOperation GET
@WriteOperation POST
@DeleteOperation DELETE

@Selector相当于SpringMVC中的@PathVariable

上面的代码就很好理解了—— configureLogLevel 方法里面就一行代码 :this.loggingSystem.setLogLevel(name, configuredLevel); ,发送POST请求后,name就是我们传的包名或者类名cn.haoxiaoyong.loggers.TestController,configuredLevel就是我们传的消息体日志级别INFO,DEBUG......

我们点进去setLogLevel这个方法发现有四个实现类:

image-20201230222912700
// 适用于java.util.logging的LoggingSystem
org.springframework.boot.logging.java.JavaLoggingSystem
//适用于Log4j2的LoggingSystem
org.springframework.boot.logging.log4j2.Log4J2LoggingSystem
//适用于logback的LoggingSystem
org.springframework.boot.logging.logback.LogbackLoggingSystem
// 啥都不干的LoggingSystem
org.springframework.boot.logging.LoggingSystem.NoOpLoggingSystem

Spring Boot 2.x中,默认使用Logback,因此进入到 LogbackLoggingSystem 中;代码就不贴了感兴趣的可以去看一下;其实就是Spring Boot使用了Logback的API,ch.qos.logback.classic.Logger.setLevel 实现日志级别的修改。

使用界面化修改日志级别

上面我们使用了PostMan和curl命令的方式修改日志的级别,该方式不适用生产,因为很麻烦,容易出错。生产环境,建议根据Actuator提供的RESTful API定制界面,或使用 Spring Boot Admin ,可视化修改日志级别,如下图所示:

image-20201230152144161

至此这次博客就真的结束了!看完点赞 下次见!