AWS X-Ray 用の SDK Java - AWS X-Ray

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

AWS X-Ray 用の SDK Java

X-Ray SDK for Java は、トレースデータを生成して X-Ray デーモンに送信するためのクラスとメソッドを提供する Java Web アプリケーション用のライブラリセットです。トレースデータには、アプリケーションが処理した受信 HTTP リクエストや、アプリケーションが AWS SDK、HTTP クライアント、または SQL データベースコネクタを使用してダウンストリームサービスに対して行う呼び出しに関する情報が含まれます。セグメントを手動で作成し、注釈およびメタデータにデバッグ情報を追加することもできます。

X-Ray SDK for Java は、オープンソースプロジェクトです。github.com/aws/ でプロジェクトをフォローし、課題やプルリクエストを送信できます GitHub。aws-xray-sdk-java

受信リクエストのトレースは、AWSXRayServletFilter をサーブレットフィルタとして追加することから開始します。サーブレットフィルタにより、セグメントが作成されます。セグメントが開いている間、SDK クライアントのメソッドを使用してセグメントに情報を追加し、サブセグメントを作成してダウンストリーム呼び出しをトレースできます。また、SDK では、セグメントが開いている間にアプリケーションがスローする例外を自動的に記録します。

リリース 1.3 以降では、Spring のアスペクト指向プログラミング (AOP) を使用してアプリケーションを計測できます。つまり、アプリケーションのランタイムにコードを追加しなくても AWS、実行中でもアプリケーションをインストゥルメントできるということです。

次に、X-Ray SDK for Java を使用して SDK Instrumentor サブモジュールをビルド設定に含めて、 AWS SDK for Java クライアントをインストゥルメントします。 AWS のサービス インストゥルメントされたクライアントを使用してダウンストリームまたはリソースを呼び出すたびに、SDK はその呼び出しに関する情報をサブセグメントに記録します。 AWS のサービス また、サービス内でアクセスするリソースはトレースマップにダウンストリームノードとして表示されるため、個々の接続のエラーやスロットリングの問題を特定するのに役立ちます。

すべてのダウンストリーム呼び出しをインストゥルメントしたくない場合は、Instrumentor サブモジュールを省略して AWS のサービス、インストゥルメントするクライアントを選択できます。SDK TracingHandlerサービスクライアントにを追加して、個々のクライアントをインストゥルメントします。 AWS

その他の X-Ray SDK for Java サブモジュールでは、HTTP ウェブ API および SQL データベースに対するダウンストリーム呼び出しを計測できます。Apache HTTP サブモジュールで X-Ray SDK for Java のバージョン HTTPClient と HTTPClientBuilder を使用する と、Apache HTTP クライアントを計測することができます。SQL クエリの計測には、データソースに SDK のインターセプターを追加します

SDK を使用し始めたら、レコーダーやサーブレットフィルターを設定して、SDK の動作をカスタマイズしてみましょう。プラグインを追加して、アプリケーションを実行しているコンピューティングリソースに関するデータを記録したり、サンプリングルールを定義することでサンプリングの動作のカスタマイズしたり、アプリケーションログに SDK からの情報をより多くあるいは少なく表示するようにログレベルを設定できます。

アプリケーションが注釈やメタデータで行うリクエストや作業に関する追加情報を記録します。注釈は、フィルタ式で使用するためにインデックス化されたシンプルなキーと値のペアで、特定のデータが含まれているトレースを検索できます。メタデータのエントリは制約が緩やかで、JSON にシリアル化できるオブジェクトと配列全体を記録できます。

注釈とメタデータ

注釈およびメタデータとは、X-Ray SDK を使用してセグメントに追加する任意のテキストです。注釈は、フィルタ式用にインデックス付けされます。メタデータはインデックス化されませんが、X-Ray コンソールまたは API を使用して raw セグメントで表示できます。X-Ray への読み取りアクセスを許可した人は誰でも、このデータを表示できます。

コードに多数の計測されたクライアントがある場合、単一のリクエストセグメントには計測されたクライアントで行われた呼び出しごとに 1 個の多数のサブセグメントを含めることができます。カスタムサブセグメントで、クライアント呼び出しをラップすることで、サブセグメントを整理してグループできます。関数全体またはコードの任意のセクションのサブセグメントを作成し、親セグメントにすべてのレコードを記述する代わりにサブセグメントにメタデータと注釈を記録できます。

サブモジュール

X-Ray SDK for Java は、Maven からダウンロードできます。X-Ray SDK for Java は、ユースケースごとにサブモジュールに分割され、部品表のバージョン管理に使用されます。

  • aws-xray-recorder-sdk-core (必須) セグメントを作成して送信するための基本的な機能です。受信リクエストを計測する AWSXRayServletFilter が含まれています。

  • aws-xray-recorder-sdk-aws-sdk— トレーシングクライアントをリクエストハンドラーとして追加して AWS のサービス 、 AWS SDK for Java クライアントとの呼び出しをインストゥルメントします。

  • aws-xray-recorder-sdk-aws-sdk-v2— トレーシングクライアントをリクエストインターレセプターとして追加することで、 AWS SDK for Java 2.2 AWS のサービス 以降のクライアントで作成された呼び出しをインストルメントします。

  • aws-xray-recorder-sdk-aws-sdk-instrumentoraws-xray-recorder-sdk-aws-sdk では、 AWS SDK for Java すべてのクライアントを自動的にインストゥルメントします。

  • aws-xray-recorder-sdk-aws-sdk-v2-instrumentor— を使用するとaws-xray-recorder-sdk-aws-sdk-v2、 AWS SDK for Java 2.2 以降のクライアントをすべて自動的にインストゥルメントします。

  • aws-xray-recorder-sdk-apache-http - Apache HTTP クライアントを使用して行われるアウトバウンド HTTP 呼び出しを計測します。

  • aws-xray-recorder-sdk-spring – Spring AOP Framework アプリケーション用のインターセプターを提供します。

  • aws-xray-recorder-sdk-sql-postgres - JDBC を使用して PostgreSQL データベースに対して行われるアウトバウンド呼び出しを計測します。

  • aws-xray-recorder-sdk-sql-mysql - JDBC を使用して MySQL データベースに対して行われるアウトバウンド呼び出しを計測します。

  • aws-xray-recorder-sdk-bom - すべてのサブモジュールで使用するバージョンを指定するための部品表を提供します。

  • aws-xray-recorder-sdk-metrics— 収集した X-Ray セグメントからサンプリングされていない Amazon CloudWatch メトリクスを公開します。

