繁体   English   中英

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

[英]Log4j2 does not change logging level at runtime

是的,我已阅读所有相关问题。 我正在使用 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>

使用 AppenderRefs 有问题吗? 我可以以某种方式告诉 Appenders 从根记录器更新日志记录级别吗?

发现了真正的问题。 不得不使用:

LoggerContext ctx = (LoggerContext) LogManager.getContext(false);

而不是

LoggerContext ctx = (LoggerContext) LogManager.getContext();

API 说明区别在于“返回 LoggerContext”和“返回当前 LoggerContext”。 我显然错过了没有布尔参数的版本的这一点信息:

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

您可以更改两个或多个 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,文档为您提供了两种方法:

  1. 使用配置文件,您可以启用自动重新配置(这是首选方式),以便在初始化后修改文件将反映在您的运行时: http : //logging.apache.org/log4j/2.x/manual/configuration .html#AutomaticReconfiguration
  2. 使用 ConfigurationBuilder,您可以以编程方式重新配置 log4j(我认为这就是您正在寻找的),请参阅本页的“使用 ConfigurationBuilder 和配置器重新配置 Log4j”段落: http : //logging.apache.org/log4j/2.x/手册/customconfig.html

除了上面的,要调试log4j初始化,在配置文件的开头设置<Configuration status="trace" Log4j2 的内部状态日志将打印到控制台。 这可能有助于故障排除。

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

    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();

这是我的简单配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="TRACE">
            <AppenderRef level="TRACE" ref="Console" />
        </Root>
    </Loggers>
</Configuration>

这是一个 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);
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM