4

log4jを使用して、サーブレットベースのJavaアプリからログを記録しようとしています。ユーザー ID などの追加情報をログに記録したいのですが、ローカル変数をスレッドに入れる方法はありますか? ロギング中に現在のスレッドを取得し、設定されたローカル変数を取得することは可能ですか?

4

4 に答える 4

8

スレッド ローカル ストレージを直接使用するのではなく、Log4j のNDCMDC (ネストされマップされた診断コンテキスト) を使用します。これらはすでにスレッド ローカルであり、%xおよび%Xパターンを使用してログ メッセージにデータを含めることができるため、データをスレッド ローカル コンテキストから明示的に引き出してログ メッセージに含める必要はありません。

于 2013-08-05T13:12:33.860 に答える
6

Log4J MDC アプローチ

これはMDCでそれを行う方法です

public class MdcExample implements Runnable {
    private static final Logger logger  = Logger.getLogger(MdcExample.class);

    public static void main(final String[] args) {
        final MdcExample threadLocalExample = new MdcExample();

        final Thread thread1 = new Thread(threadLocalExample);
        final Thread thread2 = new Thread(threadLocalExample);
        final Thread thread3 = new Thread(threadLocalExample);

        thread1.start(); thread2.start(); thread3.start();
    }

    @Override
    public void run() {

        while (true) {
            MDC.put("random", "" + Math.random());

            try {
                logger.info("My log message, prefixed with MDC");
                TimeUnit.SECONDS.sleep(1);
            }
            catch (final InterruptedException e) {
            }
        }
    }
}

Log4J 設定:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

    <!-- Appenders -->
    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p %X{random}:- %m%n" />
        </layout>
    </appender> 

    <!-- Root Logger -->
    <root>
        <priority value="info" />
        <appender-ref ref="console" />
        <appender-ref ref="file" />
    </root>

</log4j:configuration>

スレッド ローカル アプローチ (ビジネスロジックで必要な場合)

値 (ユーザーなど) をスレッドにローカルに保存する場合は、次を使用しますThreadLocal

import java.util.concurrent.TimeUnit;

public class ThreadLocalExample implements Runnable {
    ThreadLocal<Double> myRandom    = new ThreadLocal<>();

    public static void main(final String[] args) {
        final ThreadLocalExample threadLocalExample = new ThreadLocalExample();

        final Thread thread1 = new Thread(threadLocalExample);
        final Thread thread2 = new Thread(threadLocalExample);
        final Thread thread3 = new Thread(threadLocalExample);

        thread1.start(); thread2.start(); thread3.start();
    }

    @Override
    public void run() {

        this.myRandom.set(Math.random());

        while (true) {
            System.out.println(Thread.currentThread().getId() + " " + this.myRandom.get());

            try {
                TimeUnit.SECONDS.sleep(1);
            }
            catch (final InterruptedException e) {
            }
        }
    }
}

http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html

スレッド ID を log4j 出力に追加する

tlog4j の質問に関しては、スレッド名に th -Placeholder を使用できます。

これは、使用できるアペンダーの例です。

<appender name="console" class="org.apache.log4j.ConsoleAppender">
    <param name="Target" value="System.out" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%5p %d{ISO8601} [%t][%x] %c - %m%n" />
    </layout>
</appender>

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html

于 2013-08-05T13:08:36.990 に答える
3

ThreadLocal行く方法です。ThreadLocalスレッド間で共有されず、スレッドの存続期間を通じて使用できる変数を保存する機能を提供します。

ThreadLocalこの機能の性質上、同期ブロックを取り除くのに役立ちます。

于 2013-08-05T13:11:42.830 に答える
0

これにはMDCを使用する必要があります。名前付きプロパティを保存して、ログ形式で直接参照できます。Log4j の NDC 機能と MDC 機能の違いは何ですか? を参照してください。たとえば。

于 2013-08-05T13:13:57.233 に答える