searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

spring工程通过接口/配置中心动态更新日志级别

2023-07-25 01:50:00
32
0

背景

  有时候在服务运行中,需要查看debug 级别的日志,但是不方便重新打包,或者到部署的服务器去改日志配置文件,那么就需要通过接口,或者配置中心的方式动态修改。

实现

核心代码主要是借助 org.springframework.boot.logging.LoggingSystem
以下是一个根据日志名前缀匹配,动态修改日志级别接口,可以把该接口暴露为http 接口,一般的日志名,都是用以下方式设置:

LoggerFactory.getLogger(LogLevelConfig.class)

这样,就可以用输入包路径,或者具体类名,来动态修改对应的日志级别了

@Service
public class LogLevelConfig {
   private static final Logger logger = LoggerFactory.getLogger(LogLevelConfig.class);

    @Autowired
    private LoggingSystem loggingSystem;

    public void refreshLoggingLevels(String logNamePrefix,String strLevel ) {
            //info,error,debug
            LogLevel level = LogLevel.valueOf(strLevel.toUpperCase());
           for(LoggerConfiguration loggerCfg:loggingSystem.getLoggerConfigurations())
           {
                     if(loggerCfg.getName().startsWith(logNamePrefix))
                      {
                           //这里调用一次就更新一次,不过没有好的接口,好在这个操作不多
                           loggingSystem.setLogLevel(loggerCfg.getName(), level);
                      }
             }
    }
}

经过测试,修改是立即生效的。因为spring boot的 log 组件配合 slf4j 使用, 所以可以适配不同日志框架,logback和log4j都可以使用该方式动态修改日志级别。

如果配合配置中心使用,会更符合生产中实际情况,比如接入 apollo配置中心

public class LogLevelConfig {

    private static final Logger logger = LoggerFactory.getLogger(LogLevelConfig.class);
    private static final String LOGGER_TAG = "logging.level.";

    @Autowired
    private LoggingSystem loggingSystem;

    @ApolloConfig
    private Config config;

    //监听自己服务和一个公共基础 name space
    @ApolloConfigChangeListener({ConfigConsts.NAMESPACE_APPLICATION, SvcConstant.baseMsvcNameSpace})
    private void configChangeListter(ConfigChangeEvent changeEvent) {
        refreshLoggingLevels(changeEvent.changedKeys());
    }

   @PostConstruct
    public void intLevel()
    {
        refreshLoggingLevels(null);
    }

    private void refreshLoggingLevels(Set<String> keyNames ) {
        if(keyNames ==null)
        {
            keyNames = config.getPropertyNames();
        }
        for (String key : keyNames) {
            if (StringUtils.containsIgnoreCase(key, LOGGER_TAG)) {
                String strLevel = config.getProperty(key, "info");
                LogLevel level = LogLevel.valueOf(strLevel.toUpperCase());
                key = key.replace(LOGGER_TAG, "");
                //前缀匹配
                if(key.endsWith("*"))
                {
                    key = key.replace("*","");
                    for(LoggerConfiguration loggerCfg:loggingSystem.getLoggerConfigurations())
                    {
                        if(loggerCfg.getName().startsWith(key))
                        {
                            //这里调用一次就更新一次,不过没有好的接口,好在这个操作不多
                            loggingSystem.setLogLevel(loggerCfg.getName(), level);
                        }
                    }
                }
                else//精确匹配
                {
                    loggingSystem.setLogLevel(key, level);
                }
                logger.info("{}:{}", key, strLevel);
            }
        }
    }
}

  在有微服务平台的开发场景下,配合配置中心,可以发挥最大效果,配置中心可以是Apollo或者nacos

0条评论
0 / 1000
张****钏
15文章数
1粉丝数
张****钏
15 文章 | 1 粉丝
原创

spring工程通过接口/配置中心动态更新日志级别

2023-07-25 01:50:00
32
0

背景

  有时候在服务运行中,需要查看debug 级别的日志,但是不方便重新打包,或者到部署的服务器去改日志配置文件,那么就需要通过接口,或者配置中心的方式动态修改。

实现

核心代码主要是借助 org.springframework.boot.logging.LoggingSystem
以下是一个根据日志名前缀匹配,动态修改日志级别接口,可以把该接口暴露为http 接口,一般的日志名,都是用以下方式设置:

LoggerFactory.getLogger(LogLevelConfig.class)

这样,就可以用输入包路径,或者具体类名,来动态修改对应的日志级别了

@Service
public class LogLevelConfig {
   private static final Logger logger = LoggerFactory.getLogger(LogLevelConfig.class);

    @Autowired
    private LoggingSystem loggingSystem;

    public void refreshLoggingLevels(String logNamePrefix,String strLevel ) {
            //info,error,debug
            LogLevel level = LogLevel.valueOf(strLevel.toUpperCase());
           for(LoggerConfiguration loggerCfg:loggingSystem.getLoggerConfigurations())
           {
                     if(loggerCfg.getName().startsWith(logNamePrefix))
                      {
                           //这里调用一次就更新一次,不过没有好的接口,好在这个操作不多
                           loggingSystem.setLogLevel(loggerCfg.getName(), level);
                      }
             }
    }
}

经过测试,修改是立即生效的。因为spring boot的 log 组件配合 slf4j 使用, 所以可以适配不同日志框架,logback和log4j都可以使用该方式动态修改日志级别。

如果配合配置中心使用,会更符合生产中实际情况,比如接入 apollo配置中心

public class LogLevelConfig {

    private static final Logger logger = LoggerFactory.getLogger(LogLevelConfig.class);
    private static final String LOGGER_TAG = "logging.level.";

    @Autowired
    private LoggingSystem loggingSystem;

    @ApolloConfig
    private Config config;

    //监听自己服务和一个公共基础 name space
    @ApolloConfigChangeListener({ConfigConsts.NAMESPACE_APPLICATION, SvcConstant.baseMsvcNameSpace})
    private void configChangeListter(ConfigChangeEvent changeEvent) {
        refreshLoggingLevels(changeEvent.changedKeys());
    }

   @PostConstruct
    public void intLevel()
    {
        refreshLoggingLevels(null);
    }

    private void refreshLoggingLevels(Set<String> keyNames ) {
        if(keyNames ==null)
        {
            keyNames = config.getPropertyNames();
        }
        for (String key : keyNames) {
            if (StringUtils.containsIgnoreCase(key, LOGGER_TAG)) {
                String strLevel = config.getProperty(key, "info");
                LogLevel level = LogLevel.valueOf(strLevel.toUpperCase());
                key = key.replace(LOGGER_TAG, "");
                //前缀匹配
                if(key.endsWith("*"))
                {
                    key = key.replace("*","");
                    for(LoggerConfiguration loggerCfg:loggingSystem.getLoggerConfigurations())
                    {
                        if(loggerCfg.getName().startsWith(key))
                        {
                            //这里调用一次就更新一次,不过没有好的接口,好在这个操作不多
                            loggingSystem.setLogLevel(loggerCfg.getName(), level);
                        }
                    }
                }
                else//精确匹配
                {
                    loggingSystem.setLogLevel(key, level);
                }
                logger.info("{}:{}", key, strLevel);
            }
        }
    }
}

  在有微服务平台的开发场景下,配合配置中心,可以发挥最大效果,配置中心可以是Apollo或者nacos

文章来自个人专栏
java开发实践
6 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0