上篇[ SpringBoot 动态设置 logback 日志的级别 ] 说了 logback 动态设置日志级别。这篇来说下 log4j2 日志框架结合 SpringBoot 动态设置日志级别。因为 log4j2 日志框架也有非常多的公司采用,毕竟 logback 和 log4j2 是现在用的最多的两个日志框架。都不能落对吧。
0x01:pom.xml 引入依赖
代码语言:javascript复制<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.olive</groupId>
<artifactId>valid-log4j2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath />
</parent>
<name>valid-demo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions><!-- 去掉springboot默认配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency> <!-- 引入log4j2依赖 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
</dependencies>
</project>
因为 SpringBoot 默认使用 logback 记录日志。所以要排查 logback 日志框架 spring-boot-starter-logging,在引入 log4j2 日志框架 spring-boot-starter-log4j2。
0x02:Controller 控制器编写
Controller 基本框架
代码语言:javascript复制package com.olive.controller;
import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.impl.StaticLoggerBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LoggerController {
private final static Logger logger = LoggerFactory.getLogger(LoggerController.class);
// TODO
}
- 打印各级别日志
@RequestMapping("/logger/print")
public Map loggerPrint(){
Map result = new HashMap();
result.put("code", 200);
result.put("msg", "success");
logger.debug("loggerPrint debug>>>>");
logger.info("loggerPrint info>>>>");
logger.warn("loggerPrint warn>>>>");
logger.error("loggerPrint error>>>>");
return result;
}
- 打印所有日志对象
@RequestMapping("/logger/printAllLogger")
public Map printAllLogger(){
Map result = new HashMap();
result.put("code", 200);
result.put("msg", "success");
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
Map<String, LoggerConfig> loggerConfigs = config.getLoggers();
System.out.println("printAllLogger begin>>>>>>>>");
loggerConfigs.forEach((name, loggerConfig) -> {
System.out.println("name = " name);
System.out.println("loggerConfig = " loggerConfig);
});
System.out.println("printAllLogger end>>>>>>>>");
return result;
}
- 动态设置日志对象的日志级别
@RequestMapping("/logger/level")
public Map loggerLevelChange(String level){
Map result = new HashMap();
result.put("code", 200);
result.put("msg", "success");
String loggerFactoryClassStr = StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr();
System.out.println("loggerFactoryClassStr>>>>" loggerFactoryClassStr);
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
switch (level) {
case "debug":
loggerConfig.setLevel(Level.DEBUG);
break;
case "info":
loggerConfig.setLevel(Level.INFO);
break;
case "warn":
loggerConfig.setLevel(Level.WARN);
break;
case "error":
loggerConfig.setLevel(Level.ERROR);
break;
default:
break;
}
ctx.updateLoggers();
return result;
}
0x04:log4j2-spring.xml 配置
代码语言:javascript复制<?xml version="1.0" encoding="UTF-8"?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration monitorInterval="5">
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--变量配置-->
<Properties>
<!-- 格式化输出:�te表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
<!-- %logger{36} 表示 Logger 名字最长36个字符 -->
<property name="LOG_PATTERN" value="�te{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
</Properties>
<appenders>
<console name="ConsoleOut" target="SYSTEM_OUT">
<!--输出日志的格式-->
<PatternLayout pattern="${LOG_PATTERN}"/>
<!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<!-- <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> -->
</console>
</appenders>
<loggers>
<root level="debug">
<appender-ref ref="ConsoleOut"/>
</root>
</loggers>
</configuration>
这里只配置了打印到控制台的 ROOT logger。
0x05:编写引导类
代码语言:javascript复制@SpringBootApplication
public class Application
{
public static void main( String[] args )
{
SpringApplication.run(Application.class, args);
}
}
启动服务
- 打印各级别日志
因为 log4j2-spring.xml 配置的级别是 debug,所以可以在控制台看到如下打印
代码语言:javascript复制21:08:52.298 [http-nio-8080-exec-1] DEBUG com.olive.controller.LoggerController - loggerPrint debug>>>>
21:08:52.298 [http-nio-8080-exec-1] INFO com.olive.controller.LoggerController - loggerPrint info>>>>
21:08:52.298 [http-nio-8080-exec-1] WARN com.olive.controller.LoggerController - loggerPrint warn>>>>
21:08:52.298 [http-nio-8080-exec-1] ERROR com.olive.controller.LoggerController - loggerPrint error>>>>
- 打印所有日志对象
在控制台只看见打印了 ROOT logger 对象。
代码语言:javascript复制printAllLogger begin>>>>>>>>
name =
loggerConfig = root
printAllLogger end>>>>>>>>
- 动态修改日志的级别
再次调用 http://127.0.0.1:8080/logger/print 接口打印日志,在控制台看到不在打印 debug 级别日志
代码语言:javascript复制21:19:25.756 [http-nio-8080-exec-6] INFO com.olive.controller.LoggerController - loggerPrint info>>>>
21:19:25.756 [http-nio-8080-exec-6] WARN com.olive.controller.LoggerController - loggerPrint warn>>>>
21:19:25.756 [http-nio-8080-exec-6] ERROR com.olive.controller.LoggerController - loggerPrint error>>>>
- 修改 log4j2-spring.xml 配置
<loggers>
<root level="debug">
<appender-ref ref="Console"/>
</root>
<logger name="org.springframework" level="info" additivity="true">
</logger>
<logger name="org.hibernate" level="warn" additivity="true">
</logger>
</loggers>
重启服务,再次调用 http://127.0.0.1:8080/logger/printAllLogger 接口打印日志对象
代码语言:javascript复制printAllLogger begin>>>>>>>>
name =
loggerConfig = root
name = org.springframework
loggerConfig = org.springframework
name = org.hibernate
loggerConfig = org.hibernate
printAllLogger end>>>>>>>>