# 动态变更日志输出级别

> Apollo（阿波罗）是携程框架部门研发的开源配置管理中心，能够集中化管理应用不同环境、不同集群的配置，配置修改后能够实时推送到应用端，并且具备规范的权限、流程治理等特性。
>
> 官方仓库：<https://github.com/ctripcorp/apollo/>

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

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

![](https://cdn.jsdelivr.net/gh/onee-io/onee-resource/picgo/20210528163058.png)

#### 第二步：在 SpringBoot 项目中添加配置类 `LogbackConfig.java`，内容如下：

```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 日志输出，如下图所示：

![](https://cdn.jsdelivr.net/gh/onee-io/onee-resource/picgo/20210528163329.png)

#### 建议

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.onee.io/blog/apollo-pei-zhi-zhong-xin-shi-zhan-chang-jing/dong-tai-bian-geng-ri-zhi-shu-chu-ji-bie.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
