

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 迁移到 OpenTelemetry Java
<a name="xray-migration-opentelemetry"></a>

本节提供有关从 X-Ray SDK 迁移到 Java 应用程序的 OpenTelemetry SDK 的指导。

**Topics**
+ [

## 零代码自动检测解决方案
](#xray-migration-zero-code)
+ [

## 使用 SDK 的手动检测解决方案
](#xray-migration-sdk)
+ [

## 跟踪传入的请求（Spring 框架检测）
](#xray-migration-tracing-setup-otel)
+ [

## AWS 软件开发工具包 v2 插件
](#xray-migration-sdkv2)
+ [

## 检测传出 HTTP 调用
](#xray-migration-http)
+ [

## 对其他库的检测支持
](#xray-migration-libraries)
+ [

## 手动创建跟踪数据
](#xray-migration-tracedata)
+ [

## Lambda 检测
](#xray-migration-lambda)

## 零代码自动检测解决方案
<a name="xray-migration-zero-code"></a>

------
#### [ 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-Instrumention Java 代理使用 ADOT Java 代理进行自动检测。有关更多信息，请参阅[使用 Java 代理实现对跟踪数据和指标的自动检测](https://aws-otel.github.io/docs/getting-started/java-sdk/auto-instr)。如果您只想跟踪，请禁用 `OTEL_METRICS_EXPORTER=none ` 环境变量，从 Java 代理导出指标。

  （可选）您还可以在使用 ADOT Java 自动仪器自动检测应用程序时启用 CloudWatch 应用程序信号，以监控当前应用程序的运行状况并跟踪长期应用程序性能。 AWS Application Signals 提供了统一的、以应用程序为中心的应用程序、服务和依赖项视图，帮助监控应用程序的运行状况并对其进行分类。有关更多信息，请参阅 [Application Signals](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Application-Monitoring-Sections.html)。
+ 使用 OpenTelemetry Java 代理进行自动检测。有关更多信息，请参阅[使用 Java 代理实现零代码检测](https://opentelemetry.io/docs/zero-code/java/agent/)。

------

## 使用 SDK 的手动检测解决方案
<a name="xray-migration-sdk"></a>

------
#### [ 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>
```

通过实例化来配置 OpenTelemetry SDK，`TracerProvider`然后全局注册一个对象。`OpenTelemetrySdk`配置以下组件：
+ OTLP Span 导出器（例如 OtlpGrpcSpanExporter）-将跟踪导出到 CloudWatch 代理或 OpenTelemetry 收集器所必需的
+  AWS X-Ray 传播器 — 将跟踪上下文传播到与 X-Ray 集成的 AWS 服务所必需的
+  AWS X-Ray-Remote 采样器 — 如果您需要使用 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();
  ```

------

## 跟踪传入的请求（Spring 框架检测）
<a name="xray-migration-tracing-setup-otel"></a>

------
#### [ With X-Ray SDK ]

有关如何使用带有 Spring 框架的 X-Ray SDK 来检测应用程序的信息，请参阅[使用 Spring 和 X-Ray SDK for Java 启用 AOP](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java-aop-spring.html)。要在 Spring 中启用 AOP，请完成以下步骤。

1. [配置 Spring](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java-aop-spring.html#xray-sdk-java-aop-spring-configuration)

1. [向应用程序添加跟踪筛选器](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java-aop-spring.html#xray-sdk-java-aop-filters-spring)

1. [对代码添加注释或实现接口](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java-aop-spring.html#xray-sdk-java-aop-annotate-or-implement)

1. [激活应用程序中的 X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java-aop-spring.html#xray-sdk-java-aop-activate-xray)

------
#### [ 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的更多信息，请参阅[入门](https://opentelemetry.io/docs/zero-code/java/spring-boot-starter/getting-started/)。

------
#### [ Using OpenTelemetry-based Java agents ]

对 Spring Boot 应用程序进行检测的默认推荐方法是使用带有*字节码检测*的 [OpenTelemetry Java 代理](https://opentelemetry.io/docs/zero-code/java/agent/)，与直接使用 SDK 相比，它还提供了更多的 out-of-the-box检测和配置。要开始使用，请参阅[零代码自动检测解决方案](#xray-migration-zero-code)。

------

## AWS 软件开发工具包 v2 插件
<a name="xray-migration-sdkv2"></a>

------
#### [ With X-Ray SDK ]

当你在版本中添加`aws-xray-recorder-sdk-aws-sdk-v2-instrumentor`子模块时，适用于 Java 的 X-Ray AWS SDK 可以自动检测所有 SDK v2 客户端。

要使用 AWS SDK for Java 2.2 及更高版本检测单个客户端对 AWS 服务的下游客户端调用，您的编译配置中已排除该`aws-xray-recorder-sdk-aws-sdk-v2`模块，并包含该模块。`aws-xray-recorder-sdk-aws-sdk-v2-instrumentor `通过为单个客户端配置 `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 调用
<a name="xray-migration-http"></a>

------
#### [ With X-Ray SDK ]

要使用 X-Ray 检测传出的 HTTP 请求，需要适用于 Java 的 Apache HttpClient 版本的 X-Ray SDK。

```
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 `ApacheHttpClientTelemetry` 类似，它 OpenTelemetry 提供了一个具有生成器方法的类，该方法允许创建 the 的实例，`HttpClientBuilder`以便为 A HttpClient pache 提供 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](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/apache-httpclient/apache-httpclient-5.2/library)。 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();
  }
}
```

------

## 对其他库的检测支持
<a name="xray-migration-libraries"></a>

在 “支持的库、[框架、应用程序服务器和” 下的相应工具 GitHub 库中查找支持 OpenTelemetry Java 的库](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md)工具的完整列表。 JVMs

或者，您可以搜索 OpenTelemetry 注册表以了解是否 OpenTelemetry 支持检测。要开始搜索，请参阅[注册表](https://opentelemetry.io/ecosystem/registry/)。

## 手动创建跟踪数据
<a name="xray-migration-tracedata"></a>

------
#### [ 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` 方法来获得该跨度。这将从在 [使用 SDK 的手动检测解决方案](#xray-migration-sdk) 示例中全局注册的 `TracerProvider` 中获取一个跟踪器实例。您可以根据需要创建任意数量的跟踪器实例，但通常针对整个应用程序创建一个跟踪器。

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

您可以使用跟踪器创建跨度。

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

跨度的默认类型为*内部*。

```
// 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 注释](https://aws-otel.github.io/docs/getting-started/x-ray#enable-the-customized-x-ray-annotations)以及[注释和元数据](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 检测
<a name="xray-migration-lambda"></a>

------
#### [ With X-Ray SDK ]

如果要使用 X-Ray SDK，在 Lambda 启用*主动跟踪*后，无需进行任何其他配置即可使用 X-Ray SDK。Lambda 将创建一个表示 Lambda 处理程序调用的分段，您无需进行任何其他配置即可使用 X-Ray SDK 创建子分段或检测库。

------
#### [ With OpenTelemetry-based solutions ]

自动检测 Lambda 层 — 您可以使用以下解决方案自动检测 AWS 带有凸起的 Lambda 层的 Lambda 层：
+ AWS 适用于 OpenTelemetry （推荐）的 Lambda 层
**注意**  
此 Lambda 层默认启用 CloudWatch 应用程序信号，通过收集指标和跟踪来监控您的 Lambda 应用程序的性能和运行状况。为了仅进行跟踪，请设置 Lambda 环境变量 ` OTEL_AWS_APPLICATION_SIGNALS_ENABLED=false`。
  + 为 Lambda 应用程序启用性能和运行状况监控
  + 默认情况下会同时收集指标和跟踪数据
+ AWS 适用于 ADOT Java 的托管 Lambda 层。有关更多信息，请参阅适用于 Java 的 L [AWS amb OpenTelemetry da Support 发行版](https://aws-otel.github.io/docs/getting-started/lambda/lambda-java)。

要将手动检测与自动检测层结合使用，请参阅[使用 SDK 的手动检测解决方案](#xray-migration-sdk)。为了减少冷启动，可以考虑使用 OpenTelemetry 手动检测为您的 Lambda 函数生成 OpenTelemetry 跟踪。

------

**OpenTelemetry 针对 AWS Lambda 的手动检测**

考虑以下用于调用 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）的函数类。

1. 实例化一个对象 TracerProvider 并全局注册一个对象。 OpenTelemetrySdk 建议配置为： TracerProvider 

   1. 带有 X-Ray UDP 跨度导出程序的简单跨度处理器，用于向 Lambda 的 UDP X-Ray 端点发送跟踪数据

   1.  ParentBased 始终开启的采样器（如果未配置，则为默认值）

   1. 将 service.name 设置为 Lambda 函数名称的资源

   1. X-Ray Lambda 传播器

1. 将 `handleRequest` 方法更改为 `doHandleRequest` 并将 `OpenTelemetrySdk` 对象传递给基类。

1. 通过在构建客户端时注册拦截器，使用 OpenTemetry AWS 软件开发工具包检测 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 函数时，您将在控制台的 Trace Map *下看到以下跟踪*。 CloudWatch 

![\[CloudWatch 控制台中的追踪地图。\]](http://docs.aws.amazon.com/zh_cn/xray/latest/devguide/images/SDKDeprecation_Java.png)
