OpenTelemetry Java への移行 - AWS X-Ray

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

OpenTelemetry Java への移行

このセクションでは、X-Ray SDK から OpenTelemetry SDK for Java アプリケーションへの移行に関するガイダンスを提供します。

ゼロコード自動計測ソリューション

With X-Ray Java agent

X-Ray Java エージェントを有効にするには、アプリケーションの JVM 引数を変更する必要があります。

-javaagent:/path-to-disco/disco-java-agent.jar=pluginPath=/path-to-disco/disco-plugins
With OpenTelemetry-based Java agent

OpenTelemetry ベースの Java エージェントを使用するには。

  • AWS Distro for OpenTelemetry (ADOT) Auto-Instrumentation Java エージェントを使用して、ADOT Java エージェントによる自動計測を行います。詳細については、「Java エージェントを使用したトレースとメトリクスの自動計測」を参照してください。トレースのみが必要な場合は、 OTEL_METRICS_EXPORTER=none 環境変数を無効にします。 は Java エージェントからメトリクスをエクスポートします。

    (オプション) ADOT Java 自動計測 AWS を使用して でアプリケーションを自動的に計測するときに CloudWatch Application Signals を有効にして、現在のアプリケーションの状態をモニタリングし、長期的なアプリケーションパフォーマンスを追跡することもできます。Application Signals は、アプリケーション、サービス、依存関係の統合されたアプリケーション中心のビューを提供し、アプリケーションのヘルスをモニタリングおよびトリアージするのに役立ちます。詳細については、「Application Signals」を参照してください。

  • 自動計測には OpenTelemetry Java エージェントを使用します。詳細については、「Java エージェントによるゼロコード計測」を参照してください。

SDK を使用した手動計測ソリューション

Tracing setup with X-Ray SDK

X-Ray SDK for Java を使用してコードを計測するには、まず AWSXRay クラスをサービスプラグインとローカルサンプリングルールで設定する必要があり、次に提供されたレコーダーが使用されました。

static { AWS XRayRecorderBuilder builder = AWS XRayRecorderBuilder.standard().withPlugin(new EC2Plugin()).withPlugin(new ECSPlugin()); AWS XRay.setGlobalRecorder(builder.build()); }
Tracing setup with OpenTelemetry SDK

次の依存関係が必要です。

<dependencyManagement> <dependencies> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-bom</artifactId> <version>1.49.0</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-instrumentation-bom</artifactId> <version>2.15.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-sdk</artifactId> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-api</artifactId> </dependency> <dependency> <groupId>io.opentelemetry.semconv</groupId> <artifactId>opentelemetry-semconv</artifactId> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-exporter-otlp</artifactId> </dependency> <dependency> <groupId>io.opentelemetry.contrib</groupId> <artifactId>opentelemetry-aws-xray</artifactId> <version>1.46.0</version> </dependency> <dependency> <groupId>io.opentelemetry.contrib</groupId> <artifactId>opentelemetry-aws-xray-propagator</artifactId> <version>1.46.0-alpha</version> </dependency> <dependency> <groupId>io.opentelemetry.contrib</groupId> <artifactId>opentelemetry-aws-resources</artifactId> <version>1.46.0-alpha</version> </dependency> </dependencies>

をインスタンス化し、OpenTelemetrySdkオブジェクトをTracerProviderグローバルに登録して、OpenTelemetry SDK を設定します。これらのコンポーネントを設定します。

  • OTLP Span Exporter (OtlpGrpcSpanExporter など) - CloudWatch エージェントまたは OpenTelemetry Collector にトレースをエクスポートするために必要です

  • AWS X-Ray プロパゲーター – X-Ray と統合された AWS サービスにトレースコンテキストを伝達するために必要です

  • AWS X-Ray リモートサンプラー – X-Ray サンプリングルールを使用してリクエストをサンプリングする必要がある場合に必要です

  • Resource Detectors (EcsResource や Ec2Resource など) – アプリケーションを実行しているホストのメタデータを検出する

    import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.propagation.ContextPropagators; import io.opentelemetry.contrib.aws.resource.Ec2Resource; import io.opentelemetry.contrib.aws.resource.EcsResource; import io.opentelemetry.contrib.awsxray.AwsXrayRemoteSampler; import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; import io.opentelemetry.sdk.trace.samplers.Sampler; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; // ... private static final Resource otelResource = Resource.create(Attributes.of(SERVICE_NAME, "YOUR_SERVICE_NAME")) .merge(EcsResource.get()) .merge(Ec2Resource.get()); private static final SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() .addSpanProcessor(BatchSpanProcessor.create( OtlpGrpcSpanExporter.getDefault() )) .addResource(otelResource) .setSampler(Sampler.parentBased( AwsXrayRemoteSampler.newBuilder(otelResource).build() )) .build(); // Globally registering a TracerProvider makes it available throughout the application to create as many Tracers as needed. private static final OpenTelemetrySdk openTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(sdkTracerProvider) .setPropagators(ContextPropagators.create(AwsXrayPropagator.getInstance())) .buildAndRegisterGlobal();

