本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
遷移至 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,需要 beginSegment
和 beginSubsegment
方法來手動建立 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 圖層:
若要搭配自動檢測層使用手動檢測,請參閱 使用 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 用戶端,請執行下列動作。
將實作 RequestHandler
(或 RequestStreamHandler) 的函數類別取代為延伸 TracingRequestHandler
(或 TracingRequestStreamHandler) 的函數類別。
執行個體化 TracerProvider 並全域註冊 OpenTelemetrySdk 物件。建議將 TracerProvider 設定為:
具有 X-Ray UDP 跨度匯出程式的簡易跨度處理器,可將追蹤傳送至 Lambda 的 UDP X-Ray 端點
ParentBased always on sampler (若未設定,則預設為預設值)
將 service.name 設為 Lambda 函數名稱的資源
X-Ray Lambda 傳播器
將 handleRequest
方法變更為 ,doHandleRequest
並將OpenTelemetrySdk
物件傳遞至 基礎類別。
透過在建置用戶端時註冊攔截器,使用 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 主控台的追蹤地圖下看到下列追蹤。