开启:actuator
查看所有logger
GET http://localhost:8090/actuator/loggers
指定loggerName查看
GET http://localhost:8090/actuator/loggers/loggerName
修改loggerName日志级别
POST http://localhost:8090/actuator/loggers/loggerName
Content-Type: application/json
{
“configuredLevel”: “WARN”
}
提供日志级别动态修改接口(例如:Log4j2)
spring boot 2.x 不生效
org.apache.logging.log4j.core.LoggerContext context =
org.apache.logging.log4j.core.LoggerContext.getContext(false);
org.apache.logging.log4j.Level level = valueOf(update.getLevel());
String name = update.getName();
Collection<org.apache.logging.log4j.core.Logger> current = context.getLoggers();
current.addAll(org.apache.logging.log4j.core.LoggerContext.getContext().getLoggers());
for (org.apache.logging.log4j.core.Logger logger : current) {
if (logger.getName().equals(name)) {
logger.setLevel(level);
}
}
SpringBoot动态修改日志级别
参考
spring-boot-starter-actuator提供了日志级别动态变更功能
actuator中的实现参考如下两个类
org.springframework.boot.actuate.autoconfigure.logging.LoggersEndpointAutoConfiguration#loggersEndpoint
org.springframework.boot.actuate.logging.LoggersEndpoint
如下是本文所讲,SpringBoot动态修改日志级别的具体实现
为什么实现代码如下,建议先看明白SpringBoot中的 org.springframework.boot.context.logging.LoggingApplicationListener
这个只能针对当前单进程有效,示例代码只是用来了解其背后的原理,要想在分布式系统的所有进程中生效,可以对接配置中心来监听配置变更,利用LoggingSystem
来动态修改日志级别.
@Slf4j
@RestController
public class LoggerLevelController {
private static final Map<String, LogLevel> LEVELS = new HashMap<>();
static {
LEVELS.put("trace", LogLevel.TRACE);
LEVELS.put("debug", LogLevel.DEBUG);
LEVELS.put("info", LogLevel.INFO);
LEVELS.put("warn", LogLevel.WARN);
LEVELS.put("error", LogLevel.ERROR);
LEVELS.put("off", LogLevel.OFF);
}
@Autowired
private ApplicationContext context;
/** 设置日志级别 */
@RequestMapping("/level/{loggerName}")
public List<LoggerConfiguration> setLevel(@PathVariable(name = "loggerName") String loggerName, String level) {
LogLevel logLevel = LEVELS.getOrDefault(level, LogLevel.INFO);
LoggingSystem loggingSystem = context.getBean(LoggingApplicationListener.LOGGING_SYSTEM_BEAN_NAME, LoggingSystem.class);
//按分组设置日志级别
LoggerGroups loggerGroups = context.getBean(LoggingApplicationListener.LOGGER_GROUPS_BEAN_NAME, LoggerGroups.class);
LoggerGroup group = loggerGroups.get(loggerName);
if (group != null && group.hasMembers()) {
group.configureLogLevel(logLevel, loggingSystem::setLogLevel);
List<LoggerConfiguration> loggerConfigs = group.getMembers().stream()
.map(loggingSystem::getLoggerConfiguration)
.collect(Collectors.toList());
return loggerConfigs;
}
//只针对单个loggerName设置日志级别
LoggerConfiguration loggerConfiguration = loggingSystem.getLoggerConfiguration(loggerName);
//如果loggerName对应的Logger不存在不应该修改其日志级别,如果日志使用的是logback,可能导致内存泄漏
//参见 ch.qos.logback.classic.LoggerContext.getLogger(java.lang.String) L142
if (loggerConfiguration == null) {
return Collections.emptyList();
}
loggingSystem.setLogLevel(loggerName, logLevel);
return Collections.singletonList(loggingSystem.getLoggerConfiguration(loggerName));
}
/** 获取所有的日志级别设置 */
@RequestMapping("/allLogs")
public List<LoggerConfiguration> allLoggerConfigs() {
LoggingSystem loggingSystem = context.getBean(LoggingApplicationListener.LOGGING_SYSTEM_BEAN_NAME, LoggingSystem.class);
return loggingSystem.getLoggerConfigurations();
}
@RequestMapping("/log")
public String log(String level) {
log.debug("debug");
log.info("info");
log.warn("warn");
log.error("error");
System.out.println();
return level;
}
}