受信リクエストのトレース (スプリングフレームワークの計測)

With X-Ray SDK

Spring フレームワークで X-Ray SDK を使用してアプリケーションを計測する方法については、「Spring での AOP」と「X-Ray SDK for Java」を参照してください。Spring で AOP を有効にするには、以下の手順を実行します。

With OpenTelemetry SDK

OpenTelemetry は、Spring Boot アプリケーションの受信リクエストのトレースを収集するための計測ライブラリを提供します。最小限の設定で Spring Boot 計測を有効にするには、次の依存関係を含めます。

<dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-spring-boot-starter</artifactId> </dependency>

OpenTelemetry のセットアップで Spring Boot 計測を有効にして設定する方法の詳細については、OpenTelemetry の開始方法」を参照してください。

Using OpenTelemetry-based Java agents

Spring Boot アプリケーションを計測するためのデフォルトの推奨方法は、OpenTelemetry Java エージェントバイトコード計測を使用することです。これにより、SDK を直接使用するよりもout-of-the-box使用できる計測と設定も増えます。開始方法については、「」を参照してくださいゼロコード自動計測ソリューション

AWS SDK v2 計測

With X-Ray SDK

X-Ray SDK for Java は、ビルドにaws-xray-recorder-sdk-aws-sdk-v2-instrumentorサブモジュールを追加したときに、すべての AWS SDK v2 クライアントを自動的に計測できます。

AWS SDK for Java 2.2 以降 AWS で個々のクライアントのダウンストリームクライアント呼び出しを計測するために、ビルド設定の aws-xray-recorder-sdk-aws-sdk-v2-instrumentor モジュールが除外され、 aws-xray-recorder-sdk-aws-sdk-v2モジュールが含まれていました。個々のクライアントは、 で設定することで計測されましたTracingInterceptor

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(); //...
With OpenTelemetry SDK

すべての AWS SDK クライアントを自動的に計測するには、 opentelemetry-aws-sdk-2.2-autoconfigureサブモジュールを追加します。

<dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-aws-sdk-2.2-autoconfigure</artifactId> <version>2.15.0-alpha</version> <scope>runtime</scope> </dependency>

個々の AWS SDK クライアントを計測するには、 opentelemetry-aws-sdk-2.2サブモジュールを追加します。

<dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-aws-sdk-2.2</artifactId> <version>2.15.0-alpha</version> <scope>compile</scope> </dependency>

次に、 AWS SDK クライアントを作成するときにインターセプターを登録します。

import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; // ... AwsSdkTelemetry telemetry = AwsSdkTelemetry.create(openTelemetry); private final S3Client S3_CLIENT = S3Client.builder() .overrideConfiguration(ClientOverrideConfiguration.builder() .addExecutionInterceptor(telemetry.newExecutionInterceptor()) .build()) .build();

送信 HTTP 呼び出しの計測

With X-Ray SDK

X-Ray を使用して送信 HTTP リクエストを計測するには、X-Ray SDK for Java のバージョンの Apache HttpClient が必要です。

