Migrando para Java OpenTelemetry - AWS X-Ray

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Migrando para Java OpenTelemetry

Esta seção fornece orientação sobre como migrar do X-Ray SDK para o OpenTelemetry SDK for Java.

Solução de instrumentação automática de código zero

With X-Ray Java agent

Para habilitar o agente Java X-Ray, os argumentos JVM do seu aplicativo precisavam ser modificados.

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

Para usar agentes Java OpenTelemetry baseados.

  • Use o agente Java AWS Distro for OpenTelemetry (ADOT) Auto-Instrumentation para instrumentação automática com o agente ADOT Java. Para obter mais informações, consulte Instrumentação automática para traços e métricas com o agente Java. Se você quiser apenas o rastreamento, desative a variável de OTEL_METRICS_EXPORTER=none ambiente. para exportar métricas do agente Java.

    (Opcional) Você também pode ativar o CloudWatch Application Signals ao instrumentar automaticamente seus aplicativos AWS com a instrumentação automática ADOT Java para monitorar a integridade atual do aplicativo e monitorar o desempenho de longo prazo do aplicativo. O Application Signals fornece uma visão unificada e centrada no aplicativo de seus aplicativos, serviços e dependências e ajuda a monitorar e fazer a triagem da integridade do aplicativo. Para obter mais informações, consulte Application Signals.

  • Use o agente OpenTelemetry Java para instrumentação automática. Para obter mais informações, consulte Instrumentação de código zero com o Java Agent.

Soluções de instrumentação manual com o SDK

Tracing setup with X-Ray SDK

Para instrumentar seu código com o X-Ray SDK for Java, primeiro era necessário configurar AWSXRay a classe com plug-ins de serviço e regras de amostragem locais e, em seguida, era usado um gravador fornecido.

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

As seguintes dependências são obrigatórias.

<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>

Configure o OpenTelemetry SDK instanciando um objeto TracerProvider e registrando globalmente um objeto. OpenTelemetrySdk Configure esses componentes:

  • Um exportador OTLP Span (por exemplo, OtlpGrpcSpanExporter) - Necessário para exportar traços para o agente ou coletor CloudWatch OpenTelemetry

  • Um propagador de AWS raio-X — necessário para propagar o contexto de rastreamento para AWS serviços integrados ao X-Ray

  • Um amostrador remoto de AWS raio-X — necessário se você precisar coletar amostras de solicitações usando as regras de amostragem de raios X

  • Detectores de recursos (por exemplo, EcsResource ou Ec2Resource) — Detecte metadados do host que está executando seu aplicativo

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

Rastreando solicitações recebidas (instrumentação do Spring Framework)

With X-Ray SDK

Para obter informações sobre como usar o X-Ray SDK com a estrutura spring para instrumentar seu aplicativo, consulte AOP com Spring e o X-Ray SDK for Java. Para habilitar o AOP no Spring, conclua estas etapas.

With OpenTelemetry SDK

OpenTelemetry fornece bibliotecas de instrumentação para coletar rastreamentos para solicitações recebidas de aplicativos Spring Boot. Para habilitar a instrumentação do Spring Boot com configuração mínima, inclua a seguinte dependência.

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

Para obter mais informações sobre como habilitar e configurar a instrumentação do Spring Boot para sua OpenTelemetry configuração, consulte OpenTelemetry Introdução.

Using OpenTelemetry-based Java agents

O método padrão recomendado para instrumentar aplicativos Spring Boot é usar o agente OpenTelemetry Java com instrumentação de bytecode, que também fornece mais out-of-the-box instrumentações e configurações quando comparado ao uso direto do SDK. Para começar, consulteSolução de instrumentação automática de código zero.

AWS Instrumentação do SDK v2

With X-Ray SDK

O X-Ray SDK for Java pode instrumentar automaticamente AWS todos os clientes do SDK v2 quando você adiciona aws-xray-recorder-sdk-aws-sdk-v2-instrumentor o submódulo à sua compilação.

Para instrumentar chamadas posteriores de clientes individuais para AWS serviços com o AWS SDK for Java 2.2 e versões posteriores, aws-xray-recorder-sdk-aws-sdk-v2-instrumentor o módulo da sua configuração de compilação foi excluído e aws-xray-recorder-sdk-aws-sdk-v2 o módulo foi incluído. Clientes individuais foram instrumentados configurando-os com um. 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

Para instrumentar automaticamente todos os clientes AWS do SDK, adicione o opentelemetry-aws-sdk-2.2-autoconfigure submódulo.

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

Para instrumentar clientes AWS SDK individuais, adicione o opentelemetry-aws-sdk-2.2 submódulo.

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

Em seguida, registre um interceptor ao criar um cliente 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();

Instrumentar chamadas HTTP de saída

With X-Ray SDK

Para instrumentar as solicitações HTTP de saída com o X-Ray, era necessário o X-Ray SDK para Java, versão do Apache HttpClient .

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

Da mesma forma que o X-Ray Java SDK, OpenTelemetry fornece uma ApacheHttpClientTelemetry classe que tem um método construtor que permite a criação de uma instância de um HttpClientBuilder para fornecer extensões OpenTelemetry baseadas e propagação de contexto para o Apache. HttpClient

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

A seguir está um exemplo de código do opentelemetry-java-instrumentation. O cliente HTTP fornecido por newHttpClient () gerará rastreamentos para solicitações executadas.

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

Suporte de instrumentação para outras bibliotecas

