X-Ray SDK for Java の設定 - AWS X-Ray

X-Ray SDK for Java の設定

X-Ray SDK for Java には、グローバルレコーダーを提供する AWSXRay というクラスが含まれます。これは、コードの計測に使用できる TracingHandler です。グローバルレコーダーを設定して、受信 HTTP 呼び出しのセグメントを作成する AWSXRayServletFilter をカスタマイズできます。

サービスプラグイン

pluginsを使用して、アプリケーションをホストしているサービスに関する情報を記録します。

プラグイン
  • Amazon EC2 —EC2Pluginは、インスタンス ID、アベイラビリティーゾーン、および CloudWatch Logs グループを追加します。

  • ElasticBeanstalk– ElasticBeanstalkPluginは、環境名、バージョンラベル、およびデプロイ ID を追加します。

  • Amazon ECS — ECSPluginは、コンテナ ID を追加します。

  • Amazon EKS – EKSPlugin は、コンテナ ID、クラスター名、ポッド ID、および CloudWatch Logs グループを追加します。

Amazon EC2 および Elastic Beanstalk プラグインでリソースデータをセグメント化します。

プラグインを使用するには、AWSXRayRecorderBuilderwithPlugin を呼び出します。

例 src/main/java/scorekeep/WebConfig.java - レコーダー
import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.AWSXRayRecorderBuilder; import com.amazonaws.xray.plugins.EC2Plugin; import com.amazonaws.xray.plugins.ElasticBeanstalkPlugin; import com.amazonaws.xray.strategy.sampling.LocalizedSamplingStrategy; @Configuration public class WebConfig { ... static { AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin()).withPlugin(new ElasticBeanstalkPlugin()); URL ruleFile = WebConfig.class.getResource("/sampling-rules.json"); builder.withSamplingStrategy(new LocalizedSamplingStrategy(ruleFile)); AWSXRay.setGlobalRecorder(builder.build()); } }

また、SDK はプラグインの設定を利用して、セグメントの origin フィールドを設定します。これは、アプリケーションを実行する AWS リソースのタイプを示します。複数のプラグインを使用する場合、SDK は次の解決順序を使用して起点を決定します。ElasticBeanStalk > EKS > ECS > EC2。

サンプリングルール

SDK は X-Ray コンソールで定義したサンプリングルールを使用し、記録するリクエストを決定します。デフォルトルールでは、最初のリクエストを毎秒トレースし、X-Ray にトレースを送信するすべてのサービスで追加のリクエストの 5% をトレースします。X-Ray コンソールに追加のルールを作成するをクリックして、各アプリケーションで記録されるデータ量をカスタマイズします。

SDK は、定義された順序でカスタムルールを適用します。リクエストが複数のカスタムルールと一致する場合、SDK は最初のルールのみを適用します。

注記

SDK が X-Ray に到達してサンプリングルールを取得できない場合、1 秒ごとに最初のリクエストのデフォルトのローカルルールに戻り、ホストあたりの追加リクエストの 5% に戻ります。これは、ホストがサンプリング API を呼び出す権限を持っていない場合や、SDK によって行われる API 呼び出しの TCP プロキシとして機能する X-Ray デーモンに接続できない場合に発生します。

JSON ドキュメントからサンプリングルールをロードするように SDK を設定することもできます。SDK は、X-Ray サンプリングが利用できない場合のバックアップとしてローカルルールを使用することも、ローカルルールを排他的に使用することもできます。

例 sampling-rules.json
{ "version": 2, "rules": [ { "description": "Player moves.", "host": "*", "http_method": "*", "url_path": "/api/move/*", "fixed_target": 0, "rate": 0.05 } ], "default": { "fixed_target": 1, "rate": 0.1 } }

この例では、1 つのカスタムルールとデフォルトルールを定義します。カスタムルールでは、5 パーセントのサンプリングレートが適用され、/api/move/以下のパスに対してトレースするリクエストの最小数はありません。デフォルトのルールでは、1秒ごとの最初のリクエストおよび追加リクエストの 10 パーセントをトレースします。

ルールをローカルで定義することの欠点は、固定ターゲットが X-Ray サービスによって管理されるのではなく、レコーダーの各インスタンスによって個別に適用されることです。より多くのホストをデプロイすると、固定レートが乗算され、記録されるデータ量の制御が難しくなります。

AWS Lambdaの場合、サンプリングレートは変更できません。関数がインストルメント化されたサービスによって呼び出された場合、そのサービスによってサンプリングされたリクエストを生成した呼び出しは Lambda によって記録されます。アクティブなトレースが有効で、トレースヘッダーが存在しない場合、Lambda はサンプリングを決定します。

Spring でバックアップルールを提供するには、設定クラスの CentralizedSamplingStrategy にグローバルレコーダーを設定します。

例 src/main/java/myapp/WebConfig.java – レコーダーの設定
import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.AWSXRayRecorderBuilder; import com.amazonaws.xray.javax.servlet.AWSXRayServletFilter; import com.amazonaws.xray.plugins.EC2Plugin; import com.amazonaws.xray.strategy.sampling.LocalizedSamplingStrategy; @Configuration public class WebConfig { static { AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin()); URL ruleFile = WebConfig.class.getResource("/sampling-rules.json"); builder.withSamplingStrategy(new CentralizedSamplingStrategy(ruleFile)); AWSXRay.setGlobalRecorder(builder.build()); }

Tomcat の場合、ServletContextListener を拡張するリスナーを追加し、デプロイ記述子にリスナーを登録します。

例 src/com/myapp/web/Startup.java
import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.AWSXRayRecorderBuilder; import com.amazonaws.xray.plugins.EC2Plugin; import com.amazonaws.xray.strategy.sampling.LocalizedSamplingStrategy; import java.net.URL; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class Startup implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent event) { AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin()); URL ruleFile = Startup.class.getResource("/sampling-rules.json"); builder.withSamplingStrategy(new CentralizedSamplingStrategy(ruleFile)); AWSXRay.setGlobalRecorder(builder.build()); } @Override public void contextDestroyed(ServletContextEvent event) { } }
例 WEB-INF/web.xml
... <listener> <listener-class>com.myapp.web.Startup</listener-class> </listener>

ローカルルールのみを使用するには、CentralizedSamplingStrategyLocalizedSamplingStrategy に置き換えます。

builder.withSamplingStrategy(new LocalizedSamplingStrategy(ruleFile));

ログ記録

デフォルトでは、SDK はアプリケーションログに ERROR-レベルのメッセージを出力します。SDK でデバッグレベルのログを有効にすると、より詳細なログをアプリケーションログファイルに出力できます。有効なログレベルは、DEBUGINFOWARNERRORFATAL です。FATAL ログレベルは、SDK が致命的なレベルでログを記録しないため、すべてのログメッセージを消去します。

例 application.properties

logging.level.com.amazonaws.xray プロパティを使用してログレベルを設定します。

logging.level.com.amazonaws.xray = DEBUG

デバッグログを使用して問題を識別します。たとえば、「サブセグメントを手動で生成する」場合にサブセグメントが閉じない問題などです。

ログへのトレース ID の挿入

ログステートメントに現在の完全修飾トレース ID を公開するには、マップされた診断コンテキスト (MDC) に ID を挿入できます。SegmentListener インターフェイスを使用して、セグメントライフサイクルイベント中に X-Ray レコーダーからメソッドが呼び出されます。セグメントまたはサブセグメントが開始されると、修飾トレース ID がキー AWS-XRAY-TRACE-ID と共に MDC に挿入されます。そのセグメントが終了すると、キーは MDC から削除されます。これにより、トレース ID が使用中のログ記録ライブラリに公開されます。サブセグメントが終了すると、その親 ID が MDC に挿入されます。

例 完全修飾トレース ID

完全修飾 ID は TraceID@EntityID として表されます

1-5df42873-011e96598b447dfca814c156@541b3365be3dafc3

この機能は、AWS X-Ray SDK for Java で測定された Java アプリケーションで動作し、以下のログ作成設定をサポートしています。

  • Logback バックエンドを使用する SLF4J フロントエンド API

  • Log4J2 バックエンドを使用する SLF4J フロントエンド API

  • Log4J2 バックエンドを使用する Log4J2 フロントエンド API

各フロントエンドと各バックエンドのニーズについては、以下のタブを参照してください。