Maven または Gradle を使用してアプリケーションを構築する場合は、X-Ray SDK for Java をビルド設定に追加します

SDK のクラスとメソッドのリファレンスドキュメントについては、「AWS X-Ray SDK for Java API リファレンス」を参照してください。

要件

X-Ray SDK for Java には Java 8 以降、サーブレット API 3、 AWS SDK、およびジャクソンが必要です。

SDK は、コンパイル時および実行時に次のライブラリに依存します。

  • AWS Javaバージョン 1.11.398 以降の SDK

  • Servlet API 3.1.0

これらの依存関係は SDK の pom.xml ファイルで宣言され、Maven や Gradle を使用して構築すると自動的に含まれます。

X-Ray SDK for Java に含まれているライブラリを使用する場合、同梱されているバージョンを使用する必要があります。たとえば、すでに実行時に Jackson に依存し、その依存関係のためにデプロイメントに JAR ファイルを含めている場合、SDK JAR には Jackson ライブラリの独自のバージョンが含まれているため、その JAR ファイルを削除する必要があります。

依存関係管理

X-Ray SDK for Javaは、Maven から入手できます。

  • グループcom.amazonaws

  • Artifactaws-xray-recorder-sdk-bom

  • バージョン2.11.0

Maven を使用してアプリケーションを構築する場合は、SDK を依存関係として pom.xml ファイルに追加します。

例 pom.xml - 依存関係
<dependencyManagement> <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-bom</artifactId> <version>2.11.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-core</artifactId> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-apache-http</artifactId> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-aws-sdk</artifactId> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-aws-sdk-instrumentor</artifactId> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-sql-postgres</artifactId> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-sql-mysql</artifactId> </dependency> </dependencies>

Gradle の場合は、SDK をコンパイル時の依存関係として build.gradle ファイルに追加します。

例 build.gradle - 依存関係
dependencies { compile("org.springframework.boot:spring-boot-starter-web") testCompile("org.springframework.boot:spring-boot-starter-test") compile("com.amazonaws:aws-java-sdk-dynamodb") compile("com.amazonaws:aws-xray-recorder-sdk-core") compile("com.amazonaws:aws-xray-recorder-sdk-aws-sdk") compile("com.amazonaws:aws-xray-recorder-sdk-aws-sdk-instrumentor") compile("com.amazonaws:aws-xray-recorder-sdk-apache-http") compile("com.amazonaws:aws-xray-recorder-sdk-sql-postgres") compile("com.amazonaws:aws-xray-recorder-sdk-sql-mysql") testCompile("junit:junit:4.11") } dependencyManagement { imports { mavenBom('com.amazonaws:aws-java-sdk-bom:1.11.39') mavenBom('com.amazonaws:aws-xray-recorder-sdk-bom:2.11.0') } }

Elastic Beanstalk を使用してアプリケーションをデプロイする場合、すべての依存関係を含んだ大きなアーカイブを構築してアップロードする代わりに、Maven または Gradle を使用してデプロイするたびにオンインスタンスで構築できます。Gradle の使用例については、サンプルアプリケーションを参照してください。

X-Ray SDK for Java の設定

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

サービスプラグイン

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

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

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

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

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


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

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

例 src/main/java/scorekeep/ .java WebConfig-レコーダー
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 は > EKS > ECS ElasticBeanstalk > 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 にグローバルレコーダーを設定します。

例 WebConfigsrc/main/java/myapp/.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 から提供されたキーを使用して値を取得することを示します。IN 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-Ray Recorder 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 ステートメント
AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder .standard().withSegmentListener(new MySegmentListener());

環境変数

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

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

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

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

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

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

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

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

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

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

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

システムプロパティ

システムプロパティは、「環境変数」に代わる 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 と同等です。

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

X-Ray SDK for Java を使用して受信リクエストをトレースします。

X-Ray SDK を使用して、アプリケーションが Amazon EC2 AWS Elastic Beanstalk、または Amazon ECS の EC2 インスタンス上で処理する受信 HTTP リクエストをトレースできます。

Filter を使用して受信 HTTP リクエストを計測します。X-Ray サーブレットフィルターをアプリケーションに追加すると、X-Ray SDK for Java によってサンプリングされた各リクエストのセグメントが作成されます。このセグメントには、時間、メソッド、HTTP リクエストの処理などが含まれます。追加の計測により、このセグメントでサブセグメントが作成されます。

注記

AWS Lambda 関数の場合、Lambda はサンプリングされたリクエストごとにセグメントを作成します。詳細については、「AWS Lambda および AWS X-Ray」を参照してください。

各セグメントには、サービスマップ内のアプリケーションを識別する名前があります。セグメントの名前は静的に指定することも、受信リクエストのホストヘッダーに基づいて動的に名前を付けるように SDK を設定することもできます。動的ネーミングでは、リクエスト内のドメイン名に基づいてトレースをグループ化でき、名前が予想されるパターンと一致しない場合(たとえば、ホストヘッダーが偽造されている場合)、デフォルト名を適用できます。

転送されたリクエスト

ロードバランサーまたは他の仲介者がアプリケーションにリクエストを転送する場合、X-Ray は、クライアントの IP をIP パケットの送信元 IP からではなく、リクエストのX-Forwarded-Forヘッダーから取得します。転送されたリクエストについて記録されたクライアント IP は偽造される可能性があるため、信頼されるべきではありません。

リクエストが転送されると、それを示す追加フィールドが SDK によってセグメントに設定されます。セグメントのフィールド x_forwarded_fortrue に設定されている場合、クライアント IP が HTTP リクエストの X-Forwarded-For ヘッダーから取得されます。

