热修改日志等级

几天前遇到了一些问题,想查看线上的debug日志但是不好重启服务,有人建议使用了一下log4j的日志等级调整。于是写了一个后台api可以简单的实现日志等级调整的接口让后续维护更简单一些,当然起新服务再tcpcopy流量到备份服务上也ok但是麻烦。本文只是记录一下这样可以。

public class LogTools {  
    public static Level changeLevel(String value) {
        Level nowRootLevel = LogManager.getRootLogger().getLevel();
        String nowLevel =nowRootLevel.toString();
        if (nowLevel.equals(value)) {
            return nowRootLevel;
        }
        final Level level = Level.toLevel(value);
        LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
        Configuration logConf = loggerContext.getConfiguration();
        logConf.getLoggerConfig(LogManager.ROOT_LOGGER_NAME).setLevel(level);
        loggerContext.updateLoggers(logConf);

        Collection<Logger> loggers = loggerContext.getLoggers();
        for (org.apache.logging.log4j.core.Logger logger: loggers) {
            logger.setLevel(level);
        }
        return level;
    }

    public static Level changeLevel(String logName, String value) {
        Level level = Level.toLevel(value);
        LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
        Collection<Logger> loggers = loggerContext.getLoggers();
        for (org.apache.logging.log4j.core.Logger logger: loggers) {
            if (logger.getName().equals(logName)) {
                logger.setLevel(level);
            }
        }
        return level;
    }
}

简单测试一下:

  @Test
    public void test() {
        org.apache.logging.log4j.Logger logger1 = LogManager.getLogger(LogTools.class);
        org.apache.logging.log4j.Logger logger2 = LogManager.getLogger("testLog");
        LogTools.changeLevel("WARN");
        Assert.assertEquals(logger1.getLevel(), Level.WARN);
        Assert.assertEquals(logger2.getLevel(), Level.WARN);

        LogTools.changeLevel("testLog", "DEBUG");
        Assert.assertEquals(logger1.getLevel(), Level.WARN);
        Assert.assertEquals(logger2.getLevel(), Level.DEBUG);

        LogTools.changeLevel(LogTools.class.getName(), "DEBUG");
        Assert.assertEquals(logger1.getLevel(), Level.DEBUG);
        Assert.assertEquals(logger2.getLevel(), Level.DEBUG);
    }

调用的时候:

 /**
     *
     * @param logLevel
     * @param loggerName
     * @param token
     * @return
     */
    @RequestMapping(value = "/api/config/log/level", method = RequestMethod.POST, consumes = HEAD)
    ResponseEntity setLogLevel(@RequestParam(value = Constants.LOG_LOCAL_LEVEL, required = true)  String logLevel,
                               @RequestParam(value = Constants.LOGGER_NAME, required = false)  String loggerName,
                               @RequestParam(value = Constants.ACCESS_TOKEN_FIELD, required = false)  String token) {
        if (!isAdmin(token)) {
            return buildNotAdminResponse();
        }
        try {
            if (StringUtils.isEmpty(loggerName)) {
                LogTools.changeLevel(logLevel);
            } else {
                LogTools.changeLevel(loggerName, logLevel);
            }
            return buildSuccess();
        } catch (Exception e) {
            return buildNotAdminResponse(e);
        }
    }
comments powered by Disqus