import com.amazonaws.xray.proxies.apache.http.HttpClientBuilder; ... public String randomName() throws IOException { CloseableHttpClient httpclient = HttpClientBuilder.create().build();
With OpenTelemetry SDK

X-Ray Java SDK と同様に、OpenTelemetry は、Apache HttpClient に OpenTelemetry ベースのスパンとコンテキスト伝達を提供する HttpClientBuilder のインスタンスの作成を許可するビルダーメソッドを持つ ApacheHttpClientTelemetry クラスを提供します。

<dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-apache-httpclient-5.2</artifactId> <version>2.15.0-alpha</version> <scope>compile</scope> </dependency>

opentelemetry-java-instrumentation のコード例を次に示します。newHttpClient() によって提供される HTTP クライアントは、実行されたリクエストのトレースを生成します。

import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.apachehttpclient.v5_2.ApacheHttpClientTelemetry; import org.apache.hc.client5.http.classic.HttpClient; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; public class ApacheHttpClientConfiguration { private OpenTelemetry openTelemetry; public ApacheHttpClientConfiguration(OpenTelemetry openTelemetry) { this.openTelemetry = openTelemetry; } // creates a new http client builder for constructing http clients with open telemetry instrumentation public HttpClientBuilder createBuilder() { return ApacheHttpClientTelemetry.builder(openTelemetry).build().newHttpClientBuilder(); } // creates a new http client with open telemetry instrumentation public HttpClient newHttpClient() { return ApacheHttpClientTelemetry.builder(openTelemetry).build().newHttpClient(); } }

他のライブラリの計測サポート

OpenTelemetry Java でサポートされているライブラリ計測の完全なリストは、サポートされているライブラリ、フレームワーク、アプリケーションサーバー、および JVMs の下にある、それぞれの計測 GitHub リポジトリ にあります。

または、OpenTelemetry Registry を検索して、OpenTelemetry が計測をサポートしているかどうかを調べることもできます。検索を開始するには、「レジストリ」を参照してください。

トレースデータを手動で作成する

With X-Ray SDK

X-Ray SDK では、X-Ray セグメントbeginSegmentとサブセグメントを手動で作成するには、 メソッドと beginSubsegmentメソッドが必要です。

Segment segment = xrayRecorder.beginSegment("ManualSegment"); segment.putAnnotation("annotationKey", "annotationValue"); segment.putMetadata("metadataKey", "metadataValue"); try { Subsegment subsegment = xrayRecorder.beginSubsegment("ManualSubsegment"); subsegment.putAnnotation("key", "value"); // Do something here } catch (Exception e) { subsegment.addException(e); } finally { xrayRecorder.endSegment(); }
With OpenTelemetry SDK

カスタムスパンを使用して、計測ライブラリでキャプチャされない内部アクティビティのパフォーマンスをモニタリングできます。スパンの種類サーバーのみが X-Ray セグメントに変換され、他のすべてのスパンは X-Ray サブセグメントに変換されることに注意してください。

まず、 openTelemetry.getTracerメソッドで取得できるスパンを生成するには、トレーサーを作成する必要があります。これにより、このSDK を使用した手動計測ソリューション例でグローバルに登録TracerProviderされた の Tracer インスタンスが提供されます。必要に応じていくつでも Tracer インスタンスを作成できますが、アプリケーション全体に 1 つの Tracer を持つのが一般的です。

Tracer tracer = openTelemetry.getTracer("my-app");

Tracer を使用してスパンを作成できます。

import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.Scope; ... // SERVER span will become an X-Ray segment Span span = tracer.spanBuilder("get-token") .setKind(SpanKind.SERVER) .setAttribute("key", "value") .startSpan(); try (Scope ignored = span.makeCurrent()) { span.setAttribute("metadataKey", "metadataValue"); span.setAttribute("annotationKey", "annotationValue"); // The following ensures that "annotationKey: annotationValue" is an annotation in X-Ray raw data. span.setAttribute(AttributeKey.stringArrayKey("aws.xray.annotations"), List.of("annotationKey")); // Do something here } span.end();

スパンのデフォルトタイプは INTERNAL です。

// Default span of type INTERNAL will become an X-Ray subsegment Span span = tracer.spanBuilder("process-header") .startSpan(); try (Scope ignored = span.makeCurrent()) { doProcessHeader(); }

OpenTelemetry SDK を使用してトレースに注釈とメタデータを追加する

上記の例では、 setAttributeメソッドを使用して各スパンに属性を追加します。デフォルトでは、すべてのスパン属性は X-Ray raw データ内のメタデータに変換されます。属性がメタデータではなく注釈に変換されるように、上記の例では、その属性のキーをaws.xray.annotations属性のリストに追加します。詳細については、「カスタマイズされた X-Ray 注釈と注釈とメタデータを有効にする」を参照してください。 https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-annotations

OpenTelemetry ベースの Java エージェントを使用

Java エージェントを使用してアプリケーションを自動的に計測する場合は、アプリケーションで手動計測を実行する必要があります。たとえば、自動計測ライブラリでカバーされていないセクションのコードをアプリケーション内で計測するには。

エージェントで手動計測を実行するには、 opentelemetry-api アーティファクトを使用する必要があります。アーティファクトバージョンをエージェントバージョンより新しいものにすることはできません。

import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.trace.Span; // ... Span parentSpan = Span.current(); Tracer tracer = GlobalOpenTelemetry.getTracer("my-app"); Span span = tracer.spanBuilder("my-span-name") .setParent(io.opentelemetry.context.Context.current().with(parentSpan)) .startSpan(); span.end();

Lambda 計測

With X-Ray SDK

X-Ray SDK を使用すると、Lambda でアクティブトレースを有効にした後、X-Ray SDK を使用するための追加の設定は必要ありません。Lambda は Lambda ハンドラー呼び出しを表すセグメントを作成し、追加の設定なしで X-Ray SDK を使用してサブセグメントまたは計測ライブラリを作成できます。

With OpenTelemetry-based solutions

自動計測 Lambda レイヤー – 次のソリューションを使用して AWS 、販売された Lambda レイヤーを使用して Lambda を自動的に計測できます。

  • CloudWatch Application Signals Lambda レイヤー (推奨)

    注記

    この Lambda レイヤーでは、デフォルトで CloudWatch Application Signals が有効になっているため、メトリクスとトレースの両方を収集することで、Lambda アプリケーションのパフォーマンスとヘルスのモニタリングが可能になります。トレースのみの場合は、Lambda 環境変数 を設定します OTEL_AWS_APPLICATION_SIGNALS_ENABLED=false

    • Lambda アプリケーションのパフォーマンスとヘルスのモニタリングを有効にします

    • デフォルトでは、メトリクスとトレースの両方を収集します

  • AWS ADOT Java 用の マネージド Lambda レイヤー。詳細については、AWS 「 Distro for OpenTelemetry Lambda Support for Java」を参照してください。

自動計測レイヤーとともに手動計測を使用するには、「」を参照してくださいSDK を使用した手動計測ソリューション。コールドスタートを減らすには、OpenTelemetry 手動計測を使用して Lambda 関数の OpenTelemetry トレースを生成することを検討してください。

AWS Lambda の OpenTelemetry 手動計測

Amazon S3 ListBuckets 呼び出しを行う次の Lambda 関数コードを検討してください。

package example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.ListBucketsRequest; import software.amazon.awssdk.services.s3.model.ListBucketsResponse; import software.amazon.awssdk.services.s3.model.S3Exception; public class ListBucketsLambda implements RequestHandler<String, String> { private final S3Client S3_CLIENT = S3Client.builder() .build(); @Override public String handleRequest(String input, Context context) { try { ListBucketsResponse response = makeListBucketsCall(); context.getLogger().log("response: " + response.toString()); return "Success"; } catch (Exception e) { throw new RuntimeException(e); } } private ListBucketsResponse makeListBucketsCall() { try { ListBucketsRequest listBucketsRequest = ListBucketsRequest.builder() .build(); ListBucketsResponse response = S3_CLIENT.listBuckets(listBucketsRequest); return response; } catch (S3Exception e) { throw new RuntimeException("Failed to call S3 listBuckets" + e.awsErrorDetails().errorMessage(), e); } } }

依存関係は次のとおりです。

dependencies { implementation('com.amazonaws:aws-lambda-java-core:1.2.3') implementation('software.amazon.awssdk:s3:2.28.29') implementation('org.slf4j:slf4j-nop:2.0.16') }

Lambda ハンドラーと Amazon S3 クライアントを手動で計測するには、次の手順を実行します。

  1. RequestHandlerまたは RequestStreamHandler) を実装する関数クラスを、拡張する関数クラス TracingRequestHandler (または TracingRequestStreamHandler) に置き換えます。

  2. TracerProvider をインスタンス化し、OpenTelemetrySdk オブジェクトをグローバルに登録します。TracerProvider は、以下を使用して設定することをお勧めします。

    1. Lambda の UDP X-Ray エンドポイントにトレースを送信するための X-Ray UDP スパンエクスポーターを備えたシンプルなスパンプロセッサ

    2. ParentBased always on sampler (設定されていない場合はデフォルト)

    3. service.name が Lambda 関数名に設定されているリソース

    4. X-Ray Lambda プロパゲータ

  3. handleRequest メソッドを に変更doHandleRequestし、OpenTelemetrySdkオブジェクトをベースクラスに渡します。

  4. クライアントの構築時にインターセプターを登録して、OpenTemetry AWS SDK 計測を使用して Amazon S3 クライアントを計測します。

以下の OpenTelemetry 関連の依存関係が必要です。

dependencies { ... implementation("software.amazon.distro.opentelemetry:aws-distro-opentelemetry-xray-udp-span-exporter:0.1.0") implementation(platform('io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom:2.14.0')) implementation(platform('io.opentelemetry:opentelemetry-bom:1.48.0')) implementation('io.opentelemetry:opentelemetry-sdk') implementation('io.opentelemetry:opentelemetry-api') implementation('io.opentelemetry.contrib:opentelemetry-aws-xray-propagator:1.45.0-alpha') implementation('io.opentelemetry.contrib:opentelemetry-aws-resources:1.45.0-alpha') implementation('io.opentelemetry.instrumentation:opentelemetry-aws-lambda-core-1.0:2.14.0-alpha') implementation('io.opentelemetry.instrumentation:opentelemetry-aws-sdk-2.2:2.14.0-alpha') }

次のコードは、必要な変更後の Lambda 関数を示しています。追加のカスタムスパンを作成して、自動的に提供されるスパンを補完できます。

package example; import java.time.Duration; import com.amazonaws.services.lambda.runtime.Context; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.propagation.ContextPropagators; import io.opentelemetry.contrib.aws.resource.LambdaResource; import io.opentelemetry.contrib.awsxray.propagator.AwsXrayLambdaPropagator; import io.opentelemetry.instrumentation.awslambdacore.v1_0.TracingRequestHandler; import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; import io.opentelemetry.sdk.trace.samplers.Sampler; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.ListBucketsRequest; import software.amazon.awssdk.services.s3.model.ListBucketsResponse; import software.amazon.awssdk.services.s3.model.S3Exception; import software.amazon.distro.opentelemetry.exporter.xray.udp.trace.AwsXrayUdpSpanExporterBuilder; public class ListBucketsLambda extends TracingRequestHandler<String, String> { private static final Resource lambdaResource = LambdaResource.get(); private static final SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() .addSpanProcessor(SimpleSpanProcessor.create( new AwsXrayUdpSpanExporterBuilder().build() )) .addResource( lambdaResource .merge(Resource.create(Attributes.of(SERVICE_NAME, System.getenv("AWS_LAMBDA_FUNCTION_NAME")))) ) .setSampler(Sampler.parentBased(Sampler.alwaysOn())) .build(); private static final OpenTelemetrySdk openTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(sdkTracerProvider) .setPropagators(ContextPropagators.create(AwsXrayLambdaPropagator.getInstance())) .buildAndRegisterGlobal(); private static final AwsSdkTelemetry telemetry = AwsSdkTelemetry.create(openTelemetry); private final S3Client S3_CLIENT = S3Client.builder() .overrideConfiguration(ClientOverrideConfiguration.builder() .addExecutionInterceptor(telemetry.newExecutionInterceptor()) .build()) .build(); public ListBucketsLambda() { super(openTelemetry, Duration.ofMillis(0)); } @Override public String doHandleRequest(String input, Context context) { try { ListBucketsResponse response = makeListBucketsCall(); context.getLogger().log("response: " + response.toString()); return "Success"; } catch (Exception e) { throw new RuntimeException(e); } } private ListBucketsResponse makeListBucketsCall() { try { ListBucketsRequest listBucketsRequest = ListBucketsRequest.builder() .build(); ListBucketsResponse response = S3_CLIENT.listBuckets(listBucketsRequest); return response; } catch (S3Exception e) { throw new RuntimeException("Failed to call S3 listBuckets" + e.awsErrorDetails().errorMessage(), e); } } }

Lambda 関数を呼び出すと、CloudWatch コンソールのトレースマップの下に次のトレースが表示されます。

CloudWatch コンソールのトレースマップ。