动态变更日志输出级别

Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性。

官方仓库:https://github.com/ctripcorp/apollo/

对于已经接入 Apollo 配置中心的 SpringBoot 项目来说,实现日志输出级别动态实时更新非常容易,只需要以下两步:

第一步:在 Apollo 项目中添加配置 "log.level",值为 "INFO" 即可,如下图所示:

第二步:在 SpringBoot 项目中添加配置类 LogbackConfig.java,内容如下:

import cn.hutool.core.util.StrUtil;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.context.annotation.Configuration;
 
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
 
/**
 * 日志配置
 *
 * @author onee
 */
@Slf4j
@Configuration
public class LogbackConfig {
 
    /**
     * 日志级别配置KEY
     */
    private static final String LOG_LEVEL_KEY = "log.level";
 
    /**
     * 默认日志输出级别
     */
    private static final LogLevel DEFAULT_LOG_LEVEL = LogLevel.INFO;
 
    /**
     * 日志系统
     */
    @Resource
    private LoggingSystem loggingSystem;
 
    /**
     * 初始化日志输出级别
     */
    @PostConstruct
    private void initLogLevel() {
        Config config = ConfigService.getAppConfig();
        setLogLevel(config.getProperty(LOG_LEVEL_KEY, LogLevel.INFO.name()));
    }
 
    /**
     * 监听日志级别变更事件
     *
     * @param changeEvent 变更事件
     */
    @ApolloConfigChangeListener()
    private void logLevelOnChange(ConfigChangeEvent changeEvent) {
        if (changeEvent.isChanged(LOG_LEVEL_KEY)) {
            setLogLevel(changeEvent.getChange(LOG_LEVEL_KEY).getNewValue());
        }
    }
 
    /**
     * 设置日志输出级别
     *
     * @param level 级别
     */
    private void setLogLevel(String level) {
        LogLevel logLevel = DEFAULT_LOG_LEVEL;
        if (StrUtil.isNotBlank(level)) {
            try {
                logLevel = LogLevel.valueOf(level.toUpperCase());
            } catch (Exception e) {
                log.error("日志级别错误,将使用默认日志输出级别:{}", DEFAULT_LOG_LEVEL);
            }
        }
        loggingSystem.setLogLevel("", logLevel);
        log.info("设置日志输出级别为:{}", logLevel);
    }
}

测试

完成以上两步就可以实现日志级别的实时动态更新了,启动服务后,我们在 Apollo 中将 log.level 的值改为 DEBUG 并发布,可在控制台看到变更后有 debug 日志输出,如下图所示:

建议

对于非必需的日志,如接口请求出入参等,可将日志级别改为 debug,平时 INFO 级别下不会输出,有问题时改为 DEBUG 级别进行排查,可有效减少日志体积。

Last updated