22

Spring ベースの Java Web アプリケーションを作成しました。

リクエストごとに、リクエストを処理するために「コントローラ クラス」のインスタンスが作成されます。

ビジネスロジックでは、プログラムが正確に何をしたかを追跡できるように、各リクエストに自動的に割り当てられたUNIQUE IDでログを記録したいと考えています。

ログは次のようになります (同時に 2 つの要求)。

[INFO] request #XXX: begin.
[INFO] request #XXX: did step 1
[INFO] request #YYY: begin.
[INFO] request #XXX: did step 2
[INFO] request #YYY: did step 1
[INFO] request #XXX: end.
[INFO] request #YYY: end.

ログから、次のことがわかります: req #XXX: begin-step1-step2-end req #YYY: begin-step1-end

ロギングがコードのどこでも簡単に呼び出せることを願っているので、すべての Java 関数に「requestId」のパラメーターを追加したくありません。

ロギング ツールを静的な方法で呼び出すことができれば完璧です。

LOG.doLog("did step 1");

どうすればこれを行うことができますか?ありがとうございました :)

4

6 に答える 6

36

Log4j のMDCクラスを使用することもできます。MDC はスレッドごとに管理されます。ServletRequestListner を使用している場合は、requestInitialized で一意の ID を設定できます。

import org.apache.log4j.MDC;
import java.util.UUID;

public class TestRequestListener implements ServletRequestListener {    
protected static final Logger LOGGER = LoggerFactory.getLogger(TestRequestListener.class);

 public void requestInitialized(ServletRequestEvent arg0) {
    LOGGER.debug("++++++++++++ REQUEST INITIALIZED +++++++++++++++++");

    MDC.put("RequestId", UUID.randomUUID());

 }

 public void requestDestroyed(ServletRequestEvent arg0) {
    LOGGER.debug("-------------REQUEST DESTROYED ------------");
    MDC.clear(); 
 }
}

デバッグ、警告、またはエラーのいずれかをログに記録すると、コードのどこにでも表示されます。MDC に入力したものはすべて印刷されます。log4j.properties を構成する必要があります。%X{RequestId} に注意してください。これは、上記の requestInitialized() に挿入されたキー名を参照します。

log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSSS} %p %C %X{RequestId} - %m%n

このリンクも役立つことがわかりました-> Log4jのNDCとMDC機能の違いは何ですか?

于 2014-08-18T20:51:20.220 に答える
26

次の 3 つの異なる問題を解決する必要があります。

  1. リクエストごとに一意の ID を生成する
  2. ID を保存し、コード内のどこからでもアクセスできます
  3. ID を自動的に記録する

このアプローチをお勧めします

  1. サーブレット フィルターまたはServletRequestListener (M. Deinum の提案による) またはSpring Handler Interceptorを使用して、一般的な方法でリクエストをインターセプトします。UUID を使用して一意の ID を作成できます。

  2. id をリクエストの属性として保存できます。この場合、id はサービスではなく、コントローラー レイヤーでのみ伝達されます。そのため、 ThreadLocal変数を使用するか、Spring に RequestContextHolder で魔法を行うように依頼て問題を解決できます。 RequestContextHolder を使用すると、サービス層でその特定のスレッドのリクエストとリクエスト属性にもアクセスできます。RequestContextHolder は ThreadLocal 変数を使用してリクエストを保存します。次の方法でリクエストにアクセスできます。

    ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
    // Extract the request
    HttpServletRequest request = attr.getRequest();
    
  3. log4j を使用している場合、ロガーのパターン レイアウトのカスタマイズに関する興味深い記事( 2018 代替) があります。ただし、ログ システム インターフェイスのプロキシを作成し、ログに記録されたすべての文字列に ID を手動で追加するだけです。

于 2013-09-16T08:45:51.217 に答える