Encontre a lista completa de instrumentações de biblioteca suportadas para OpenTelemetry Java em seu respectivo GitHub repositório de instrumentação, em Bibliotecas, estruturas, servidores de aplicativos e. JVMs

Como alternativa, você pode pesquisar no OpenTelemetry Registro para descobrir se OpenTelemetry suporta instrumentação. Para começar a pesquisar, consulte Registro.

Criação manual de dados de rastreamento

With X-Ray SDK

Com o X-Ray SDK, os beginSubsegment métodos beginSegment e são necessários para criar manualmente segmentos e subsegmentos de raio-X.

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

Você pode usar extensões personalizadas para monitorar o desempenho de atividades internas que não são capturadas pelas bibliotecas de instrumentação. Observe que somente servidores do tipo span são convertidos em segmentos de X-Ray, todos os outros spans são convertidos em subsegmentos de X-Ray.

Primeiro, você precisará criar um Tracer para gerar extensões, que podem ser obtidas por meio do openTelemetry.getTracer método. Isso fornecerá uma instância Tracer da TracerProvider que foi registrada globalmente no Soluções de instrumentação manual com o SDK exemplo. Você pode criar quantas instâncias do Tracer forem necessárias, mas é comum ter um Tracer para um aplicativo inteiro.

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

Você pode usar o Tracer para criar extensões.

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

Os intervalos têm um tipo padrão de 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(); }

Adicionar anotações e metadados aos rastreamentos com o SDK OpenTelemetry

No exemplo acima, o setAttribute método é usado para adicionar atributos a cada extensão. Por padrão, todos os atributos de amplitude serão convertidos em metadados nos dados brutos do X-Ray. Para garantir que um atributo seja convertido em uma anotação e não em metadados, o exemplo acima adiciona a chave desse atributo à lista do atributo. aws.xray.annotations Para obter mais informações, consulte Enable the Customized X-Ray Annotations and Annotations and metadata.

Com agentes Java OpenTelemetry baseados

Se você estiver usando o agente Java para instrumentar automaticamente seu aplicativo, precisará executar a instrumentação manual em seu aplicativo. Por exemplo, para instrumentar o código dentro do aplicativo para seções que não são cobertas por nenhuma biblioteca de instrumentação automática.

Para realizar a instrumentação manual com o agente, você precisa usar o opentelemetry-api artefato. A versão do artefato não pode ser mais recente que a versão do agente.

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

Instrumentação Lambda

With X-Ray SDK

Usando o X-Ray SDK, depois que seu Lambda tiver o Active Tracing ativado, não há necessidade de configuração adicional para usar o X-Ray SDK. O Lambda criará um segmento representando a invocação do manipulador Lambda, e você poderá criar subsegmentos ou bibliotecas de instrumentos usando o X-Ray SDK sem nenhuma configuração adicional.

With OpenTelemetry-based solutions

Camadas Lambda de instrumentação automática — Você pode instrumentar automaticamente seu Lambda AWS com camadas Lambda vendidas usando as seguintes soluções:

  • CloudWatch Camada Lambda de sinais de aplicação (recomendada)

    nota

    Essa camada Lambda tem sinais de CloudWatch aplicativo ativados por padrão, o que permite o monitoramento de desempenho e integridade de seu aplicativo Lambda por meio da coleta de métricas e rastreamentos. Para apenas rastrear, defina a variável de ambiente Lambda. OTEL_AWS_APPLICATION_SIGNALS_ENABLED=false

    • Permite o monitoramento do desempenho e da integridade do seu aplicativo Lambda

    • Coleta métricas e rastreamentos por padrão

  • AWS camada Lambda gerenciada para ADOT Java. Para obter mais informações, consulte AWS Distro for OpenTelemetry Lambda Support For Java.

Para usar a instrumentação manual junto com a camada de instrumentação automática, consulte. Soluções de instrumentação manual com o SDK Para reduzir as partidas a frio, considere o uso de instrumentação OpenTelemetry manual para gerar OpenTelemetry traços para sua função Lambda.

OpenTelemetry instrumentação manual para Lambda AWS

Considere o seguinte código de função Lambda que faz uma chamada do Amazon ListBuckets S3.

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

Aqui estão as dependências.

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') }

Para instrumentar manualmente seu manipulador Lambda e o cliente Amazon S3, faça o seguinte.

  1. Substitua suas classes de função que implementam RequestHandler (ou RequestStreamHandler) por aquelas que se estendem TracingRequestHandler (ou TracingRequestStreamHandler).

  2. TracerProvider Instancie um objeto e registre globalmente. OpenTelemetrySdk TracerProvider Recomenda-se que seja configurado com:

    1. Um processador de amplitude simples com um exportador de amplitude UDP de raio-X para enviar traços para o endpoint UDP X-Ray da Lambda

    2. Um amostrador ParentBased sempre ativo (padrão se não estiver configurado)

    3. Um recurso com service.name definido como o nome da função Lambda

    4. Um propagador X-Ray Lambda

  3. doHandleRequestAltere o handleRequest método e passe o OpenTelemetrySdk objeto para a classe base.

  4. Instrumente o cliente Amazon S3 com a instrumentação do OpenTemetry AWS SDK registrando o interceptor ao criar o cliente.

Você precisa das seguintes dependências OpenTelemetry relacionadas.

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') }

O código a seguir demonstra a função Lambda após as alterações necessárias. Você pode criar extensões personalizadas adicionais para complementar as extensões fornecidas automaticamente.

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

Ao invocar a função Lambda, você verá o seguinte rastreamento em Trace Map no CloudWatch console.

Mapa de rastreamento no CloudWatch console.