12月19日。 2018 – 4 min read
あるプロジェクトの文脈で、多くのデバッグのケースに直面したことがあります。 ログ内の単純なメッセージでは必ずしも十分ではありません。 たとえば、アクションを実行したユーザーに関するより多くの情報 (彼の IP、彼の権限、彼の識別子、…) が必要な場合があります。 私たちの場合、アプリケーションはいくつかのマイクロサービスから構築されており、あるマイクロサービスから別のマイクロサービスに渡されるリクエストがたどるフローを正確に特定したいと考えました。 この目的のために、一意の識別子が生成され、各Webアプリケーションのログに表示されました。
- どのようにメッセージをログに記録するか。
- どのコンテキスト情報をメッセージに追加するか。
- この情報は、非同期スレッドを実行するときに追加できますか。
この記事では、Spring Boot Java アプリケーションを構築して Log4j でメッセージを記録し、このライブラリの MDC (Mapping Diagnostic Context) を使用して、特に非同期タスクについて、メッセージに加えてコンテキスト データを追加します。
Log4j 内蔵ライブラリでクラシック Spring Boot アプリケーションを生成することから始めてみましょう。 このライブラリにより、さまざまなタイプ (情報、エラー、警告、…)のログメッセージを生成するロガーを使用できます。
- Spring Initializr (https://start.spring.io/) で、依存関係のない基本的な Spring Boot プロジェクトを構築します。このファイルは、将来のログ メッセージの形式を定義します
pom.xml
src/main/resources/log4j2.xml
最初のログ メッセージ
現在の状態では、アプリケーション (IDE などを介してまたは Maven を使用して) を起動するとログ メッセージは何も表示されません。 Log4j ライブラリを使用して、情報メッセージを記録するコンポーネントを作成します。
以下のコードで src/main/java/com/sipios/example/mdc/Execute.java ファイルを作成します。 パッケージ名は com.sipios.example.mdc ですが、もちろんあなたのものに置き換えてください 🙂
src/main/java/com/sipios/example/mdc/Execute.java
もしアプリケーションを実行したら、最初のログメッセージは定義したフォーマットにしたがって表示されていると思われます。 また、error
とwarning
のメソッドを使用することも可能です。 8051>
Use MDC (Mapping Diagnostic Context) in your log
Now that we know how to use the Log4j library, we will be able to use the Mapping Diagnostic Context (MDC) which allows us to associate a data Map with our message.これらのタイプのログ メッセージは、表示されてしまうでしょう。 我々はあなたがMDCに置くことをお勧めしますデータのいくつかの例。
- 現在のセッションのデータ (ユーザー、クエリ、要求 …)
- プロセスの実行に関するメトリック (初期時間と実行時間、…))
- アプリケーションのバージョンに関する情報の断片
- …
このマップは、%X
マスクがLog4jメッセージフォーマットの定義で使用されている場合、ログに表示されます。 これは、私たちのsrc/main/resources/log4j2.xmlファイル内のここでのケースです。 前の実行で、私たちは空のMapを示す{}
を見ます。
MDCを使用することは非常に簡単で、put
, get
, remove
, clear
メソッドを介してクラシックMapのように使用されます…。
src/main/java/com/sipios/example/mdc/Execute.java
MDC はグローバルなので修正しない限り保存されます。 例えばコンポーネントを残して空にしたい場合は、clear
メソッドを使用するだけです。
How does it work with asynchronous components?
MDC を非同期コンポーネント (メイン スレッドの並列スレッドで実行されるコンポーネント) で試してみましょう! まず最初に、そのような Bean を実行するようにアプリケーションを構成する必要があります。 2つのメソッドを持つサービスを作成し、1つは同期、もう1つは非同期です。
- Application クラスに @EnableAsync アノテーションを追加する
- Async と通常のメソッドを持つサービスを作成する
- サービスのメソッドを注入して使用するようにコンポーネントを変更する
- アプリケーションを起動する
src/main/java/com/sipios/example/mdc/Application.Application を作成する。java
src/main/java/com/sipios/example/mdc/service/Example.java
src/main/java/com/sipios/example/mdc/Execute.java.Java
src/java/com/sapios/midc/mdc/example/Execute.java
Add taskExecutor in Application class
src/main/java/com/sipios/example/mdc/Application.java
再起動 :
ご覧のように非同期スレッドのMDCは空になりました。 実際、各非同期タスクは新しいスレッドで開始されます。 各スレッドはタスク実行者によって開始されたMap MDCにリンクされています。 メインスレッドと同じ MDC を得るために、このエグゼキュータ上でプレイすることが可能です。 MDCを複製するために、asyncExecutorにデコレーターを追加してみましょう!
src/main/java/com/sipios/example/mdc/ExampleTaskDecorator.Script.Script.Script.Script.Script.Script.Script.Script.Script.Script.Script.Script.Script.Script.Script.Script.Script.Script.java
Set this decorator in async config
src/main/java/com/sipios/example/mdc/Application.java
Relaunch application
There is you go ! 同期または非同期タスクで必要なすべてのコンテキストをログで伝えることができます。
このおかげで、アプリケーションのデバッグは単純化され、より理解しやすくなりました。 私たちのプロジェクトの一部として、これは貢献者との交換で多くの時間を節約しました。 あとはあなた次第です 🙂
Bibliography
- http://www.baeldung.com/mdc-in-log4j-2-logback
- https://spring.io/guides/gs/async-method/
- https://moelholm.com/2017/07/24/spring-4-3-using-a-taskdecorator-to-copy-mdc-data-to-async-threads/
のようになります。