SLF4J Frontend
  1. 以下の Maven 依存関係をプロジェクトに追加します。

    <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-slf4j</artifactId> <version>2.11.0</version> </dependency>
  2. AWSXRayRecorder を構築するときに withSegmentListener メソッドを含めます。これにより、SegmentListener クラスが追加されて、SLF4J MDC に新しいトレース ID が自動的に挿入されるようになります。

    SegmentListener は、ログステートメントのプレフィクスを設定するためのパラメータとしてオプションの文字列を取ります。プレフィクスは、次の方法で設定できます。

    • なし – デフォルトの AWS-XRAY-TRACE-ID プレフィックスを使用します。

    • – 空の文字列を使用します (例:"")。

    • カスタム – 文字列で定義されているカスタムプレフィックスを使用します。

    AWSXRayRecorderBuilder ステートメント
    AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder .standard().withSegmentListener(new SLF4JSegmentListener("CUSTOM-PREFIX"));
Log4J2 front end
  1. 以下の Maven 依存関係をプロジェクトに追加します。

    <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-log4j</artifactId> <version>2.11.0</version> </dependency>
  2. AWSXRayRecorder を構築するときに withSegmentListener メソッドを含めます。これにより、SegmentListener クラスが追加されて、SLF4J MDC に新しい完全修飾トレース ID が自動的に挿入されるようになります。

    SegmentListener は、ログステートメントのプレフィクスを設定するためのパラメータとしてオプションの文字列を取ります。プレフィクスは、次の方法で設定できます。

    • なし – デフォルトの AWS-XRAY-TRACE-ID プレフィックスを使用します。

    • – 空の文字列 (例: "") を使用して、プレフィックスを削除します。

    • カスタム – 文字列で定義されているカスタムプレフィックスを使用します。

    AWSXRayRecorderBuilder ステートメント
    AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder .standard().withSegmentListener(new Log4JSegmentListener("CUSTOM-PREFIX"));
Logback backend

トレース ID をログイベントに挿入するには、各ログ記録ステートメントを書式設定するロガーの PatternLayout を変更する必要があります。

  1. patternLayout が設定されている場所を見つけます。これは、プログラムで行うことも、XML 設定ファイルを使用して行うこともできます。詳細については、「Logback の設定」を参照してください。

  2. 以降のログ記録ステートメントにトレース ID を挿入するには、patternLayout の任意の場所に %X{AWS-XRAY-TRACE-ID} を挿入します。%X{} は、MDC から提供されたキーを使用して値を取得することを示します。Logback の PatternLayouts の詳細については、「PatternLayout」を参照してください。

Log4J2 backend
  1. patternLayout が設定されている場所を見つけます。これは、プログラムで行うことも、XML、JSON、YAML、またはプロパティ形式で記述された設定ファイルを使用して行うこともできます。

    設定ファイルを使用した Log4J2 の設定の詳細については、「設定」を参照してください。

    プログラムによる Log4J2 の設定の詳細については、「プログラムによる設定」を参照してください。

  2. 以降のログ記録ステートメントにトレース ID を挿入するには、PatternLayout の任意の場所に %X{AWS-XRAY-TRACE-ID} を挿入します。%X{} は、MDC から提供されたキーを使用して値を取得することを示します。Log4J2 の PatternLayouts の詳細については、「パターンレイアウト」を参照してください。

トレース ID の挿入の例

以下に示しているのは、トレース ID を含むように変更された PatternLayout 文字列です。トレース ID は、スレッド名 (%t) の後、ログレベル (%-5p) の前に出力されます。

例 ID を挿入した PatternLayout
%d{HH:mm:ss.SSS} [%t] %X{AWS-XRAY-TRACE-ID} %-5p %m%n

AWS X-Ray によって、ログステートメントにキーとトレース ID が自動的に出力されて、解析が容易になります。以下に示しているのは、変更した PatternLayout を使用したログステートメントです。

例 ID を挿入したログステートメント
2019-09-10 18:58:30.844 [nio-5000-exec-4] AWS-XRAY-TRACE-ID: 1-5d77f256-19f12e4eaa02e3f76c78f46a@1ce7df03252d99e1 WARN 1 - Your logging message here

ログメッセージ自体はパターン %m に格納され、ロガーを呼び出すときに設定されます。

セグメントリスナー

