1. 程式人生 > 其它 >Apollo SpringBoot log4j動態更新日誌級別

Apollo SpringBoot log4j動態更新日誌級別

技術標籤:Spring BootApollolog4jspring bootlog4j

Apollo SpringBoot log4j動態更新日誌級別

背景

使用Apollo作為配置中心,日誌配置在namespace為longging中,生產想要實現修改日誌級別後不需要重啟應用。

實現

import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import jodd.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggerConfiguration;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * @Description: Apollo 日誌級別動態重新整理
 * @Auther: chenshx
 * @Date: 2020/12/15
 */
@Component
public class LoggerLevelRefresher {
    private static final Logger logger = LoggerFactory.getLogger(LoggerConfiguration.class);
    /**
     * 日誌字首
     */
    private static final String LOGGER_TAG = "logging.level.";
    /**
     * 預設日誌級別
     */
    private static final String LOGGER_DEFAULT_LEVEL = "WARN";
    /**
     * Apollo 日誌配置對應的namespace
     */
    private static final String LOGGING_NAMESPACE = "logging";

    @Autowired
    private LoggingSystem loggingSystem;

    @ApolloConfigChangeListener(LOGGING_NAMESPACE)
    private void onChange(ConfigChangeEvent changeEvent) {
        Set<String> keyNames = changeEvent.changedKeys();
        for (String key : keyNames) {
            if (containsIgnoreCase(key, LOGGER_TAG)) {
                ConfigChange configChange = changeEvent.getChange(key);
                //刪除配置時,key對應的newValue為空,這裡設定為預設日誌級別warn
                String newValue = StringUtil.isBlank(configChange.getNewValue()) ? LOGGER_DEFAULT_LEVEL : configChange.getNewValue();
                LogLevel level = LogLevel.valueOf(newValue.toUpperCase());
                //去除日誌字首
                loggingSystem.setLogLevel(key.replace(LOGGER_TAG, ""), level);
                logger.info("key:{},new value:{},old value:{}", key, newValue, configChange.getOldValue());
            }
        }
    }

    private static boolean containsIgnoreCase(String str, String searchStr) {
        if (str == null || searchStr == null) {
            return false;
        }
        return str.toLowerCase().contains(searchStr);
    }
}

思路說明:

  1. 通過@ApolloConfigChangeListener註解,實現監聽日誌配置所在的nameSpace(註解預設是監聽application)
  2. springboot預設配置時以logging.level開頭,獲取該部分變更資料,刪除或未配置值使用預設日誌級別WARN
  3. 通過LoggingSystem.setLogLevel(String loggerName, LogLevel level)設定最新日誌級別