遷移至 OpenTelemetry Java - AWS X-Ray

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

遷移至 OpenTelemetry Java

本節提供從 X-Ray 開發套件遷移至適用於 Java 的 OpenTelemetry 開發套件應用程式的指引。

零程式碼自動檢測解決方案

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 代理程式匯出指標。

    (選用) 您也可以 AWS 在使用 ADOT Java 自動檢測功能自動檢測應用程式時啟用 CloudWatch Application Signals,以監控目前的應用程式運作狀態並追蹤長期應用程式效能。Application Signals 為您的應用程式、服務和相依性提供統一、以應用程式為中心的檢視,並協助監控和分類應用程式運作狀態。如需詳細資訊,請參閱 Application Signals

  • 使用 OpenTelemetry Java 代理程式進行自動檢測。如需詳細資訊,請參閱使用 Java Agent 進行零碼檢測

使用 SDK 的手動檢測解決方案

Tracing setup with X-Ray SDK

若要使用適用於 Java 的 X-Ray 開發套件來檢測程式碼,首先需要使用服務外掛程式和本機取樣規則來設定 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>

透過執行個體化 TracerProvider和全域註冊OpenTelemetrySdk物件來設定 OpenTelemetry SDK。設定這些元件:

  • OTLP Span Exporter (例如 OtlpGrpcSpanExporter) - 將追蹤匯出至 CloudWatch 代理程式或 OpenTelemetry Collector 時需要

  • AWS X-Ray 傳播器 – 將追蹤內容傳播至與 X-Ray 整合 AWS 的服務時需要

  • AWS X-Ray 遠端取樣器 – 如果您需要使用 X-Ray 取樣規則來取樣請求,則為必要項目

  • 資源偵測器 (例如 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

如需有關如何使用 X-Ray 開發套件搭配彈簧架構來檢測應用程式的資訊,請參閱搭配 Spring 的 AOP 和適用於 Java 的 X-Ray 開發套件。若要在 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

當您在建置中新增aws-xray-recorder-sdk-aws-sdk-v2-instrumentor子模組時,適用於 Java 的 X-Ray 開發套件可以自動檢測所有 AWS SDK v2 用戶端。

若要使用適用於 Java 的 AWS SDK 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 請求,需要適用於 Java 的 X-Ray 開發套件的 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 開發套件類似,OpenTelemetry 提供的 ApacheHttpClientTelemetry類別具有建置器方法,允許建立 的執行個體HttpClientBuilder,為 Apache HttpClient 提供 OpenTelemetry 型跨度和內容傳播。

<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(); } }

其他程式庫的檢測支援

在支援的程式庫、架構、應用程式伺服器和 JVM 下,在其個別的檢測 GitHub 儲存庫 中尋找 OpenTelemetry Java 支援的程式庫檢測的完整清單。 JVMs

或者,您可以搜尋 OpenTelemetry 登錄檔,了解 OpenTelemetry 是否支援檢測。若要開始搜尋,請參閱登錄檔。

手動建立追蹤資料

With X-Ray SDK

使用 X-Ray SDK,需要 beginSegmentbeginSubsegment方法來手動建立 X-Ray 區段和子區段。

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方法取得。這將提供來自 的 Tracer 執行個體TracerProvider,該執行個體已在 使用 SDK 的手動檢測解決方案範例中全域註冊。您可以視需要建立任意數量的 Tracer 執行個體,但整個應用程式通常會有一個 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 原始資料中的中繼資料。為了確保屬性轉換為註釋而非中繼資料,上述範例會將該屬性的索引鍵新增至aws.xray.annotations屬性清單。如需詳細資訊,請參閱啟用自訂 X-Ray 註釋註釋和中繼資料

使用 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 開發套件,在 Lambda 啟用主動追蹤之後,使用 X-Ray 開發套件不需要額外的組態。Lambda 將建立代表 Lambda 處理常式調用的區段,而且您可以使用 X-Ray SDK 建立子區段或儀器程式庫,而不需要任何額外的組態。

With OpenTelemetry-based solutions

自動檢測 Lambda 圖層 – 您可以使用下列解決方案,自動檢測 Lambda 與已 AWS 佈建的 Lambda 圖層:

  • CloudWatch Application Signals Lambda layer (建議)

    注意

    此 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. 具有 X-Ray UDP 跨度匯出程式的簡易跨度處理器,可將追蹤傳送至 Lambda 的 UDP X-Ray 端點

    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 主控台中的追蹤映射。