セグメントリスナーは、AWSXRayRecorder によって生成されたセグメントの開始と終了などのライフサイクルイベントをインターセプトするためのインターフェイスです。セグメントリスナーイベント関数の実装では、onBeginSubsegment で作成された場合にすべてのサブセグメントに同じ注釈を追加したり、afterEndSegment を使用して各セグメントがデーモンに送信された後にメッセージをログに記録したりします。または、beforeEndSubsegment を使用して SQL インターセプタによって送信されたクエリを記録し、サブセグメントが SQL クエリを表しているかどうかを確認して、そうであればメタデータを追加します。

SegmentListener 関数の完全なリストについては、AWS X-RayRecorder SDK for Java API のドキュメントを参照してください。

次の例は、onBeginSubsegment での作成時にすべてのサブセグメントに一貫性のある注釈を追加し、afterEndSegment を使用して各セグメントの最後にログメッセージを出力する方法を示しています。

例 MySegmentListener.java
import com.amazonaws.xray.entities.Segment; import com.amazonaws.xray.entities.Subsegment; import com.amazonaws.xray.listeners.SegmentListener; public class MySegmentListener implements SegmentListener { ..... @Override public void onBeginSubsegment(Subsegment subsegment) { subsegment.putAnnotation("annotationKey", "annotationValue"); } @Override public void afterEndSegment(Segment segment) { // Be mindful not to mutate the segment logger.info("Segment with ID " + segment.getId()); } }

このカスタムセグメントリスナーは、AWSXRayRecorder を構築するときに参照されます。

例 AWSXRayRecorderBuilder statement
AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder .standard().withSegmentListener(new MySegmentListener());

環境変数

環境変数を使用して、X-Ray SDK for Java を設定できます。SDK は次の変数をサポートしています。

  • AWS_XRAY_CONTEXT_MISSING – 計測されたコードが、セグメントが開いていないときにデータを記録しようとした場合に例外をスローするには、RUNTIME_ERROR に設定します。

    有効な値
    • RUNTIME_ERROR— ランタイム例外をスローします。

    • LOG_ERROR – エラーをログ記録して続行します (デフォルト)。

    • IGNORE_ERROR – エラーを無視して続行します。

    オープン状態のリクエストがない場合、または新しいスレッドを発生させるコードで、スタートアップコードに実装されたクライアントを使用しようとした場合に発生する可能性がある、セグメントまたはサブセグメントの欠落に関連するエラー。

  • AWS_XRAY_DAEMON_ADDRESS – X-Ray デーモンリスナーのホストとポートを設定します。デフォルトでは、SDK はトレースデータ (UDP) とサンプリング (TCP) の両方に127.0.0.1:2000を使用します。この変数は、デーモンを次のように構成している場合に使用します。別のポートでリッスンするまたは、別のホストで実行されている場合。

    [形式]
    • 同じポートaddress:port

    • 異なるポートtcp:address:port udp:address:port

  • AWS_LOG_GROUP - ロググループの名前を、ご使用のアプリケーションに関連付けられたロググループに設定します。ロググループがアプリケーションと同じ AWS アカウントとリージョンを使用している場合、X-Ray はこの指定されたロググループを使用してアプリケーションのセグメントデータを自動的に検索します。ロググループの詳細については、「ロググループとストリームの操作」を参照してください。

  • AWS_XRAY_TRACING_NAME – SDK がセグメントに使用するサービス名を設定します。サーブレットフィルタのセグメント命名ルールで設定したサービス名を上書きします。

環境変数は、同等の「システムプロパティ」と、コードで設定される値を上書きします。

システムプロパティ

システムプロパティは、「環境変数」に代わる JVM 固有の代替的な方法として使用できます。SDK では、以下のプロパティをサポートしています。

  • com.amazonaws.xray.strategy.tracingNameAWS_XRAY_TRACING_NAME と同等です。

  • com.amazonaws.xray.emitters.daemonAddressAWS_XRAY_DAEMON_ADDRESS と同等です。

  • com.amazonaws.xray.strategy.contextMissingStrategyAWS_XRAY_CONTEXT_MISSING と同等です。

環境変数と同等の環境変数のいずれも設定されている場合は、環境変数の値が使用されます。どちらのメソッドでも、コードで設定される値は上書きされます。