

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# OpenTelemetry Java로 마이그레이션
<a name="xray-migration-opentelemetry"></a>

이 섹션에서는 X-Ray SDK에서 Java용 OpenTelemetry SDK 애플리케이션으로 마이그레이션하는 방법에 대한 지침을 제공합니다.

**Topics**
+ [제로 코드 자동 계측 솔루션](#xray-migration-zero-code)
+ [SDK를 사용한 수동 계측 솔루션](#xray-migration-sdk)
+ [수신 요청 추적(스프링 프레임워크 계측)](#xray-migration-tracing-setup-otel)
+ [AWS SDK 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 에이전트 사용
+ ADOT Java 에이전트를 사용한 자동 계측을 위해 AWS Distro for OpenTelemetry(ADOT) Auto-Instrumentation Java 에이전트를 사용합니다. 자세한 내용은 [Java 에이전트를 사용한 추적 및 지표에 대한 자동 계측](https://aws-otel.github.io/docs/getting-started/java-sdk/auto-instr)을 참조하세요. 추적만 원하는 경우 `OTEL_METRICS_EXPORTER=none ` 환경 변수를 비활성화하여 Java 에이전트에서 지표를 내보냅니다.

  (선택 사항) ADOT Java 자동 계측 AWS 을 사용하여에서 애플리케이션을 자동으로 계측할 때 CloudWatch Application Signals를 활성화하여 현재 애플리케이션 상태를 모니터링하고 장기 애플리케이션 성능을 추적할 수도 있습니다. Application Signals는 애플리케이션, 서비스 및 종속성에 대한 통합 애플리케이션 중심 보기를 제공하고 애플리케이션 상태를 모니터링하고 분류하는 데 도움이 됩니다. 자세한 내용은 [Application Signals](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Application-Monitoring-Sections.html)를 참조하세요.
+ 자동 계측을 위해 OpenTelemetry Java 에이전트를 사용합니다. 자세한 내용은 [Java Agent를 사용한 제로 코드 계측](https://opentelemetry.io/docs/zero-code/java/agent/)을 참조하세요.

------

## SDK를 사용한 수동 계측 솔루션
<a name="xray-migration-sdk"></a>

------
#### [ Tracing setup with X-Ray SDK ]

Java용 X-Ray SDK를 사용하여 코드를 계측하려면 먼저 `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 샘플링 규칙을 사용하여 요청을 샘플링해야 하는 경우 필요합니다.
+ 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();
  ```

------

## 수신 요청 추적(스프링 프레임워크 계측)
<a name="xray-migration-tracing-setup-otel"></a>

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

스프링 프레임워크와 함께 X-Ray SDK를 사용하여 애플리케이션을 계측하는 방법에 대한 자세한 내용은 [Spring을 사용하는 AOP 및 Java용 X-Ray SDK](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를 직접 사용하는 경우와 비교할 때 더 많은 기본 제공 계측 및 구성을 제공합니다. 시작하려면 [제로 코드 자동 계측 솔루션](#xray-migration-zero-code) 섹션을 참조하세요.

------

## AWS SDK v2 계측
<a name="xray-migration-sdkv2"></a>

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

빌드에 `aws-xray-recorder-sdk-aws-sdk-v2-instrumentor` 하위 모듈을 추가하면 Java용 X-Ray SDK가 모든 AWS SDK v2 클라이언트를 자동으로 계측할 수 있습니다.

Java 2.2 이상용 AWS SDK를 사용하여 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 호출 구성
<a name="xray-migration-http"></a>

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

X-Ray를 사용하여 발신 HTTP 요청을 계측하려면 Java용 X-Ray SDK의 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](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>

[지원되는 라이브러리, 프레임워크, 애플리케이션 서버 및 JVM](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md) 아래의 해당 계측 GitHub 리포지토리에서 OpenTelemetry Java에 지원되는 라이브러리 계측의 전체 목록을 찾습니다.

또는 OpenTelemetry 레지스트리를 검색하여 OpenTelemetry가 계측을 지원하는지 확인할 수 있습니다. 검색을 시작하려면 [레지스트리](https://opentelemetry.io/ecosystem/registry/)를 참조하세요.

## 추적 데이터 수동 생성
<a name="xray-migration-tracedata"></a>

------
#### [ 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` 메서드를 통해 얻을 수 있는 스팬을 생성하려면 *Tracer*를 생성해야 합니다. 그러면 [SDK를 사용한 수동 계측 솔루션](#xray-migration-sdk) 예제에 전역적으로 등록된 `TracerProvider`의 Tracer 인스턴스가 제공됩니다. 필요한 만큼 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 주석 활성화](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 Application Signals가 기본적으로 활성화되어 있으므로 지표와 추적을 모두 수집하여 Lambda 애플리케이션에 대한 성능 및 상태 모니터링을 사용할 수 있습니다. 추적만 하려면 Lambda 환경 변수 ` OTEL_AWS_APPLICATION_SIGNALS_ENABLED=false`를 설정합니다.
  + Lambda 애플리케이션에 대한 성능 및 상태 모니터링을 활성화합니다.
  + 기본적으로 지표와 추적을 모두 수집합니다.
+ AWS ADOT Java용 관리형 Lambda 계층입니다. 자세한 내용은 [Java에 대한AWS Distro for OpenTelemetry의 Lambda 지원](https://aws-otel.github.io/docs/getting-started/lambda/lambda-java)을 참조하세요.

자동 계측 계층과 함께 수동 계측을 사용하려면 [SDK를 사용한 수동 계측 솔루션](#xray-migration-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)를 확장하는 함수 클래스로 바꿉니다.

1. TracerProvider를 인스턴스화하고 OpenTelemetrySdk 객체를 전역적으로 등록합니다. TracerProvider는 다음과 같이 구성하는 것이 좋습니다.

   1. 추적을 Lambda의 UDP X-Ray 엔드포인트로 전송하기 위한 X-Ray UDP 스팬 내보내기 도구가 있는 Simple Span Processor

   1. ParentBased Always On 샘플러(구성되지 않은 경우 기본값)

   1. service.name이 Lambda 함수 이름으로 설정된 리소스

   1. X-Ray Lambda 전파기

1. `handleRequest` 메서드를 `doHandleRequest`로 변경하고 `OpenTelemetrySdk` 객체를 기본 클래스에 전달합니다.

1. 클라이언트를 빌드할 때 인터셉터를 등록하여 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 콘솔의 추적 맵.](http://docs.aws.amazon.com/ko_kr/xray/latest/devguide/images/SDKDeprecation_Java.png)
