log4jログレベルの動的な変更


127

アプリケーションを再デプロイする必要がないように、log4jログレベルを動的に変更するためのさまざまなアプローチは何ですか。これらの場合、変更は永続的ですか?




3
log4j2のための更新質問:stackoverflow.com/questions/23434252/...
slaadvak

1
このページの(ほとんど)すべてがlog4jに関するものであり、log4j2に関するものではないことに注意してください。このページ全体が混乱と誤解に満ちているので、無用です。@slaadvakの推奨に従って、stackoverflow.com / questions / 23434252 /…にアクセスします。
ランバート

回答:


86

ログレベルの変更は簡単です。構成の他の部分を変更すると、より詳細なアプローチがもたらされます。

LogManager.getRootLogger().setLevel(Level.DEBUG);

変更は、のライフサイクルを通じて永続的Loggerです。再初期化時に、実行時にレベルの設定がレベルの変更を保持しないため、構成が読み取られて使用されます。

更新: Log4j 2を使用している場合はsetLevelドキュメントごとにへの呼び出しを削除する必要があります。これは、実装クラスを介して実現できるためです。

logger.setLevel()または同様のメソッドの呼び出しは、APIではサポートされていません。アプリケーションはこれらを削除する必要があります。同等の機能がLog4j 2実装クラスで提供されますが、アプリケーションがLog4j 2内部の変更の影響を受けやすくなる可能性があります。


5
ランタイム依存関係のみLogManager.getLogger(Class.forName("org.hibernate.util.JDBCExceptionReporter")).setLevel(Level.FATAL);
CelinHC '16

8
log4j 2 APIは「setLevel」メソッドを提供しないことに注意してください。
ChrisCantrell 2013年

5
しかし、これはルートロガーを設定するだけですよね?ルート下のロガーに個別のレベルが設定されている場合、ルートロガーを設定しても、それらのロガーには影響しません。root.getLoggerRepository()。getCurrentCategories()のようなものを実行し、ロガーの各インスタンスを反復処理し、各ロガーにLEVELSを設定する必要があるのではないでしょうか。@AaronMcIver
TheMonkWhoSoldHisCode 14

8
@ChrisCantrell Log4j 2 は、これを行う方法を提供しますが、それほど単純ではありません。
CorayThan 2014

2
Log4j2は、log4j2.xmlファイル(または同等のファイル)を一定の間隔でスキャンすることにより、その構成を更新するように構成できます。例<Configuration status = "warn" monitorInterval = "5" name = "tryItApp" packages = "">
キンボールロビンソン

89

ファイルウォッチドッグ

Log4jはlog4j.xml、構成の変更についてファイルを監視できます。log4jファイルを変更すると、log4jは変更に応じてログレベルを自動的に更新します。詳細については、org.apache.log4j.xml.DOMConfigurator.configureAndWatch(String,long)のドキュメントを参照してください。チェック間のデフォルトの待機時間は60秒です。ファイルシステム上の構成ファイルを直接変更するため、これらの変更は永続的です。DOMConfigurator.configureAndWatch()を1回呼び出すだけで済みます。

注意:configureAndWatchメソッドは、スレッドリークのため、J2EE環境での使用は安全ではありません。

JMX

ログレベルを設定する(または一般的に再構成する)log4jのもう1つの方法は、JMXを使用することです。Log4jは、ロガーをJMX MBeanとして登録します。アプリケーションサーバーのMBeanServerコンソール(またはJDKのjconsole.exe)を使用して、個々のロガーを再構成できます。これらの変更は永続的ではなく、アプリケーション(サーバー)を再起動した後、構成ファイルで設定された構成にリセットされます。

自作

Aaronによって説明されているように、ログレベルをプログラムで設定できます。あなたはそれをあなたが望むようにあなたのアプリケーションに実装することができます。たとえば、ユーザーまたは管理者がログレベルを変更setLevel()して、ロガーのメソッドを呼び出すGUIを作成できます。どこかに設定を保持するかどうかはあなた次第です。


