Java 以编程方式更改 Log4j2 中的日志级别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23434252/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 22:59:28  来源:igfitidea点击:

Programmatically change log level in Log4j2

javalog4j2

提问by CorayThan

I'm interested in programmatically changing the log level in Log4j2. I tried looking at their configuration documentationbut that didn't seem to have anything. I also tried looking in the package: org.apache.logging.log4j.core.config, but nothing in there looked helpful either.

我对以编程方式更改 Log4j2 中的日志级别感兴趣。我尝试查看他们的配置文档,但似乎没有任何内容。我也尝试查看 package: org.apache.logging.log4j.core.config,但里面也没有任何东西看起来有帮助。

采纳答案by slaadvak

EDITED according to log4j2 version 2.4 FAQ

根据 log4j2 2.4 版常见问题进行编辑

You can set a logger's level with the class Configurator from Log4j Core. BUTbe aware that the Configurator class is not part of the public API.

您可以使用 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);

Source

来源

EDITED to reflect changes in the API introduced in Log4j2 version 2.0.2

编辑以反映 Log4j2 版本 2.0.2 中引入的 API 中的更改

If you wish to change the root logger level, do something like this :

如果您想更改根记录器级别,请执行以下操作:

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.

Hereis the javadoc for LoggerConfig.

是 LoggerConfig 的 javadoc。

回答by Victor

The programmatic approach is rather intrusive. Perhaps you should check JMX support given by Log4J2:

程序化方法相当具有侵入性。也许您应该检查 Log4J2 提供的 JMX 支持:

  1. Enable the JMX port in your application start up:

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

  2. Use any of the available JMX clients (the JVM provides one in JAVA_HOME/bin/jconsole.exe) while executing your application.

  3. In JConsole look for the "org.apache.logging.log4j2.Loggers" bean

  4. Finally change the level of your logger

  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. 最后更改记录器的级别

The thing that I like most of this is that you don′t have to modify your code or configuration for managing this. It′s all external and transparent.

我最喜欢的一点是你不必修改你的代码或配置来管理它。这一切都是外在的和透明的。

More info: http://logging.apache.org/log4j/2.x/manual/jmx.html

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

回答by J?rg Friedrich

If you want to change a single specific logger level (not the root logger or loggers configured in the configuration file) you can do this:

如果要更改单个特定记录器级别(而不是配置文件中配置的根记录器或记录器),您可以执行以下操作:

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

回答by alfred.schalk

I found a good answer here: https://garygregory.wordpress.com/2016/01/11/changing-log-levels-in-log4j2/

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

You can use org.apache.logging.log4j.core.config.Configurator to set the level for a specific logger.

您可以使用 org.apache.logging.log4j.core.config.Configurator 来设置特定记录器的级别。

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

回答by 4myle

The accepted answer by @slaadvak did not work for me for Log4j2 2.8.2. The following did.

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

To change the log Leveluniversallyuse:

Level普遍更改日志,请使用:

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

To change the log Levelfor only the current class, use:

Level仅更改当前类的日志,请使用:

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

回答by dpp.2325

One un-usual way i found to do is to create two separate file with different logging level.
For example. log4j2.xml and log4j-debug.xml Now change the configuration from this files.
Sample Code:

我发现的一种不寻常的方法是创建两个具有不同日志记录级别的单独文件。
例如。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));

回答by hobgoblin

Most of the answers by default assume that logging has to be additive. But say that some package is generating lot of logs and you want to turn off logging for that particular logger only. Here is the code that I used to get it working

默认情况下,大多数答案都假定日志记录必须是附加的。但是假设某个包正在生成大量日志,并且您只想关闭该特定记录器的日志记录。这是我用来让它工作的代码

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

A test case for the same

相同的测试用例

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");
    }
}

Assuming following log4j2.xml is in classpath

假设以下 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>