メッセージハンドラーは、次の情報が含まれる http ブロックを使用して、各受信リクエスト用にセグメントを作成します。

  • HTTP メソッド – GET、POST、PUT、DELETE、その他。

  • クライアントアドレス – リクエストを送信するクライアントの IP アドレス。

  • レスポンスコード – 完了したリクエストの HTTP レスポンスコード。

  • タイミング – 開始時間 (リクエストが受信された時間) および終了時間 (レスポンスが送信された時間)。

  • ユーザーエージェント — リクエストからのuser-agent

  • コンテンツの長さ — レスポンスからのcontent-length

トレースフィルタをアプリケーション (Tomcat) に追加する

Tomcat の場合は、プロジェクトの <filter> ファイルに web.xml を追加します。fixedName パラメーターを使用して、サービス名を指定し、着信リクエスト用に作成されたセグメントに適用します。

例 WEB-INF/web.xml - Tomcat
<filter> <filter-name>AWSXRayServletFilter</filter-name> <filter-class>com.amazonaws.xray.javax.servlet.AWSXRayServletFilter</filter-class> <init-param> <param-name>fixedName</param-name> <param-value>MyApp</param-value> </init-param> </filter> <filter-mapping> <filter-name>AWSXRayServletFilter</filter-name> <url-pattern>*</url-pattern> </filter-mapping>

トレースフィルタをアプリケーション (Spring) に追加する

Spring の場合は、WebConfig クラスに Filter を追加します。セグメント名を文字列として AWSXRayServletFilter コンストラクタに渡します。

例 src/main/java/myapp/.java WebConfig-spring
package myapp; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Bean; import javax.servlet.Filter; import com.amazonaws.xray.javax.servlet.AWSXRayServletFilter; @Configuration public class WebConfig { @Bean public Filter TracingFilter() { return new AWSXRayServletFilter("Scorekeep"); } }

セグメント命名ルールの設定

AWS X-Ray サービス名を使用してアプリケーションを識別し、アプリケーションが使用する他のアプリケーション、データベース、外部 API、リソースと区別します。 AWS X-Ray SDK が受信リクエストのセグメントを生成すると、アプリケーションのサービス名がセグメントの名前フィールドに記録されます。

X-Ray SDK では、HTTP リクエストヘッダーのホスト名の後にセグメントの名前を指定できます。ただし、このヘッダーは偽造され、サービスマップに予期しないノードが発生する可能性があります。偽造されたホストヘッダーを持つリクエストによって SDK がセグメントの名前を間違えないようにするには、受信リクエストのデフォルト名を指定する必要があります。

アプリケーションが複数のドメインのリクエストを処理する場合、動的ネーミングストラテジーを使用してセグメント名にこれを反映するように SDK を設定できます。動的ネーミングストラテジーにより、SDK は予想されるパターンに一致するリクエストにホスト名を使用し、そうでないリクエストにデフォルト名を適用できます。

たとえば、3 つのサブドメイン(www.example.com,api.example.com,およびstatic.example.com)に対してリクエストを処理する単一のアプリケーションがあるとします。動的ネーミングストラテジーをパターン *.example.com で使用して、異なる名前を持つ各サブドメインのセグメントを識別することができます。結果的にはサービスマップ上に 3 つのサービスノードを作成することになります。アプリケーションがパターンと一致しないホスト名のリクエストを受信すると、指定したフォールバック名を持つ 4 番目のノードがサービスマップに表示されます。

すべてのリクエストセグメントに対して同じ名前を使用するには、前のセクションで示すとおり、サーブレットフィルタを初期化するときに、アプリケーションの名前を指定します。これは、SegmentNamingStrategySegmentNamingStrategy.fixed()AWSXRayServletFilterコンストラクターを呼び出してコンストラクターに渡すことで修正コードを作成するのと同じ効果があります。

注記

コードで定義したデフォルトのサービス名は、AWS_XRAY_TRACING_NAME 環境変数で上書きできます。

動的な命名戦略は、ホスト名と一致するようパターンを定義し、HTTP リクエストのホスト名がパターンと一致しない場合はデフォルトの名前を使用します。Tomcat で動的にセグメントに命名するには、dynamicNamingRecognizedHosts および dynamicNamingFallbackName を使用して、パターンとデフォルト名をそれぞれ定義します。

例 WEB-INF/web.xml - 動的名前付けのサーブレットフィルタ
<filter> <filter-name>AWSXRayServletFilter</filter-name> <filter-class>com.amazonaws.xray.javax.servlet.AWSXRayServletFilter</filter-class> <init-param> <param-name>dynamicNamingRecognizedHosts</param-name> <param-value>*.example.com</param-value> </init-param> <init-param> <param-name>dynamicNamingFallbackName</param-name> <param-value>MyApp</param-value> </init-param> </filter> <filter-mapping> <filter-name>AWSXRayServletFilter</filter-name> <url-pattern>*</url-pattern> </filter-mapping>

Spring の場合は、SegmentNamingStrategyを呼び出してダイナミックを作成しSegmentNamingStrategy.dynamic()AWSXRayServletFilterコンストラクターに渡します。

例 src/main/java/myapp/.java-WebConfig 動的命名によるサーブレットフィルター
package myapp; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Bean; import javax.servlet.Filter; import com.amazonaws.xray.javax.servlet.AWSXRayServletFilter; import com.amazonaws.xray.strategy.SegmentNamingStrategy; @Configuration public class WebConfig { @Bean public Filter TracingFilter() { return new AWSXRayServletFilter(SegmentNamingStrategy.dynamic("MyApp", "*.example.com")); } }

Java 用 X-Ray AWS SDK による SDK 呼び出しのトレース

アプリケーションがデータを保存したり、キューに書き込んだり、 AWS のサービス 通知を送信したりするために呼び出しを行うと、X-Ray SDK for Java は下流の呼び出しをサブセグメント単位で追跡します。トレースされたリソース、 AWS のサービス およびそれらのサービス内でアクセスするリソース (Amazon S3 バケットや Amazon SQS キューなど) は、X-Ray コンソールのトレースマップにダウンストリームノードとして表示されます。

aws-sdk および aws-sdk-instrumentor サブモジュールをビルドに含めると、X-Ray SDK for Java では自動的にすべての AWS SDK クライアントを計測します。Instrumentor サブモジュールを含めない場合は、一部のクライアントを計測して他を除外できます。

個々のクライアントを計測するには、aws-sdk-instrumentorビルドからサブモジュールを削除し、サービスのクライアントビルダーを使用して AWS SDK TracingHandler クライアントに XRayClient as a を追加します。

たとえば、AmazonDynamoDB を計測するには、トレースハンドラーを AmazonDynamoDBClientBuilder に渡します。

例 MyModel.java-DynamoDB クライアント
import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.handlers.TracingHandler; ... public class MyModel { private AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard() .withRegion(Regions.fromName(System.getenv("AWS_REGION"))) .withRequestHandlers(new TracingHandler(AWSXRay.getGlobalRecorder())) .build(); ...

すべてのサービスにおいて、X-Ray コンソールでコールされた API の名前を確認できます。サービスのサブセットの場合、X-Ray SDK はセグメントに情報を追加して、サービスマップでより細かく指定します。

たとえば、実装された DynamoDB クライアントでコールすると、SDK はテーブルをターゲットとするコールのセグメントにテーブル名を追加します。コンソールで、各テーブルはサービスマップ内に個別のノードとして表示され、テーブルをターゲットにしないコール用の汎用の DynamoDB ノードが表示されます。

例 項目を保存するための DynamoDB に対するコールのサブセグメント
{ "id": "24756640c0d0978a", "start_time": 1.480305974194E9, "end_time": 1.4803059742E9, "name": "DynamoDB", "namespace": "aws", "http": { "response": { "content_length": 60, "status": 200 } }, "aws": { "table_name": "scorekeep-user", "operation": "UpdateItem", "request_id": "UBQNSO5AEM8T4FDA4RQDEB94OVTDRVV4K4HIRGVJF66Q9ASUAAJG", } }

名前付きリソースにアクセスしたとき、次のサービスをコールすると、サービスマップに追加のノードが作成されます。特定のリソースをターゲットとしないコールでは、サービスの汎用ノードが作成されます。

  • Amazon DynamoDB – テーブル名

  • Amazon Simple Storage Service – バケットとキー名

  • Amazon Simple Queue Service – キュー名

AWS SDK for Java 2.2 AWS のサービス 以降でへのダウンストリーム呼び出しをインストゥルメントするには、aws-xray-recorder-sdk-aws-sdk-v2-instrumentorビルド設定からモジュールを省略できます。その代わりに、aws-xray-recorder-sdk-aws-sdk-v2 module を含め、TracingInterceptor で設定して個々のクライアントを実装します。

例 AWS SDK for Java 2.2 以降-トレースインターセプター
import com.amazonaws.xray.interceptors.TracingInterceptor; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration import software.amazon.awssdk.services.dynamodb.DynamoDbClient; //... public class MyModel { private DynamoDbClient client = DynamoDbClient.builder() .region(Region.US_WEST_2) .overrideConfiguration(ClientOverrideConfiguration.builder() .addExecutionInterceptor(new TracingInterceptor()) .build() ) .build(); //...

X-Ray SDK for Java を使用してダウンストリーム HTTP ウェブサービスの呼び出しをトレースする

アプリケーションがマイクロサービスまたはパブリック HTTP API に呼び出しを実行する場合に、X-Ray SDK for Java の HttpClient バージョンを使用してこれらの呼び出しを計測し、API をダウンストリームサービスとしてサービスグラフに追加できます。

X-Ray SDK for Java にはDefaultHttpClient、発信 HTTP HttpComponents 呼び出しをインストルメントするための Apache HttpClientBuilder の同等のものの代わりに使用できるクラスが含まれています。

  • com.amazonaws.xray.proxies.apache.http.DefaultHttpClient - org.apache.http.impl.client.DefaultHttpClient

  • com.amazonaws.xray.proxies.apache.http.HttpClientBuilder - org.apache.http.impl.client.HttpClientBuilder

これらのライブラリは、aws-xray-recorder-sdk-apache-httpサブモジュールにあります。

既存のインポートステートメントを X-Ray の該当部分に置き換えてすべてのクライアントを計測するか、クライアントを初期化する際に完全修飾名を使用して特定のクライアントを計測できます。

例 HttpClientBuilder
import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; import com.amazonaws.xray.proxies.apache.http.HttpClientBuilder; ... public String randomName() throws IOException { CloseableHttpClient httpclient = HttpClientBuilder.create().build(); HttpGet httpGet = new HttpGet("http://names.example.com/api/"); CloseableHttpResponse response = httpclient.execute(httpGet); try { HttpEntity entity = response.getEntity(); InputStream inputStream = entity.getContent(); ObjectMapper mapper = new ObjectMapper(); Map<String, String> jsonMap = mapper.readValue(inputStream, Map.class); String name = jsonMap.get("name"); EntityUtils.consume(entity); return name; } finally { response.close(); } }

ダウンストリームウェブ API に対する呼び出しを計測すると、X-Ray SDK for Java は HTTP リクエストおよびレスポンスに関する情報を含むセグメントを記録します。X-Ray はサブセグメントを使用してリモート API の推測セグメントを生成します。

例 ダウンストリーム HTTP 呼び出しのサブセグメント
{ "id": "004f72be19cddc2a", "start_time": 1484786387.131, "end_time": 1484786387.501, "name": "names.example.com", "namespace": "remote", "http": { "request": { "method": "GET", "url": "https://names.example.com/" }, "response": { "content_length": -1, "status": 200 } } }
例 ダウンストリーム HTTP 呼び出しの推定セグメント
{ "id": "168416dc2ea97781", "name": "names.example.com", "trace_id": "1-62be1272-1b71c4274f39f122afa64eab", "start_time": 1484786387.131, "end_time": 1484786387.501, "parent_id": "004f72be19cddc2a", "http": { "request": { "method": "GET", "url": "https://names.example.com/" }, "response": { "content_length": -1, "status": 200 } }, "inferred": true }

X-Ray SDK for Java での SQL クエリのトレース

SQL インターセプター

X-Ray SDK for Java JDBC インターセプターをデータソース設定に追加して、SQL データベースのクエリを計測します。

  • PostgreSQLcom.amazonaws.xray.sql.postgres.TracingInterceptor

  • MySQLcom.amazonaws.xray.sql.mysql.TracingInterceptor

これらのインターセプタは、それぞれaws-xray-recorder-sql-postgres と aws-xray-recorder-sql-mysql サブモジュールにあります。 これらは、Tomcat の接続プールと互換性がある org.apache.tomcat.jdbc.pool.JdbcInterceptor を実装します。

注記

SQL インターセプタは、セキュリティ上の目的で SQL クエリ自体をサブセグメント内に記録しません。

Spring の場合は、プロパティファイルのインターセプターを追加し、スプリングブートの DataSourceBuilder を使用して、データソースを構築します。

src/main/java/resources/application.properties - PostgreSQL JDBC Interceptor
spring.datasource.continue-on-error=true spring.jpa.show-sql=false spring.jpa.hibernate.ddl-auto=create-drop spring.datasource.jdbc-interceptors=com.amazonaws.xray.sql.postgres.TracingInterceptor spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL94Dialect
src/main/java/myapp/WebConfig.java - データソース
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import javax.servlet.Filter; import javax.sql.DataSource; import java.net.URL; @Configuration @EnableAutoConfiguration @EnableJpaRepositories("myapp") public class RdsWebConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource dataSource() { logger.info("Initializing PostgreSQL datasource"); return DataSourceBuilder.create() .driverClassName("org.postgresql.Driver") .url("jdbc:postgresql://" + System.getenv("RDS_HOSTNAME") + ":" + System.getenv("RDS_PORT") + "/ebdb") .username(System.getenv("RDS_USERNAME")) .password(System.getenv("RDS_PASSWORD")) .build(); } ... }

Tomcat の場合、X-Ray SDK for Java クラスを参照する JDBC データソースの setJdbcInterceptors を呼び出します。

src/main/myapp/model.java - データソース
import org.apache.tomcat.jdbc.pool.DataSource; ... DataSource source = new DataSource(); source.setUrl(url); source.setUsername(user); source.setPassword(password); source.setDriverClassName("com.mysql.jdbc.Driver"); source.setJdbcInterceptors("com.amazonaws.xray.sql.mysql.TracingInterceptor;");

Tomcat JDBC データソースライブラリは、X-Ray SDK for Java に含まれていますが、使用するドキュメントへの指定された依存関係として宣言できます。

pom.xml - JDBC Data Source
<dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jdbc</artifactId> <version>8.0.36</version> <scope>provided</scope> </dependency>

ネイティブ SQL トレースデコレータ

  • aws-xray-recorder-sdk-sql を依存関係に追加します。

  • データベースのデータソース、接続、またはステートメントを修飾します。

    dataSource = TracingDataSource.decorate(dataSource) connection = TracingConnection.decorate(connection) statement = TracingStatement.decorateStatement(statement) preparedStatement = TracingStatement.decoratePreparedStatement(preparedStatement, sql) callableStatement = TracingStatement.decorateCallableStatement(callableStatement, sql)

X-Ray SDK for Java を使用したカスタムサブセグメントの生成

サブセグメントは、トレースの セグメント をリクエストを処理するために行われた作業の詳細で拡張します。計測済みクライアント内で呼び出しを行うたびに、X-Ray SDK によってサブセグメントに生成された情報が記録されます。追加のサブセグメントを作成して、他のサブセグメントをグループ化したり、コードセクションのパフォーマンスを測定したり、注釈とメタデータを記録したりできます。

サブセグメントを管理するには、beginSubsegment および endSubsegment メソッドを使用します。

例 GameModel.java-カスタムサブセグメント
import com.amazonaws.xray.AWSXRay; ... public void saveGame(Game game) throws SessionNotFoundException { // wrap in subsegment Subsegment subsegment = AWSXRay.beginSubsegment("Save Game"); try { // check session String sessionId = game.getSession(); if (sessionModel.loadSession(sessionId) == null ) { throw new SessionNotFoundException(sessionId); } mapper.save(game); } catch (Exception e) { subsegment.addException(e); throw e; } finally { AWSXRay.endSubsegment(); } }

この例では、サブセグメント内のコードは、セッションモデルのメソッドを使用して DynamoDB からゲームのセッションをロードし、 AWS SDK for Javaの DynamoDB マッパーを使用してゲームを保存します。このコードをサブセグメントにラップすることで、呼び出しが Save Game サブセグメントの DynamoDB の子としてコンソールのトレースビューに表示されます。

サブセグメントのコードがチェック例外をスローした場合は、try ブロックにコードをラップして、finally ブロックで AWSXRay.endSubsegment() を呼び出し、常にサブセグメントが閉じられるようにします。サブセグメントが閉じていない場合は、親セグメントが完了できず、X-Ray に送信されません。

チェック例外をスローしないコードの場合は、コードを Lambda 関数として AWSXRay.CreateSubsegment に渡すことができます。

例 Lambda 関数のサブセグメント
import com.amazonaws.xray.AWSXRay; AWSXRay.createSubsegment("getMovies", (subsegment) -> { // function code });

セグメントまたは別のサブセグメント内にサブセグメントを作成する場合、X-Ray SDK for Java によってその ID が生成され、開始時刻と終了時刻が記録されます。

例 サブセグメントとメタデータ
"subsegments": [{ "id": "6f1605cd8a07cb70", "start_time": 1.480305974194E9, "end_time": 1.4803059742E9, "name": "Custom subsegment for UserModel.saveUser function", "metadata": { "debug": { "test": "Metadata string from UserModel.saveUser" } },

非同期やマルチスレッドのプログラミングでは、非同期実行中に X-Ray コンテキストが変更されることがあるため、サブセグメントを endSubsegment() メソッドに手動で渡して正しく閉じるようにする必要があります。親セグメントが閉じられた後に非同期サブセグメントが閉じられた場合、このメソッドはセグメント全体を X-Ray デーモンに自動的にストリームします。

例 非同期サブセグメント
@GetMapping("/api") public ResponseEntity<?> api() { CompletableFuture.runAsync(() -> { Subsegment subsegment = AWSXRay.beginSubsegment("Async Work"); try { Thread.sleep(3000); } catch (InterruptedException e) { subsegment.addException(e); throw e; } finally { AWSXRay.endSubsegment(subsegment); } }); return ResponseEntity.ok().build(); }

X-Ray SDK for Java を使用してセグメントに注釈とメタデータを追加する

アノテーションとメタデータを使用して、リクエスト、環境、またはアプリケーションに関する追加情報を記録できます。X-Ray SDK が作成するセグメントまたは作成するカスタムサブセグメントに、注釈およびメタデータを追加できます。

注釈は文字列、数値、またはブール値を使用したキーと値のペアです。注釈は、フィルタ式用にインデックス付けされます。注釈を使用して、コンソールでトレースをグループ化するため、またはGetTraceSummaries API を呼び出すときに使用するデータを記録します。

メタデータは、オブジェクトとリストを含む、任意のタイプの値を持つことができるキーバリューのペアですが、フィルタ式に使用するためにインデックスは作成されません。メタデータを使用してトレースに保存する追加のデータを記録しますが、検索で使用する必要はありません。

注釈とメタデータに加えて、セグメントにユーザー ID 文字列を記録することもできます。ユーザー ID はセグメントの個別のフィールドに記録され、検索用にインデックスが作成されます。

X-Ray SDK for Java での注釈の記録

注釈を使用して、検索用にインデックスを作成するセグメントまたはサブセグメントに情報を記録します。

注釈の要件
  • キー — X-Ray アノテーションのキーには、最大 500 文字の英数字を使用できます。アンダースコア記号 (_) 以外のスペースや記号は使用できません。

  • — X-Ray アノテーションの値には、最大 1,000 文字の Unicode 文字を使用できます。

  • 注釈の数 — 1 つのトレース 1 つにつき最大 50 個の注釈を使用できます。

注釈を記録するには
  1. AWSXRay から現在のセグメントまたはサブセグメントの参照を取得します。

    import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Segment; ... Segment document = AWSXRay.getCurrentSegment();

    または

    import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Subsegment; ... Subsegment document = AWSXRay.getCurrentSubsegment();
  2. 文字列キー、および、ブール値、数値、文字列値を使用して putAnnotation を呼び出します。

    document.putAnnotation("mykey", "my value");

SDK は、セグメントドキュメントの annotations オブジェクトにキーと値のペアとして、注釈を記録します。同じキーで putAnnotation を 2 回呼び出すと、同じセグメントまたはサブセグメントに以前記録された値が上書きされます。

特定の値を持つ注釈のあるトレースを見つけるには、annotations.keyフィルタ式 キーワードを使用します。

src/main/java/scorekeep/GameModel.java – 注釈とメタデータ
import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Segment; import com.amazonaws.xray.entities.Subsegment; ... public void saveGame(Game game) throws SessionNotFoundException { // wrap in subsegment Subsegment subsegment = AWSXRay.beginSubsegment("## GameModel.saveGame"); try { // check session String sessionId = game.getSession(); if (sessionModel.loadSession(sessionId) == null ) { throw new SessionNotFoundException(sessionId); } Segment segment = AWSXRay.getCurrentSegment(); subsegment.putMetadata("resources", "game", game); segment.putAnnotation("gameid", game.getId()); mapper.save(game); } catch (Exception e) { subsegment.addException(e); throw e; } finally { AWSXRay.endSubsegment(); } }

X-Ray SDK for Java を使用したメタデータの記録

メタデータを使用して、検索用にインデックスを作成する必要のないセグメントまたはサブセグメントに情報を記録します。メタデータ値は、文字列、数値、ブール値、または JSON オブジェクトや JSON 配列にシリアル化できる任意のオブジェクトになります。

メタデータを記録するには
  1. AWSXRay から現在のセグメントまたはサブセグメントの参照を取得します。

    import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Segment; ... Segment document = AWSXRay.getCurrentSegment();

    または

    import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Subsegment; ... Subsegment document = AWSXRay.getCurrentSubsegment();
  2. 文字列名前空間、文字列キー、ブール値、数値、文字列値、オブジェクト値を使用して putMetadata を呼び出します。

    document.putMetadata("my namespace", "my key", "my value");

    または

    キーと値だけを使用して putMetadata を呼び出します。

    document.putMetadata("my key", "my value");

名前空間を指定しない場合、SDK は default を使用します。同じキーで putMetadata を 2 回呼び出すと、同じセグメントまたはサブセグメントに以前記録された値が上書きされます。

src/main/java/scorekeep/GameModel.java – 注釈とメタデータ
import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Segment; import com.amazonaws.xray.entities.Subsegment; ... public void saveGame(Game game) throws SessionNotFoundException { // wrap in subsegment Subsegment subsegment = AWSXRay.beginSubsegment("## GameModel.saveGame"); try { // check session String sessionId = game.getSession(); if (sessionModel.loadSession(sessionId) == null ) { throw new SessionNotFoundException(sessionId); } Segment segment = AWSXRay.getCurrentSegment(); subsegment.putMetadata("resources", "game", game); segment.putAnnotation("gameid", game.getId()); mapper.save(game); } catch (Exception e) { subsegment.addException(e); throw e; } finally { AWSXRay.endSubsegment(); } }

X-Ray SDK for Javaを使用したユーザー ID の記録

リクエストセグメントにユーザー ID を記録して、リクエストを送信したユーザーを識別します。

ユーザー ID を記録するには
  1. AWSXRay から現在のセグメントへの参照を取得します。

    import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Segment; ... Segment document = AWSXRay.getCurrentSegment();
  2. リクエストを送信したユーザーの文字列 ID を使用して setUser を呼び出します。

    document.setUser("U12345");

コントローラーで setUser を呼び出し、アプリケーションがリクエストの処理を開始するとすぐに、ユーザー ID を記録できます。ユーザー ID を設定するためだけにセグメントを使用する場合、呼び出しを 1 行で連鎖させることができます。

src/main/java/scorekeep/ .java — ユーザー ID MoveController
import com.amazonaws.xray.AWSXRay; ... @RequestMapping(value="/{userId}", method=RequestMethod.POST) public Move newMove(@PathVariable String sessionId, @PathVariable String gameId, @PathVariable String userId, @RequestBody String move) throws SessionNotFoundException, GameNotFoundException, StateNotFoundException, RulesException { AWSXRay.getCurrentSegment().setUser(userId); return moveFactory.newMove(sessionId, gameId, userId, move); }

ユーザー ID のトレースを見つけるには、userフィルタ式で、 キーワードを使用します。

AWS X-Ray Java 用 X-Ray SDK のメトリクス

このトピックでは、 AWS X-Ray 名前空間、指標、ディメンションについて説明します。X-Ray SDK for Java を使用して、収集した X-Ray セグメントからサンプリングされていない Amazon CloudWatch メトリクスを公開できます。これらのメトリクスは、セグメントの開始時間と終了時間、さらにエラー、障害、スロットリングのステータスフラグから取得されます。これらの追跡メトリクスを使用して、サブセグメント内の再試行と依存関係の問題を公開します。

CloudWatch 本質的にはメトリクスリポジトリです。メトリクスは、 CloudWatch 時系列に並んだ一連のデータポイントの基本的な概念であり、それを表します。メトリクスのデータポイントをにパブリッシュ (または AWS のサービス) CloudWatch し、それらのデータポイントに関する統計を順序付けられた時系列データのセットとして取得します。

メトリクスは名前、名前空間、1 つ以上のディメンションで一意に定義されます。各データポイントには、タイムスタンプと、オプションとして測定単位があります。統計を要求した場合、返されるデータストリームは、名前空間、メトリクス名、ディメンションによって識別されます。

詳細については CloudWatch、Amazon CloudWatch ユーザーガイドを参照してください

X-Ray CloudWatch メトリクス

ServiceMetrics/SDK 名前空間には、次のメトリクスが含まれます。

メトリクス 利用可能な統計情報 説明 単位

Latency

Average、Minimum、Maximum、Count

開始時間と終了時間の差。Average、Minimum、Maximum はすべて、オペレーション関連のレイテンシーを表します。Count は、呼び出し数を表します。

ミリ秒

ErrorRate

Average、Sum

4xx Client Error ステータスコードで失敗し、エラーになったリクエストの割合。

割合 (%)

FaultRate

Average、Sum

5xx Server Error ステータスコードで失敗し、障害になったトレースの割合。

割合 (%)

ThrottleRate

Average、Sum

429 ステータスコードを返すスロットリングトレースの割合。これは ErrorRate メトリクスのサブセットです。

割合 (%)

OkRate

Average、Sum

トレースされた後、OK ステータスコードになったリクエストの割合。

割合 (%)

X-Ray CloudWatch 寸法

以下の表のディメンションを使用して、X-Ray によって計測された Java アプリケーションに対して返されるメトリクスを絞り込みます。

ディメンション 説明

ServiceType

不明な場合、サービスのタイプ (AWS::EC2::InstanceNONE など)。

ServiceName

サービスの正規名。

X-Ray CloudWatch メトリックスを有効にする

以下の手順を使用して、計測された Java アプリケーションでトレースメトリクスを有効にします。

トレースメトリクスを設定するには
  1. aws-xray-recorder-sdk-metrics パッケージを Maven 依存関係として追加します。詳細は、X-Ray SDK for Java サブモジュールを参照してください。

  2. グローバルレコーダービルドの一部として新しい MetricsSegmentListener() を有効にします。

    例 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.plugins.ElasticBeanstalkPlugin; import com.amazonaws.xray.strategy.sampling.LocalizedSamplingStrategy; @Configuration public class WebConfig { ... static { AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder .standard() .withPlugin(new EC2Plugin()) .withPlugin(new ElasticBeanstalkPlugin()) .withSegmentListener(new MetricsSegmentListener()); URL ruleFile = WebConfig.class.getResource("/sampling-rules.json"); builder.withSamplingStrategy(new LocalizedSamplingStrategy(ruleFile)); AWSXRay.setGlobalRecorder(builder.build()); } }
  3. Amazon Elastic Compute Cloud (Amazon EC2)、Amazon Elastic Container Service (Amazon ECS)、または Amazon Elastic Kubernetes サービス (Amazon EKS) CloudWatch を使用してメトリクスを収集するエージェントをデプロイします。

  4. エージェントと通信するように SDK を設定します。 CloudWatch デフォルトでは、SDK CloudWatch 127.0.0.1 はアドレスでエージェントと通信します。環境変数または Java プロパティを address:port に設定することで、代替アドレスを設定できます。

    例 環境変数
    AWS_XRAY_METRICS_DAEMON_ADDRESS=address:port
    例 Java のプロパティ
    com.amazonaws.xray.metrics.daemonAddress=address:port
設定を検証するには
  1. AWS Management Console にサインインし、https://console.aws.amazon.com/cloudwatch/ CloudWatch のコンソールを開きます。

  2. [Metrics (メトリクス)] タブを開いて、メトリクスの到着を確認します。

  3. (オプション) CloudWatch コンソールの [Logs] タブで、ServiceMetricsSDKロググループを開きます。ホストメトリクスに一致するログストリームを探し、ログメッセージを確認します。

マルチスレッドアプリケーションでのスレッド間のセグメントコンテキストの受け渡し

アプリケーションで新しいスレッドを作成すると、AWSXRayRecorder は現在のセグメントまたはサブセグメント Entity への参照を保持しません。インストゥルメントされたクライアントを新しいスレッドで使用すると、SDK は存在しないセグメントに書き込もうとするため、が発生します。SegmentNotFoundException

開発中に例外が発生しないようにするには、ContextMissingStrategy代わりにエラーを記録するようにレコーダーに指示するように設定できます。ストラテジーはコード内で設定することもSetContextMissingStrategy環境変数やシステムプロパティを使用して同等のオプションを設定することもできます

エラーに対処する 1 つの方法として、スレッドを開始するときに beginSegment を呼び出して新しいセグメントを使用する方法と、スレッドを終了するときに endSegment を使用する方法があります。 これは、アプリケーションの起動時に実行されるコードのように、HTTP リクエストに応答して実行されないコードを実装する場合に機能します。

複数のスレッドを使用して着信リクエストを処理する場合は、現在のセグメントまたはサブセグメントを新しいスレッドに渡してグローバルレコーダーに渡すことができます。これにより、新しいスレッド内に記録された情報が、そのリクエストに関して記録された残りの情報と同じセグメントに関連付けられることが保証されます。新しいスレッドでセグメントが使用可能になると、そのセグメントのコンテキストにアクセスできる任意の実行可能なファイルを segment.run(() -> { ... }) メソッドで実行できるようになります。

例については、「実装されたクライアントをワーカースレッドで使用する」を参照してください。

非同期プログラミングでの X-Ray の使用

X-Ray SDK for Java は、との非同期 Java プログラムで使用できます。SegmentContextExecutorsは Executor SegmentContextExecutor インターフェースを実装しているため、のすべての非同期操作に渡すことができます。CompletableFutureこれにより、非同期オペレーションがそのコンテキスト内で正しいセグメントで実行されることが保証されます。

例 App.java: への渡し SegmentContextExecutor CompletableFuture
DynamoDbAsyncClient client = DynamoDbAsyncClient.create(); AWSXRay.beginSegment(); // ... client.getItem(request).thenComposeAsync(response -> { // If we did not provide the segment context executor, this request would not be traced correctly. return client.getItem(request2); }, SegmentContextExecutors.newSegmentContextExecutor());

Spring による AOP と X-Ray SDK for Java

このトピックでは、X-Ray SDK および Spring Framework を使用して、コアロジックを変更せずにアプリケーションを計測する方法について説明します。つまり、リモートで実行されているアプリケーションを非侵襲的にインストルメントする方法があるということです。 AWS

Spring の設定

Maven または Gradle を使用して、AOP でアプリケーションを計測するように Spring を設定できます。

Maven を使用してアプリケーションを構築する場合は、次の依存関係を pom.xml ファイルに追加します。

<dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-spring</artifactId> <version>2.11.0</version> </dependency>

Gradle の場合は、次の依存関係を build.gradle ファイルに追加します。

compile 'com.amazonaws:aws-xray-recorder-sdk-spring:2.11.0'

Spring Boot の設定

前のセクションで説明した Spring の依存関係に加えて、Spring Boot を使用している場合で、それがまだクラスパス上にない場合は、次の依存関係を追加します。

Maven:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> <version>2.5.2</version> </dependency>

Gradle:

compile 'org.springframework.boot:spring-boot-starter-aop:2.5.2'

トレースフィルターをアプリケーションに追加する

WebConfig のクラスに Filter を追加します。セグメント名を文字列として AWSXRayServletFilter コンストラクタに渡します。フィルターのトレースおよび受信リクエストの計測の詳細については、「X-Ray SDK for Java を使用して受信リクエストをトレースします。」を参照してください。

例 src/main/java/myapp/.java WebConfig-spring
package myapp; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Bean; import javax.servlet.Filter; import com.amazonaws.xray.javax.servlet.AWSXRayServletFilter; @Configuration public class WebConfig { @Bean public Filter TracingFilter() { return new AWSXRayServletFilter("Scorekeep"); } }

Jakarta のサポート

Spring 6 の Enterprise Edition では、Javax ではなく Jakarta を使用しています。この新しい名前空間をサポートするために、X-Ray では独自の Jakarta 名前空間に存在するクラスの並列セットを作成しました。

フィルタークラスの場合は、javaxjakarta に置き換えてください。セグメント命名ルールを設定するときは、次の例のように、命名ルールクラス名の前に jakarta を追加してください。

package myapp; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Bean; import jakarta.servlet.Filter; import com.amazonaws.xray.jakarta.servlet.AWSXRayServletFilter; import com.amazonaws.xray.strategy.jakarta.SegmentNamingStrategy; @Configuration public class WebConfig { @Bean public Filter TracingFilter() { return new AWSXRayServletFilter(SegmentNamingStrategy.dynamic("Scorekeep")); } }

コードに注釈を付ける、またはインターフェイスを実装する

クラスには @XRayEnabled の注釈を付けるか、XRayTraced インターフェイスを実装する必要があります。これにより、X-Ray の計測のため、影響を受けた関数をラップするように AOP システムに伝えます。

アプリケーションでの X-Ray のアクティベーション

アプリケーションで X-Ray トレースを有効化するには、コードで次のメソッドをオーバーライドして、抽象クラス BaseAbstractXRayInterceptor を拡張する必要があります。

  • generateMetadata—この関数では、現在の関数のトレースにアタッチされたメタデータをカスタマイズできます。デフォルトでは、実行中の関数のクラス名がメタデータに記録されます。追加情報が必要な場合は、さらにデータを追加できます。

  • xrayEnabledClasses—この関数は空であり、空のままにしておく必要があります。これは、ラップするメソッドをインターセプターに指示するポイントカットのホストとして機能します。@XRayEnabled の注釈が付けられたどのクラスをトレースするか指定して、ポイントカットを定義します。次のステートメントは、@XRayEnabled という注釈が付けられたすべてのコントローラービーンをラップするようにインターセプターに伝えます。

    @Pointcut(“@within(com.amazonaws.xray.spring.aop.XRayEnabled) && bean(*Controller)”)

プロジェクトで Spring Data JPA を使用している場合は、BaseAbstractXRayInterceptor ではなく AbstractXRayInterceptor から拡張することを検討してください。

次のコードは、抽象クラス BaseAbstractXRayInterceptorを示しています。

@Aspect @Component public class XRayInspector extends BaseAbstractXRayInterceptor { @Override protected Map<String, Map<String, Object>> generateMetadata(ProceedingJoinPoint proceedingJoinPoint, Subsegment subsegment) throws Exception { return super.generateMetadata(proceedingJoinPoint, subsegment); } @Override @Pointcut("@within(com.amazonaws.xray.spring.aop.XRayEnabled) && bean(*Controller)") public void xrayEnabledClasses() {} }

次のコードは、X-Ray によって計測されるクラスです。

@Service @XRayEnabled public class MyServiceImpl implements MyService { private final MyEntityRepository myEntityRepository; @Autowired public MyServiceImpl(MyEntityRepository myEntityRepository) { this.myEntityRepository = myEntityRepository; } @Transactional(readOnly = true) public List<MyEntity> getMyEntities(){ try(Stream<MyEntity> entityStream = this.myEntityRepository.streamAll()){ return entityStream.sorted().collect(Collectors.toList()); } } }

アプリケーションを正しく設定した場合は、コンソールの次のスクリーンショットに示すように、コントローラーからサービス呼び出しまで、アプリケーションの完全なコールスタックが表示されます。


        完全なコールスタック。