8
log4jウォッチドッグアプローチに関する注意事項:「configureAndWatchは別のウォッチドッグスレッドを起動するため、このスレッドをlog4j 1.2で停止する方法がないため、configureAndWatchメソッドは、アプリケーションがリサイクルされるJ2EE環境での使用には安全ではありません。」参照:Log4J FAQ
Somu

Log4jのconfigureAndWatch機能を使用する場合、EJBの@PostDestroyメソッドでそのウォッチドッグスレッドを停止できます(これは、コンテナーがシャットダウンするときを示す十分な指標です)それだけですか?それとも私が見逃していることはもっとあります。
robin bajaj 2013

申し訳ありませんが、@ PreDestroyメソッド
robin bajaj

Log4jは、ロガーをJMX MBeanとして登録します。」私のサーブレットはlog4j 1.2を使用しています。log4jMBeanが表示されません。
Abdull

DOMConfigurator.configureAndWatch()を1回呼び出すだけで済みます。どうすればこれを達成できますか?
gstackoverflow

5

log4j2は、log4j 2 .xmlファイル(または同等のファイル)を一定の間隔でスキャンすることにより、その構成を更新するように構成できます。「monitorInterval」パラメーターを構成タグに追加するだけです。サンプルのlog4j 2 .xmlファイルの2行目を参照してください。これは、最後のログイベントから5秒以上経過した場合に、設定を再スキャンするようにlog4jに指示します。

<?xml version="1.0" encoding="UTF-8" ?>
<Configuration status="warn" monitorInterval="5" name="tryItApp" packages="">

    <Appenders>
        <RollingFile name="MY_TRY_IT"
                     fileName="/var/log/tryIt.log"
                     filePattern="/var/log/tryIt-%i.log.gz">
            <Policies>
                <SizeBasedTriggeringPolicy size="25 MB"/>
            </Policies>
            ...
        </RollingFile>
    </Appenders>


    <Loggers>
        <Root level="error">
            <AppenderRef ref="MY_TRY_IT"/>
        </Root>
    </Loggers>

</Configuration>

Tomcatインスタンスにデプロイする場合、IDE内、またはSpring Bootを使用する場合に、これを機能させるための追加の手順があります。これは、ここではやや範囲外と思われ、おそらく別の質問に値するでしょう。


@ vsingh、Spring Boot、Tomcat、またはコンテナーの内部にデプロイしていますか、それともIDEを使用していますか?これらの場合、追加の手順が発生することがあります(log4j2の障害ではありません)。基本的に、フレームワークまたはツールによって別の場所にコピーされているため、アプリはファイルの変更を認識できません。
キンボールロビンソン

こんにちは私はJboss6.4でこれをテストし、アプリがファイルを見ることができる場所(.warファイル内)でlog4j2設定ファイルを更新しました。ただし、それでも機能しませんでした。なにか提案を?
MidTierDeveloper

3

この回答は、ロギングレベルを動的に変更するのに役立ちません。サービスを再起動する必要があります。サービスを正常に再起動している場合は、以下の解決策を使用してください

私はこれをlog4jログレベルを変更するために行いました。それは私にとってはうまくいきました、私はどのドキュメントも参照していません。このシステムプロパティ値を使用して、ログファイル名を設定しました。同じテクニックを使用してログレベルも設定しましたが、うまくいきました

これをJVMパラメータとして渡しました(私はJava 1.7を使用しています)

申し訳ありませんが、これは動的にログレベルを変更しません。サービスの再起動が必要です

java -Dlogging.level=DEBUG -cp xxxxxx.jar  xxxxx.java

log4j.propertiesファイルに、このエントリを追加しました

log4j.rootLogger=${logging.level},file,stdout

私は試した

 java -Dlogging.level=DEBUG -cp xxxxxx.jar  xxxxx.java
 java -Dlogging.level=INFO-cp xxxxxx.jar  xxxxx.java
 java -Dlogging.level=OFF -cp xxxxxx.jar  xxxxx.java

それはすべてうまくいった。お役に立てれば!

私のpom.xmlに次の依存関係があります

<dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
</dependency>

<dependency>
    <groupId>log4j</groupId>
    <artifactId>apache-log4j-extras</artifactId>
    <version>1.2.17</version>
</dependency>

2
あなたが言ったことは何でも問題ないようですが、問題はログレベルを動的に変更することです。
Azim 2016

これを行うには、サービスを再起動する必要があります。これにより、ロギングレベルが動的に変更されることはありません。
kk。

2

log4j 1.xでは、DOMConfiguratorを使用して、事前定義されたXMLログ構成のセットの1つ(たとえば、通常の使用とデバッグの1つ)を送信するのが最善の方法です。

これらを利用するには、次のような方法があります。

  public static void reconfigurePredefined(String newLoggerConfigName) {
    String name = newLoggerConfigName.toLowerCase();
    if ("default".equals(name)) {
      name = "log4j.xml";
    } else {
      name = "log4j-" + name + ".xml";
    }

    if (Log4jReconfigurator.class.getResource("/" + name) != null) {
      String logConfigPath = Log4jReconfigurator.class.getResource("/" + name).getPath();
      logger.warn("Using log4j configuration: " + logConfigPath);
      try (InputStream defaultIs = Log4jReconfigurator.class.getResourceAsStream("/" + name)) {
        new DOMConfigurator().doConfigure(defaultIs, LogManager.getLoggerRepository());
      } catch (IOException e) {
        logger.error("Failed to reconfigure log4j configuration, could not find file " + logConfigPath + " on the classpath", e);
      } catch (FactoryConfigurationError e) {
        logger.error("Failed to reconfigure log4j configuration, could not load file " + logConfigPath, e);
      }
    } else {
      logger.error("Could not find log4j configuration file " + name + ".xml on classpath");
    }
  }

適切な構成名でこれを呼び出し、テンプレートをクラスパスに置くことを確認してください。


このメソッドのトリガーポイントは何ですか?log4j構成に変更があった場合にこのメソッドを呼び出す必要があることをどのようにして知るのでしょうか。
2016年

「オンデマンド」という意味がまだわかりません。このメソッドを接続するスニペットを見せていただけますか?
asgs

2
どうぞ:これは、私たちが使用するコントローラーからのスニペットです。動的にログを再構成するためのいくつかのリンクを含む管理ページがあり、それによりリンク/ admin / setLogLevel?level = ErrorへのGETが行われ、 次に @RequestMapping(value = "setLogLevel"、method = RequestMethod.GET)public ModelAndView setLogLevel(@RequestParam(value = "level"、required = true)String level){Log4jReconfigurator.reconfigureExisting(level);
ISparkes

つまり、私の場合、「オンデマンド」とは「ユーザーがボタンをクリックしたとき」を意味します
ISparkes

ああ、わかった。したがって、管理コンソールはこのメソッドを呼び出すリクエストを行う必要があります。
asgs

0

私はこの方法を使用して「org.apache.http」ログの冗長性を減らすことに成功しました:

ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("org.apache.http");
logger.setLevel(Level.TRACE);
logger.setAdditive(false);


-1

すべてのロガーのログレベルを変更する場合は、以下の方法を使用します。これにより、すべてのロガーが列挙され、ロギングレベルが指定されたレベルに変更されます。あなたがいることを確認してくださいしないでください持っているlog4j.appender.loggerName.Threshold=DEBUGあなたの中にプロパティセットlog4j.propertiesファイルを。

public static void changeLogLevel(Level level) {
    Enumeration<?> loggers = LogManager.getCurrentLoggers();
    while(loggers.hasMoreElements()) {
        Logger logger = (Logger) loggers.nextElement();
        logger.setLevel(level);
    }
}

-3

次のコードスニペットを使用できます

((ch.qos.logback.classic.Logger)LoggerFactory.getLogger(packageName)).setLevel(ch.qos.logback.classic.Level.toLevel(logLevel));

私はそれを試さなければなりません。
user2045474 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.