Log4j2のプログラムでログレベルを変更する


108

Log4j2のログレベルをプログラムで変更することに興味があります。私はそれらの設定ドキュメントを見てみましたが、何もないようでした。私もパッケージを調べてみましたorg.apache.logging.log4j.core.configが、そこに役立つものは何もありませんでした。


2
ここで回答が得られない場合は、メーリングリストを試してみてください。一般に、メインの作者が2日に1回調べています。次に戻って、あなた自身の質問に答えてください:-)
tgkprog '

回答:


138

log4j2バージョン2.4 FAQに従って編集

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です。


3
(クラス/パッケージの)特定のロガーだけを変更したい場合は、そのロガー、setLevel、およびupdateLoggersのコンテキストを取得します。
tgkprog 2014年

34
ロギングレベルを設定するだけの複雑な方法。以前のバージョンのlog4jの元の1行ではなく、5行のコードでそれを実行する理由は確かにありますが、私にはそれが表示されません。とにかく、これをありがとう、@ slaadvak!
Sturm

1
.updateLoggers()は必要ないようです。.setLevel()で行われた変更はすぐに適用されるようです。
zbyszek

1
新しいLoggerConfigを追加した場合でも、updateLoggersの呼び出しは常に必要です。UpdateLoggersを使用すると、すべてのロガーがLoggerConfigsに再度関連付けられ、ログレベルを関連するLoggerConfigのログレベルに変更します。新しいLoggerConfigを追加すると、新しいLoggerConfigパターンに一致するすべてのLoggerがリダイレクトされます。ロガーとその構成はLog4j2で分離されているため、「複雑な」方法が必要です。
参加者は2016年

1
:ここではLog4Jのの新しいバージョンの更新、1または2ラインのソリューションを提供して答えであるstackoverflow.com/a/44678752/1339923
Lambart

37

@slaadvakが承認した回答がLog4j2 2.8.2で機能しませんでした。次はしました。

Level 普遍的にログを変更するには:

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

Level現在のクラスのみのログを変更するには、以下を使用します。

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

1
名前を文字列としてハードコーディングするのではなく、ロガー自体からロガー名をプルしたため、私の投票に合格しました。
DWoldrich、

18

単一の特定のロガーレベルを変更する場合(構成ファイルで構成されている1つまたは複数のルートロガーではない)、次のようにできます。

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

3
これは私のロガーにはまったく影響しませんでした。私はsetLevel(logger, Level.ERROR);logger.debugステートメントを使用しましたが、それでも出力されます。マイlog4j2.xmlファイルがであるpastebin.com/fcbV2mTW
ヌーメノン

コードを更新しました。問題がある場合はお知らせください。
イェルク・フリードリヒ

4
log4jの2.7にLoggerContextはないgetConfiguration()メソッドは、参照したlogging.apache.org/log4j/2.x/log4j-api/apidocs/index.html?org/...
maxxyme

log4j-core-2.7.jarには最終的なLoggerContextがあり、それを使用できますctx =(LoggerContext)LogManager.getContext(false); 最終的な構成configuration = ctx.getConfiguration();
jprism 2017

3
これを見た後、私は考えています。「実行時にレベルを変更してほしくないのでしょうか?」
Koray Tugay

13

私はここで良い答えを見つけました:https : //garygregory.wordpress.com/2016/01/11/changing-log-levels-in-log4j2/

org.apache.logging.log4j.core.config.Configuratorを使用して、特定のロガーのレベルを設定できます。

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

2
この回答は、同じ解決策と、ルートロガーに設定する方法を示しています。これは便利な場合もあります。stackoverflow.com
a

4

プログラムによるアプローチはやや煩わしいものです。おそらく、Log4J2によって提供されるJMXサポートを確認する必要があります。

  1. アプリケーションの起動でJMXポートを有効にします。

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

  2. アプリケーションの実行中は、利用可能なJMXクライアント(JVMはJAVA_HOME / bin / jconsole.exeに1つを提供します)のいずれかを使用します。

  3. JConsoleで「org.apache.logging.log4j2.Loggers」Beanを探します

  4. 最後にロガーのレベルを変更します

私がこれのほとんどを気に入っているのは、これを管理するためにコードや構成を変更する必要がないことです。それはすべて外部で透明です。

詳細:http : //logging.apache.org/log4j/2.x/manual/jmx.html


とても助かります、ありがとう!
ダレンパーカー

3

デフォルトの回答のほとんどは、ロギングを追加する必要があると想定しています。しかし、いくつかのパッケージが大量のログを生成していて、その特定のロガーのみのロギングをオフにしたいとします。これは私がそれを機能させるために使用したコードです

    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>

2

私が見つけた珍しい方法の1つは、異なるログレベルで2つの個別のファイルを作成することです。
例えば。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));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.