Java Log4j2在运行时不更改日志记录级别

Java Log4j2在运行时不更改日志记录级别,java,log4j2,Java,Log4j2,是的,我已经阅读了所有相关的问题。我正在使用log4j2(尝试了2.4版和更新到最新的2.6.2版) 我有一个面向客户的小型实用程序。我渴望将暴露的配置保持在最低限度。但对于有问题的情况,我还想添加一个-debug标志,以便在运行时启用调试日志 下面是我启用调试日志记录的代码 private static void enableDebugLogs(){ LoggerContext ctx = (LoggerContext) LogManager.getContext(); Log

是的,我已经阅读了所有相关的问题。我正在使用log4j2(尝试了2.4版和更新到最新的2.6.2版)

我有一个面向客户的小型实用程序。我渴望将暴露的配置保持在最低限度。但对于有问题的情况,我还想添加一个
-debug
标志,以便在运行时启用调试日志

下面是我启用调试日志记录的代码

private static void enableDebugLogs(){
    LoggerContext ctx = (LoggerContext) LogManager.getContext();
    LoggerConfig log = ctx.getConfiguration().getRootLogger();

    System.out.println(log.getLevel()); // INFO

    log.setLevel(Level.DEBUG);

    System.out.println(log.getLevel()); // DEBUG

    ctx.updateLoggers();

    System.out.println(ctx.getRootLogger().getLevel()); // DEBUG, hey it works, right?
}
但它实际上并不适用于这些情况:

enableDebugLogs();
logger.debug("Debug mode on"); // static, already made logger. Level did not change

LogManager.getLogger(Main.class).debug("Debug"); // Nope, not printing

Logger root = LogManager.getRootLogger();
root.info("Level: " + root.getLevel());  // Level: INFO, should be DEBUG
实用程序通常在30秒内完成,因此更改应该是即时的。下面是log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level - %msg%n"/>
        </Console>
        <RollingFile name="File" fileName="program_name.log" filePattern="program_name-archived.log">
            <PatternLayout>
                <Pattern>%d{HH:mm:ss.SSS} %-5level - %msg%n</Pattern>
            </PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="10 KB" />
            </Policies>
            <DefaultRolloverStrategy min="1" max="1"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="File"/>
        </Root>
    </Loggers>
</Configuration>

%d{HH:mm:ss.SSS}%-5级-%msg%n

使用AppenderRefs有问题吗?我是否可以告诉Appender从根记录器更新日志记录级别?

要在log4j2初始化后重新配置它,文档提供了两种方法:

  • 使用配置文件,您可以启用自动重新配置(这是首选方式),以便在初始化后修改文件将反映在运行时:
  • 使用ConfigurationBuilder,您可以通过编程方式重新配置log4j(我认为这正是您需要的),请参阅本页的“使用ConfigurationBuilder和Configurator重新配置log4j”一段:

  • 找到了真正的问题。必须使用:

    LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    
    而不是

    LoggerContext ctx = (LoggerContext) LogManager.getContext();
    
    API声明差异为“返回LoggerContext”和“返回当前LoggerContext”。对于没有布尔参数的版本,我显然错过了一些信息:


    “警告-此方法返回的LoggerContext可能不是用于为调用类创建记录器的LoggerContext。”

    除此之外,要调试log4j初始化,请设置
    您可以在两个或多个log4j2.xml文件之间更改日志配置。
    
    例如,创建两个具有不同配置的log4j2.xml文件。log4j2.xml&log4j2-debug.xml并将其传递给下面的代码

    ConfigurationFactory configFactory = XmlConfigurationFactory.getInstance();
                ConfigurationFactory.setConfigurationFactory(configFactory);
                LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
                ClassLoader classloader = Thread.currentThread().getContextClassLoader();
                InputStream inputStream = classloader.getResourceAsStream(logFileName);
                ConfigurationSource configurationSource = new ConfigurationSource(inputStream);
    
                ctx.start(configFactory.getConfiguration(ctx, configurationSource));
    

    这是一个鲜为人知的事实。 如果在log4j2.xml或等效属性中将ROOT_LOGGER级别设置为DEBUG,那么将该级别动态设置为更低的级别对我来说不起作用;换句话说,动态设置没有效果。 只有当我将log4j2.xml中的设置更改为跟踪,然后使用下面的更改日志级别时,它才对我起作用:

        Level level = Level.valueOf(this.consoleLogLevel.toUpperCase());
        //Dynamically set the log level for ALL loggers
        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        Configuration config = ctx.getConfiguration();
        LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
        loggerConfig.setLevel(level);
        ctx.updateLoggers();
    
    这是我的简单配置文件:

    
    
    下面是一个TestNG测试,您可以通过重构来验证上述内容:

     @Test
        public void givenCut_whenLoggingWithERRORLevel_LoggingOutputIsAtERRORLevelAndHigherOnly() {
            try {
                lcaProperties.setLogLevel(Level.ERROR.name());
                GlobalLogger globalLogger = GlobalLogger.builder().lcaServiceProperties(lcaProperties).build();
                assertNotNull(globalLogger.getConsoleLogger());
                assertNotNull(globalLogger.getFunctionalDbLogger());
    
                assertEquals(globalLogger.getConsoleLogger().getLevel(), Level.ERROR);
                assertEquals(log.getLevel(), Level.ERROR);
                System.out.println("log.getLogLevel() = " + log.getLevel());
                System.out.println("globalLogger.getConsoleLogger().getLevel() = " + globalLogger.getConsoleLogger().getLevel());
    
                log.fatal("logLevel::"+log.getLevel()+"::log.fatal");
                log.error("logLevel::"+log.getLevel()+"::log.error");
                log.warn("logLevel::"+log.getLevel()+"::log.warn");
                log.info("logLevel::"+log.getLevel()+"::log.info");
                log.debug("logLevel::"+log.getLevel()+"::log.debug");
                log.trace("logLevel::"+log.getLevel()+"::log.trace");
    
                globalLogger.getConsoleLogger().fatal("logLevel::"+globalLogger.getConsoleLogger().getLevel()+"::globalLogger.getConsoleLogger().fatal");
                globalLogger.getConsoleLogger().error("logLevel::"+globalLogger.getConsoleLogger().getLevel()+"::globalLogger.getConsoleLogger().debug");
                globalLogger.getConsoleLogger().warn("logLevel::"+globalLogger.getConsoleLogger().getLevel()+"::globalLogger.getConsoleLogger().debug");
                globalLogger.getConsoleLogger().info("logLevel::"+globalLogger.getConsoleLogger().getLevel()+"::globalLogger.getConsoleLogger().debug");
                globalLogger.getConsoleLogger().debug("logLevel::"+globalLogger.getConsoleLogger().getLevel()+"::globalLogger.getConsoleLogger().debug");
                globalLogger.getConsoleLogger().trace("logLevel::"+globalLogger.getConsoleLogger().getLevel()+"globalLogger.getConsoleLogger()::log.trace");
    
            } catch (Exception e) {
                fail();
                log.error(e);
            }
        }
    

    请注意,如果您同时使用(监视配置文件和编程更改),自动重新配置可以并且将重置您的编程更改。无论我做什么,我仍然无法使其工作。在我使用
    Configurator.setLevel(logger,level)更改日志级别后,帮助我获得当前配置