簡體   English   中英

以編程方式更改 Log4j2 中的日志級別

[英]Programmatically change log level in Log4j2

我對以編程方式更改 Log4j2 中的日志級別感興趣。 我嘗試查看他們的 配置文檔,但似乎沒有任何內容。 我還嘗試查看包: org.apache.logging.log4j.core.config ,但其中的任何內容看起來也沒有幫助。

簡單的方法:

根據 log4j2 2.4 版常見問題進行編輯

您可以使用 Log4j Core 中的 Configurator 類設置記錄器的級別。 但請注意,Configurator 類不是公共 API 的一部分。

// org.apache.logging.log4j.core.config.Configurator;
Configurator.setLevel("com.example.Foo", Level.DEBUG);

// You can also set the root logger:
Configurator.setRootLevel(Level.DEBUG);

來源

優選方式:

編輯以反映 Log4j2 版本 2.0.2 中引入的 API 中的更改

如果您想更改根記錄器級別,請執行以下操作:

LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME); 
loggerConfig.setLevel(level);
ctx.updateLoggers();  // This causes all Loggers to refetch information from their LoggerConfig.

是 LoggerConfig 的 javadoc。

@slaadvak 接受的答案不適用於Log4j2 2.8.2 以下做到了。

要更改日志Level普遍使用:

Configurator.setAllLevels(LogManager.getRootLogger().getName(), level);

要僅更改當前類的日志Level ,請使用:

Configurator.setLevel(LogManager.getLogger(CallingClass.class).getName(), level);

如果要更改單個特定記錄器級別(不是配置文件中配置的根記錄器或記錄器),您可以執行以下操作:

public static void setLevel(Logger logger, Level level) {
    final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    final Configuration config = ctx.getConfiguration();

    LoggerConfig loggerConfig = config.getLoggerConfig(logger.getName());
    LoggerConfig specificConfig = loggerConfig;

    // We need a specific configuration for this logger,
    // otherwise we would change the level of all other loggers
    // having the original configuration as parent as well

    if (!loggerConfig.getName().equals(logger.getName())) {
        specificConfig = new LoggerConfig(logger.getName(), level, true);
        specificConfig.setParent(loggerConfig);
        config.addLogger(logger.getName(), specificConfig);
    }
    specificConfig.setLevel(level);
    ctx.updateLoggers();
}

我在這里找到了一個很好的答案: https : //garygregory.wordpress.com/2016/01/11/changed-log-levels-in-log4j2/

您可以使用 org.apache.logging.log4j.core.config.Configurator 來設置特定記錄器的級別。

Logger logger = LogManager.getLogger(Test.class);
Configurator.setLevel(logger.getName(), Level.DEBUG);

程序化方法相當具有侵入性。 也許您應該檢查 Log4J2 提供的 JMX 支持:

  1. 在應用程序啟動時啟用 JMX 端口:

    -Dcom.sun.management.jmxremote.port=[port_num]

  2. 在執行應用程序時使用任何可用的 JMX 客戶端(JVM 在 JAVA_HOME/bin/jconsole.exe 中提供了一個)。

  3. 在 JConsole 中查找“org.apache.logging.log4j2.Loggers”bean

  4. 最后更改記錄器的級別

我最喜歡的一點是您不必修改代碼或配置來管理它。 這一切都是外部的和透明的。

更多信息: http : //logging.apache.org/log4j/2.x/manual/jmx.html

默認情況下,大多數答案都假定日志記錄必須是附加的。 但是假設某個包正在生成大量日志,並且您只想關閉該特定記錄器的日志記錄。 這是我用來讓它工作的代碼

    public class LogConfigManager {

    public void setLogLevel(String loggerName, String level) {
        Level newLevel = Level.valueOf(level);
        LoggerContext logContext = (LoggerContext) LogManager.getContext(false);
        Configuration configuration = logContext.getConfiguration();
        LoggerConfig loggerConfig = configuration.getLoggerConfig(loggerName);
        // getLoggerConfig("a.b.c") could return logger for "a.b" if there is no logger for "a.b.c"
        if (loggerConfig.getName().equalsIgnoreCase(loggerName)) {
            loggerConfig.setLevel(newLevel);
            log.info("Changed logger level for {} to {} ", loggerName, newLevel);
        } else {
            // create a new config.
            loggerConfig = new LoggerConfig(loggerName, newLevel, false);
            log.info("Adding config for: {} with level: {}", loggerConfig, newLevel);
            configuration.addLogger(loggerName, loggerConfig);


            LoggerConfig parentConfig = loggerConfig.getParent();
            do {
                for (Map.Entry<String, Appender> entry : parentConfig.getAppenders().entrySet()) {
                    loggerConfig.addAppender(entry.getValue(), null, null);
                }
                parentConfig = parentConfig.getParent();
            } while (null != parentConfig && parentConfig.isAdditive());
        }
        logContext.updateLoggers();
    }
}

相同的測試用例

public class LogConfigManagerTest {
    @Test
    public void testLogChange() throws IOException {
        LogConfigManager logConfigManager = new LogConfigManager();
        File file = new File("logs/server.log");
        Files.write(file.toPath(), new byte[0], StandardOpenOption.TRUNCATE_EXISTING);
        Logger logger = LoggerFactory.getLogger("a.b.c");
        logger.debug("Marvel-1");
        logConfigManager.setLogLevel("a.b.c", "debug");
        logger.debug("DC-1");
        // Parent logger level should remain same
        LoggerFactory.getLogger("a.b").debug("Marvel-2");
        logConfigManager.setLogLevel("a.b.c", "info");
        logger.debug("Marvel-3");
        // Flush everything
        LogManager.shutdown();

        String content = Files.readAllLines(file.toPath()).stream().reduce((s1, s2) -> s1 + "\t" + s2).orElse(null);
        Assert.assertEquals(content, "DC-1");
    }
}

假設以下 log4j2.xml 在類路徑中

<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config">

    <Appenders>
        <File name="FILE" fileName="logs/server.log" append="true">
            <PatternLayout pattern="%m%n"/>
        </File>
        <Console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout pattern="%m%n"/>
        </Console>
    </Appenders>

    <Loggers>
        <AsyncLogger name="a.b" level="info">
            <AppenderRef ref="STDOUT"/>
            <AppenderRef ref="FILE"/>
        </AsyncLogger>

        <AsyncRoot level="info">
            <AppenderRef ref="STDOUT"/>
        </AsyncRoot>
    </Loggers>

</Configuration>

我發現的一種不尋常的方法是創建兩個具有不同日志記錄級別的單獨文件。
例如。 log4j2.xml 和 log4j-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));

對於那些仍在為此苦苦掙扎的人,我不得不將類加載器添加到“getContext()”調用中:

  log.info("Modifying Log level! (maybe)");
  LoggerContext ctx = (LoggerContext) LogManager.getContext(this.getClass().getClassLoader(), false);
  Configuration config = ctx.getConfiguration();
  LoggerConfig loggerConfig = config.getLoggerConfig("com.cat.barrel");
  loggerConfig.setLevel(org.apache.logging.log4j.Level.TRACE);
  ctx.updateLoggers();

我在測試中添加了一個 jvm 參數: -Dlog4j.debug 這會為 log4j 做一些詳細的日志記錄。 我注意到最終的 LogManager 不是我使用的那個。 Bam,添加類加載器,您就可以開始比賽了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM