AWS X-Ray SDK para Java - 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á.

AWS X-Ray SDK para Java

O X-Ray SDK for Java é um conjunto de bibliotecas Java para aplicativos Web que fornecem classes e métodos para gerar e enviar dados de rastreamento para o daemon X-Ray. Os dados de rastreamento incluem informações sobre solicitações HTTP recebidas pelo aplicativo e chamadas que o aplicativo faz para serviços downstream usando o AWS SDK, clientes HTTP ou um conector de banco de dados SQL. Você também pode criar segmentos manualmente e adicionar informações de depuração em anotações e metadados.

O X-Ray SDK para Java é um projeto de código aberto. Você pode acompanhar o projeto e enviar problemas e pull requests em GitHub: github.com/aws/ aws-xray-sdk-java

Comece adicionando AWSXRayServletFilter como um filtro de servlet para rastrear as solicitações de entrada. Um filtro de servlet cria um segmento. Embora o segmento esteja aberto, você pode usar os métodos do cliente do SDK para adicionar informações ao segmento e criar subsegmentos para rastrear as chamadas subsequentes. O SDK também registra automaticamente exceções que seu aplicativo lança enquanto o segmento está aberto.

A partir da versão 1.3, você pode instrumentar seu aplicativo usando a programação orientada a aspectos (AOP) no Spring. Isso significa que você pode instrumentar seu aplicativo enquanto ele está em execução AWS, sem adicionar nenhum código ao tempo de execução do aplicativo.

Em seguida, use o X-Ray SDK for Java para instrumentar AWS SDK for Java seus clientes incluindo o submódulo SDK Instrumentor em sua configuração de compilação. Sempre que você faz uma chamada para um downstream AWS service (Serviço da AWS) ou recurso com um cliente instrumentado, o SDK registra as informações sobre a chamada em um subsegmento. Serviços da AWS e os recursos que você acessa nos serviços aparecem como nós downstream no mapa de rastreamento para ajudá-lo a identificar erros e problemas de limitação em conexões individuais.

Se você não quiser instrumentar todas as chamadas downstream Serviços da AWS, pode omitir o submódulo Instrumentor e escolher quais clientes instrumentar. Instrumente clientes individuais adicionando um TracingHandler a a um cliente de serviço do AWS SDK.

Outros submódulos do X-Ray SDK para Java oferecem instrumentação para as chamadas subsequentes para APIs da web HTTP e bancos de dados SQL. Você pode usar as versões HTTPClient e HTTPClientBuilder do X-Ray SDK para Java no submódulo Apache HTTP para instrumentar clientes do Apache HTTP. Para instrumentar consultas SQL, adicione o interceptor do SDK para sua fonte de dados.

Depois que você começar a usar o SDK, personalize seu comportamento configurando o gravador e o filtro de servlet. Você pode adicionar plug-ins para registrar dados sobre os recursos de computação que executam sua aplicação, personalizar o comportamento de amostragem, estipulando regras de amostragem, e definir o nível de log para ver mais ou menos informações do SDK nos logs da aplicação.

Registre informações adicionais sobre as solicitações e o trabalho que o a aplicação faz em anotações e metadados. Anotações são simples pares de chave-valor que são indexados para serem usados com expressões de filtro para que você possa pesquisar rastreamentos que contêm dados específicos. As entradas de metadados são menos restritivas e podem registrar matrizes e objetos inteiros: tudo o que pode ser serializado em JSON.

Anotações e metadados

Anotações e metadados são textos arbitrários que você adiciona aos segmentos com o X-Ray SDK. As anotações são indexadas para serem usadas com expressões de filtro. Os metadados não são indexados, mas podem ser visualizados no segmento bruto com o console ou a API do X-Ray. Qualquer pessoa à qual você conceder acesso de leitura ao X-Ray poderá visualizar esses dados.

Quando você tem uma grande quantidade de clientes instrumentados em seu código, um único segmento de solicitação pode conter muitos subsegmentos, um para cada chamada feita com um cliente instrumentado. Você pode organizar e agrupar subsegmentos integrando chamadas de clientes em subsegmentos personalizados. Você pode criar um subsegmento personalizado para uma função inteira ou qualquer seção de código e registrar metadados e anotações no subsegmento em vez de gravar tudo no segmento principal.

Submódulos

Você pode baixar o X-Ray SDK para Java do Maven. O X-Ray SDK para Java é dividido em submódulos por caso de uso, com uma lista de materiais para gerenciamento de versões:

Se você usar o Maven ou o Gradle para criar sua aplicação, adicione o X-Ray SDK para Java à configuração de compilação.

Para obter a documentação de referência das classes e métodos do SDK, consulte AWS X-Ray SDK for Java API Reference.

Requisitos

O X-Ray SDK for Java Java requer 8 ou posterior, a Servlet API 3, AWS o SDK e Jackson.

O SDK depende das seguintes bibliotecas para compilação e tempo de execução:

  • AWS SDK para a Java versão 1.11.398 ou posterior

  • API Servlet 3.1.0

Essas dependências são declaradas no arquivo pom.xml do SDK e serão incluídas automaticamente se você criar usando Maven ou Gradle.

Se você usar uma biblioteca que esteja incluída no X-Ray SDK para Java, deverá usar a versão incluída. Por exemplo, se você já usa Jackson em tempo de execução e inclui arquivos JAR em sua implantação para essa dependência, deverá remover esses arquivos JAR porque o SDK JAR inclui suas próprias versões de bibliotecas Jackson.

Gerenciar dependências

O SDK para Java do X-Ray para Java está disponível no Maven:

  • Grupo: com.amazonaws

  • Artefato: aws-xray-recorder-sdk-bom

  • Versão: 2.11.0

Se você usar o Maven para criar seu aplicativo, adicione o SDK como uma dependência no arquivo pom.xml.

exemplo pom.xml – dependências
<dependencyManagement> <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-bom</artifactId> <version>2.11.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-core</artifactId> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-apache-http</artifactId> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-aws-sdk</artifactId> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-aws-sdk-instrumentor</artifactId> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-sql-postgres</artifactId> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-sql-mysql</artifactId> </dependency> </dependencies>

Para Gradle, adicione o SDK como uma dependência de tempo de compilação ao arquivo build.gradle.

exemplo build.gradle – dependências
dependencies { compile("org.springframework.boot:spring-boot-starter-web") testCompile("org.springframework.boot:spring-boot-starter-test") compile("com.amazonaws:aws-java-sdk-dynamodb") compile("com.amazonaws:aws-xray-recorder-sdk-core") compile("com.amazonaws:aws-xray-recorder-sdk-aws-sdk") compile("com.amazonaws:aws-xray-recorder-sdk-aws-sdk-instrumentor") compile("com.amazonaws:aws-xray-recorder-sdk-apache-http") compile("com.amazonaws:aws-xray-recorder-sdk-sql-postgres") compile("com.amazonaws:aws-xray-recorder-sdk-sql-mysql") testCompile("junit:junit:4.11") } dependencyManagement { imports { mavenBom('com.amazonaws:aws-java-sdk-bom:1.11.39') mavenBom('com.amazonaws:aws-xray-recorder-sdk-bom:2.11.0') } }

Se você usar o Elastic Beanstalk para implantar a aplicação, poderá usar o Maven ou o Gradle para criar na instância toda vez que implantar, em vez de criar e carregar um grande arquivo que inclui todas as suas dependências. Consulte o aplicativo de amostra para obter um exemplo que usa Gradle.

Configurar o X-Ray SDK para Java

O X-Ray SDK para Java tem uma classe chamada AWSXRay, que fornece o gravador global. Este é um TracingHandler que pode ser usado para instrumentar o código. Você pode configurar o gravador global para personalizar o AWSXRayServletFilter que cria segmentos para chamadas HTTP de entrada.

Plug-ins de serviço

Use plugins para registrar informações sobre o serviço que hospeda a aplicação.

Plug-ins
  • Amazon EC2 — EC2Plugin adiciona o ID da instância, a zona de disponibilidade e o grupo de CloudWatch registros.

  • Elastic Beanstalk: o ElasticBeanstalkPlugin adiciona o nome do ambiente, o rótulo da versão e o ID de implantação.

  • Amazon ECS: o ECSPlugin adiciona o ID do contêiner.

  • Amazon EKS — EKSPlugin adiciona o ID do contêiner, o nome do cluster, o ID do pod e o grupo de CloudWatch registros.

Segmente dados de recursos com os plug-ins do Amazon EC2 e do Elastic Beanstalk.

Para usar um plugin, acione o withPlugin em seu AWSXRayRecorderBuilder.

exemplo src/main/java/scorekeep/ .java WebConfig - gravador
import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.AWSXRayRecorderBuilder; import com.amazonaws.xray.plugins.EC2Plugin; import com.amazonaws.xray.plugins.ElasticBeanstalkPlugin; import com.amazonaws.xray.strategy.sampling.LocalizedSamplingStrategy; @Configuration public class WebConfig { ... static { AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin()).withPlugin(new ElasticBeanstalkPlugin()); URL ruleFile = WebConfig.class.getResource("/sampling-rules.json"); builder.withSamplingStrategy(new LocalizedSamplingStrategy(ruleFile)); AWSXRay.setGlobalRecorder(builder.build()); } }

O SDK também usa as configurações do plug-in para definir o campo origin no segmento. Isso indica o tipo de AWS recurso que executa seu aplicativo. Quando você usa vários plug-ins, o SDK usa a seguinte ordem de resolução para determinar a origem: ElasticBeanstalk > EKS > ECS > EC2.

Regras de amostragem

O SDK usa as regras de amostragem que você define no console do X-Ray para determinar quais solicitações serão registradas. A regra padrão rastreia a primeira solicitação a cada segundo e 5% de todas as solicitações adicionais em todos os serviços que enviam rastreamentos ao X-Ray. Crie regras adicionais no console do X-Ray para personalizar a quantidade de dados registrados para cada uma das aplicações.

O SDK aplica regras personalizadas na ordem em que elas estão definidas. Se uma solicitação corresponder a várias regras personalizadas, o SDK aplicará somente a primeira regra.

nota

Se o SDK não conseguir acessar o X-Ray para obter regras de amostragem, ele reverte para uma regra local padrão da primeira solicitação recebida no início de cada segundo e cinco por cento de todas as solicitações adicionais por host. Isso pode ocorrer se o host não tiver permissão para chamar APIs de amostragem ou não conseguir se conectar ao daemon do X-Ray, que atua como um proxy de TCP para chamadas de API feitas pelo SDK.

Você também pode configurar o SDK para carregar regras de amostragem de um documento JSON. O SDK pode usar regras locais como backup para casos em que a amostragem do X-Ray não está disponível ou usar exclusivamente regras locais.

exemplo sampling-rules.json
{ "version": 2, "rules": [ { "description": "Player moves.", "host": "*", "http_method": "*", "url_path": "/api/move/*", "fixed_target": 0, "rate": 0.05 } ], "default": { "fixed_target": 1, "rate": 0.1 } }

Este exemplo define uma regra personalizada e uma regra padrão. A regra personalizada aplica uma taxa de amostragem de 5% sem um número mínimo de solicitações para rastrear os caminhos em /api/move/. A regra padrão rastreia a primeira solicitação a cada segundo e 10% das solicitações adicionais.

A desvantagem de definir regras localmente é que o destino fixo é aplicado por instância do gravador de forma independente, em vez de ser gerenciado pelo serviço X-Ray. À medida que você implanta mais hosts, a taxa fixa é multiplicada, dificultando o controle da quantidade de dados registrados.

Ativado AWS Lambda, você não pode modificar a taxa de amostragem. Se sua função for chamada por um serviço instrumentado, as chamadas que geraram solicitações que foram amostradas por esse serviço serão registradas pelo Lambda. Se o rastreamento ativo estiver habilitado e nenhum cabeçalho de rastreamento estiver presente, o Lambda tomará a decisão de amostragem.

Para fornecer regras de backup em Spring, configure o gravador global com uma CentralizedSamplingStrategy em uma classe de configuração.

exemplo src/main/java/myapp/ .java WebConfig - configuração do gravador
import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.AWSXRayRecorderBuilder; import com.amazonaws.xray.javax.servlet.AWSXRayServletFilter; import com.amazonaws.xray.plugins.EC2Plugin; import com.amazonaws.xray.strategy.sampling.LocalizedSamplingStrategy; @Configuration public class WebConfig { static { AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin()); URL ruleFile = WebConfig.class.getResource("/sampling-rules.json"); builder.withSamplingStrategy(new CentralizedSamplingStrategy(ruleFile)); AWSXRay.setGlobalRecorder(builder.build()); }

Para Tomcat, adicione um listener que estenda ServletContextListener e registre o listener na descrição da implantação.

exemplo src/com/myapp/web/Startup.java
import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.AWSXRayRecorderBuilder; import com.amazonaws.xray.plugins.EC2Plugin; import com.amazonaws.xray.strategy.sampling.LocalizedSamplingStrategy; import java.net.URL; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class Startup implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent event) { AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin()); URL ruleFile = Startup.class.getResource("/sampling-rules.json"); builder.withSamplingStrategy(new CentralizedSamplingStrategy(ruleFile)); AWSXRay.setGlobalRecorder(builder.build()); } @Override public void contextDestroyed(ServletContextEvent event) { } }
exemplo WEB-INF/web.xml
... <listener> <listener-class>com.myapp.web.Startup</listener-class> </listener>

Para usar somente regras locais, substitua o CentralizedSamplingStrategy por uma LocalizedSamplingStrategy.

builder.withSamplingStrategy(new LocalizedSamplingStrategy(ruleFile));

Registro em log

Por padrão, o SDK envia mensagens de nível de ERROR da aplicação para os logs da aplicação. Você pode habilitar o registro em log em nível de depuração no SDK para gerar logs mais detalhados no arquivo de log da aplicação. Os níveis de log válidos são DEBUG, INFO, WARN, ERROR e FATAL. O nível de log FATAL silencia todas as mensagens de log porque o SDK não registra em log no nível fatal.

exemplo application.properties

Defina o nível de registro com a propriedade logging.level.com.amazonaws.xray.

logging.level.com.amazonaws.xray = DEBUG

Use logs de depuração para identificar problemas como subsegmentos não fechados ao gerar subsegmentos manualmente.

Injeção de ID de rastreamentos em logs

Para expor o ID de rastreamento totalmente qualificado atual às instruções de log, é possível injetar o ID no contexto de diagnóstico mapeado (MDC). Usando a interface SegmentListener, os métodos são chamados do gravador do X-Ray durante eventos do ciclo de vida do segmento. Quando um segmento ou subsegmento começa, o ID de rastreamento qualificado é injetado no MDC com a chave AWS-XRAY-TRACE-ID. Quando esse segmento termina, a chave é removida do MDC. Isso expõe o ID de rastreamento à biblioteca de log em uso. Quando um subsegmento termina, seu ID pai é injetado no MDC.

exemplo ID de rastreamento totalmente qualificado

O ID totalmente qualificado é representado como TraceID@EntityID

1-5df42873-011e96598b447dfca814c156@541b3365be3dafc3

Esse recurso funciona com aplicativos Java instrumentados com o AWS X-Ray SDK for Java e oferece suporte às seguintes configurações de registro:

  • API front-end SLF4J com backend Logback

  • API front-end SLF4J com backend Log4J2

  • API front-end Log4J2 com backend Log4J2

Consulte as guias a seguir para obter as necessidades de cada front-end e de cada backend.

SLF4J Frontend
  1. Adicione a seguinte dependência Maven ao seu projeto.

    <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-slf4j</artifactId> <version>2.11.0</version> </dependency>
  2. Inclua o método withSegmentListener ao construir o AWSXRayRecorder. Isso adiciona uma classe de SegmentListener que injeta automaticamente novos IDs de rastreamento no SLF4J MDC.

    O SegmentListener usa uma string opcional como um parâmetro para configurar o prefixo da instrução de log. O prefixo pode ser configurado das seguintes maneiras:

    • Nenhum: usa o prefixo AWS-XRAY-TRACE-ID padrão.

    • Vazio: usa uma string vazia (por exemplo, "").

    • Personalizado: usa um prefixo personalizado conforme definido na string.

    exemplo Instrução AWSXRayRecorderBuilder
    AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder .standard().withSegmentListener(new SLF4JSegmentListener("CUSTOM-PREFIX"));
Log4J2 front end
  1. Adicione a seguinte dependência Maven ao seu projeto.

    <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-log4j</artifactId> <version>2.11.0</version> </dependency>
  2. Inclua o método withSegmentListener ao construir o AWSXRayRecorder. Isso adicionará uma classe de SegmentListener, que injeta automaticamente novos IDs de rastreamento totalmente qualificados no SLF4J MDC.

    O SegmentListener usa uma string opcional como um parâmetro para configurar o prefixo da instrução de log. O prefixo pode ser configurado das seguintes maneiras:

    • Nenhum: usa o prefixo AWS-XRAY-TRACE-ID padrão.

    • Vazio: usa uma string vazia (por exemplo, "") e remove o prefixo.

    • Personalizado: usa o prefixo personalizado definido na string.

    exemplo Instrução AWSXRayRecorderBuilder
    AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder .standard().withSegmentListener(new Log4JSegmentListener("CUSTOM-PREFIX"));
Logback backend

Para inserir o ID de rastreamento em seus eventos de log, você deve modificar o PatternLayout do registrador de logs, que formata cada instrução de log.

  1. Localize onde o patternLayout está configurado. Isto pode ser feito programaticamente ou através de um arquivo de configuração XML. Para saber mais, consulte Configuração de Logback.

  2. Insira %X{AWS-XRAY-TRACE-ID} em qualquer lugar no patternLayout para inserir o ID de rastreamento em instruções de log futuras. O %X{} indica que você está recuperando um valor com a chave fornecida do MDC. Para saber mais sobre o PatternLayouts Logback, consulte PatternLayout.

Log4J2 backend
  1. Localize onde o patternLayout está configurado. Isto pode ser feito programaticamente ou através de um arquivo de configuração escrito no formato XML, JSON, YAML ou de propriedades.

    Para saber mais sobre como configurar o Log4J2 por meio de um arquivo de configuração, consulte Configuração.

    Para saber mais sobre como configurar o Log4J2 programaticamente, consulte Configuração programática.

  2. Insira %X{AWS-XRAY-TRACE-ID} em qualquer lugar no PatternLayout para inserir o ID de rastreamento em instruções de log futuras. O %X{} indica que você está recuperando um valor com a chave fornecida do MDC. Para saber mais sobre o PatternLayouts Log4J2, consulte Pattern Layout.

Exemplo de injeção de ID de rastreamento

A seguir, é mostrado uma string PatternLayout modificada para incluir o ID de rastreamento. O ID de rastreamento é impresso após o nome do thread (%t) e antes do nível de log (%-5p).

exemplo PatternLayout com injeção de ID
%d{HH:mm:ss.SSS} [%t] %X{AWS-XRAY-TRACE-ID} %-5p %m%n

AWS X-Ray imprime automaticamente a chave e o ID de rastreamento na instrução de log para facilitar a análise. A seguir é mostrada uma instrução de log usando o PatternLayout modificado.

exemplo Instrução de log com injeção de ID
2019-09-10 18:58:30.844 [nio-5000-exec-4] AWS-XRAY-TRACE-ID: 1-5d77f256-19f12e4eaa02e3f76c78f46a@1ce7df03252d99e1 WARN 1 - Your logging message here

A mensagem de log em si é alojada no %m padrão e definida ao chamar o registrador de log.

Listeners de segmento

Os listeners de segmento são uma interface para interceptar eventos de ciclo de vida, como o início e o fim de segmentos produzidos pelo AWSXRayRecorder. A implementação de uma função de evento do listener de segmento pode para adicionar a mesma anotação a todos os subsegmentos quando eles são criados com onBeginSubsegment, para registrar em log uma mensagem após cada segmento ser enviado para o daemon usando afterEndSegment ou para registrar consultas enviadas pelos interceptores SQL usando beforeEndSubsegment para verificar se o subsegmento representa uma consulta SQL, adicionando outros metadados em caso afirmativo.

Para ver a lista completa de funções SegmentListener, acesse a documentação do AWS X-Ray X-Ray Recorder SDK para Java API.

O exemplo a seguir mostra como adicionar uma anotação consistente a todos os subsegmentos na criação com onBeginSubsegment e imprimir uma mensagem de log no final de cada segmento com afterEndSegment.

exemplo MySegmentListener.java
import com.amazonaws.xray.entities.Segment; import com.amazonaws.xray.entities.Subsegment; import com.amazonaws.xray.listeners.SegmentListener; public class MySegmentListener implements SegmentListener { ..... @Override public void onBeginSubsegment(Subsegment subsegment) { subsegment.putAnnotation("annotationKey", "annotationValue"); } @Override public void afterEndSegment(Segment segment) { // Be mindful not to mutate the segment logger.info("Segment with ID " + segment.getId()); } }

Esse listener de segmento personalizado é então referenciado ao criar o AWSXRayRecorder.

exemplo AWSXRayRecorderBuilder declaração
AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder .standard().withSegmentListener(new MySegmentListener());

Variáveis de ambiente

Você pode usar variáveis de ambiente para configurar o X-Ray SDK para Java. O SDK é compatível com as variáveis a seguir.

  • AWS_XRAY_CONTEXT_MISSING: defina como RUNTIME_ERROR para lançar exceções, caso o código instrumentado tente registrar dados quando nenhum segmento estiver aberto.

    Valores válidos
    • RUNTIME_ERROR: lance uma exceção de tempo de execução.

    • LOG_ERROR: registre um erro e continue (padrão).

    • IGNORE_ERROR: ignore o erro e continue.

    Erros relativos a segmentos ou subsegmentos ausentes poderão ocorrer quando você tentar usar um cliente instrumentado no código de inicialização que é executado quando nenhuma solicitação estiver aberta ou em um código que gere um novo thread.

  • AWS_XRAY_DAEMON_ADDRESS: defina o host e a porta do receptor do daemon do X-Ray. Por padrão, o SDK usa 127.0.0.1:2000 para dados de rastreamento (UDP) e para amostragem (TCP). Use essa variável se você tiver configurado o daemon para escutar em uma porta diferente ou se ele estiver sendo executado em um host diferente.

    Formato
    • Mesma porta: address:port

    • Portas diferentes: tcp:address:port udp:address:port

  • AWS_LOG_GROUP— Defina o nome de um grupo de registros para o grupo de registros associado ao seu aplicativo. Se o seu grupo de registros usar a mesma AWS conta e região do seu aplicativo, o X-Ray pesquisará automaticamente os dados de segmento do seu aplicativo usando esse grupo de registros especificado. Para obter mais informações sobre grupos de registros, consulte Trabalhando com grupos e fluxos de registros.

  • AWS_XRAY_TRACING_NAME: defina um nome de serviço para o SDK usar para segmentos. Sobrepõe o nome do serviço que você definiu na estratégia de nomeação de segmentos do filtro do servlet.

As variáveis de ambiente substituem as propriedades do sistema equivalentes e os valores definidos no código.

Propriedades do sistema

É possível usar propriedades do sistema como uma alternativa específica de JVM a variáveis de ambiente. O SDK é compatível com as propriedades a seguir.

  • com.amazonaws.xray.strategy.tracingName: equivalente ao AWS_XRAY_TRACING_NAME.

  • com.amazonaws.xray.emitters.daemonAddress: equivalente ao AWS_XRAY_DAEMON_ADDRESS.

  • com.amazonaws.xray.strategy.contextMissingStrategy: equivalente ao AWS_XRAY_CONTEXT_MISSING.

Caso uma propriedade do sistema e a variável de ambiente equivalente sejam definidas, são usados os valores da variável de ambiente. Ambos os métodos substituem valores definidos no código.

Rastrear solicitações recebidas com o X-Ray SDK para Java

Você pode usar o X-Ray SDK para rastrear solicitações HTTP recebidas que seu aplicativo atende em uma instância do EC2 no Amazon EC2 ou no Amazon ECS. AWS Elastic Beanstalk

Use um Filter para instrumentar solicitações HTTP de entrada. Quando você adiciona o filtro de servlet do X-Ray à aplicação, o X-Ray SDK para Java cria um segmento para cada solicitação amostrada. Este segmento inclui tempo, método e disposição da solicitação HTTP. Instrumentação adicional cria subsegmentos sobre esse segmento.

nota

Para AWS Lambda funções, o Lambda cria um segmento para cada solicitação de amostra. Consulte AWS Lambda e AWS X-Ray Para mais informações.

Cada segmento tem um nome que identifica a aplicação no mapa de serviços. O segmento pode ser nomeado estaticamente ou você pode configurar o SDK para nomeá-lo dinamicamente com base no cabeçalho do host na solicitação de entrada. A nomeação dinâmica permite agrupar rastreamentos com base no nome de domínio na solicitação e aplicar um nome padrão se o nome não corresponder ao padrão esperado (por exemplo, se o cabeçalho do host for falsificado).

Solicitações encaminhadas

Se um balanceador de carga ou outro intermediário encaminhar uma solicitação para a aplicação, o X-Ray obterá o IP do cliente do cabeçalho X-Forwarded-For na solicitação em vez do IP de origem no pacote IP. O IP do cliente registrado para uma solicitação encaminhada pode ser falsificado; portanto, não é digno de confiança.

Quando uma solicitação é encaminhada, o SDK define um campo adicional no segmento para indicar isso. Se o segmento tiver o campo x_forwarded_for definido como true, isso significa que o IP do cliente foi obtido no cabeçalho X-Forwarded-For na solicitação HTTP.

O manipulador de mensagens cria um segmento para cada solicitação recebida com um bloco http que contém as seguintes informações:

  • Método HTTP: GET, POST, PUT, DELETE etc.

  • Endereço do cliente: o endereço IP do cliente que enviou a solicitação.

  • Código de resposta: o código de resposta HTTP da solicitação concluída.

  • Horário: a hora de início (quando a solicitação foi recebida) e a hora de término (quando a resposta foi enviada).

  • Agente do usuário: o user-agent da solicitação.

  • Tamanho do conteúdo: o content-length da resposta.

Adicionar um filtro de rastreamento ao aplicativo (Tomcat)

Para Tomcat, adicione um <filter> ao arquivo web.xml do seu projeto. Use o parâmetro fixedName para especificar um nome de serviço para aplicar a segmentos criados para solicitações recebidas.

exemplo WEB-INF/web.xml: Tomcat
<filter> <filter-name>AWSXRayServletFilter</filter-name> <filter-class>com.amazonaws.xray.javax.servlet.AWSXRayServletFilter</filter-class> <init-param> <param-name>fixedName</param-name> <param-value>MyApp</param-value> </init-param> </filter> <filter-mapping> <filter-name>AWSXRayServletFilter</filter-name> <url-pattern>*</url-pattern> </filter-mapping>

Adicionar um filtro de rastreamento ao aplicativo (spring)

Para Spring, adicione um Filter à classe WebConfig. Passe o nome do segmento para o construtor AWSXRayServletFilter como uma string.

exemplo src/main/java/myapp/ .java WebConfig - primavera
package myapp; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Bean; import javax.servlet.Filter; import com.amazonaws.xray.javax.servlet.AWSXRayServletFilter; @Configuration public class WebConfig { @Bean public Filter TracingFilter() { return new AWSXRayServletFilter("Scorekeep"); } }

Configurar uma estratégia de nomeação de segmentos

AWS X-Ray usa um nome de serviço para identificar seu aplicativo e diferenciá-lo dos outros aplicativos, bancos de dados, APIs externas e AWS recursos que seu aplicativo usa. Quando o X-Ray SDK gera segmentos para solicitações recebidas, ele registra o nome do serviço da aplicação no campo de nome do segmento.

O X-Ray SDK pode nomear segmentos com o nome do host no cabeçalho da solicitação HTTP. No entanto, esse cabeçalho pode ser falsificado, o que pode resultar em nós inesperados no mapa de serviço. Para evitar que o SDK nomeie segmentos incorretamente devido a solicitações com cabeçalhos de host falsificados, você deve especificar um nome padrão para as solicitações recebidas.

Se a aplicação atende a solicitações para vários domínios, você pode configurar o SDK para usar uma estratégia de nomeação dinâmica para refletir isso nos nomes dos segmentos. Uma estratégia de nomeação dinâmica permite que o SDK use o nome do host para solicitações que correspondam a um padrão esperado e aplique o nome padrão às solicitações que não correspondem.

Por exemplo, você pode ter uma única aplicação para atender a solicitações para três subdomínios: www.example.com, api.example.com e static.example.com Você pode usar uma estratégia de nomeação dinâmica com o padrão *.example.com a fim de identificar segmentos para cada subdomínio com um nome diferente, o que resulta em três nós de serviço no mapa de serviços. Se a aplicação receber solicitações com um nome de host que não corresponda ao padrão, você verá um quarto nó no mapa de serviços com um nome alternativo especificado por você.

Para usar o mesmo nome para todos os segmentos de solicitação, especifique o nome do seu aplicativo ao inicializar o filtro de servlet, como mostrado na seção anterior. Isso tem o mesmo efeito que criar uma correção SegmentNamingStrategychamando-a SegmentNamingStrategy.fixed() e passando-a para o AWSXRayServletFilterconstrutor.

nota

Você pode sobrepor o nome do serviço padrão que definiu no código com a variável de ambiente AWS_XRAY_TRACING_NAME.

Uma estratégia de nomenclatura dinâmica define um padrão que os nomes de host devem corresponder, e um nome padrão a ser usado se o nome do host na solicitação HTTP não corresponder ao padrão. Para nomear segmentos dinamicamente no Tomcat, use o dynamicNamingRecognizedHosts e o dynamicNamingFallbackName para definir o padrão e o nome padrão, respectivamente.

exemplo WEB-INF/web.xml – filtro de servlet com nomeação dinâmica
<filter> <filter-name>AWSXRayServletFilter</filter-name> <filter-class>com.amazonaws.xray.javax.servlet.AWSXRayServletFilter</filter-class> <init-param> <param-name>dynamicNamingRecognizedHosts</param-name> <param-value>*.example.com</param-value> </init-param> <init-param> <param-name>dynamicNamingFallbackName</param-name> <param-value>MyApp</param-value> </init-param> </filter> <filter-mapping> <filter-name>AWSXRayServletFilter</filter-name> <url-pattern>*</url-pattern> </filter-mapping>

Para Spring, crie uma dinâmica SegmentNamingStrategySegmentNamingStrategy.dynamic()chamando e passe-a para o AWSXRayServletFilter construtor.

exemplo src/main/java/myapp/ .java WebConfig - filtro de servlet com nomenclatura dinâmica
package myapp; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Bean; import javax.servlet.Filter; import com.amazonaws.xray.javax.servlet.AWSXRayServletFilter; import com.amazonaws.xray.strategy.SegmentNamingStrategy; @Configuration public class WebConfig { @Bean public Filter TracingFilter() { return new AWSXRayServletFilter(SegmentNamingStrategy.dynamic("MyApp", "*.example.com")); } }

Rastreando chamadas AWS do SDK com o X-Ray SDK for Java

Quando seu aplicativo faz chamadas Serviços da AWS para armazenar dados, gravar em uma fila ou enviar notificações, o X-Ray SDK for Java rastreia as chamadas downstream em subsegmentos. Os recursos rastreados Serviços da AWS e que você acessa nesses serviços (por exemplo, um bucket do Amazon S3 ou uma fila do Amazon SQS) aparecem como nós downstream no mapa de rastreamento no console X-Ray.

O X-Ray SDK para Java instrumenta automaticamente todos os clientes de SDK da AWS quando você inclui o aws-sdk e submódulos aws-sdk-instrumentor na compilação. Se você não incluir o submódulo Instrumentor, poderá optar por instrumentar alguns clientes e, ao mesmo tempo, excluir outros.

Para instrumentar clientes individuais, remova o aws-sdk-instrumentor submódulo da sua compilação e adicione um XRayClient como TracingHandler em seu cliente AWS SDK usando o construtor de clientes do serviço.

Por exemplo, para instrumentar um cliente AmazonDynamoDB, transmita um manipulador de rastreamento para AmazonDynamoDBClientBuilder.

exemplo MyModel.java - cliente do DynamoDB
import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.handlers.TracingHandler; ... public class MyModel { private AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard() .withRegion(Regions.fromName(System.getenv("AWS_REGION"))) .withRequestHandlers(new TracingHandler(AWSXRay.getGlobalRecorder())) .build(); ...

Para todos os serviços, o nome da API chamada no console do X-Ray pode ser visto. Para um subconjunto de serviços, o X-Ray SDK adiciona informações ao segmento para fornecer maior detalhamento no mapa de serviços.

Por exemplo, quando você faz uma chamada com um cliente instrumentado do DynamoDB, o SDK adiciona o nome da tabela ao segmento para chamadas direcionadas a uma tabela. No console, cada tabela aparece como um nó separado no mapa de serviços, com um nó genérico do DynamoDB para chamadas não direcionadas a uma tabela.

exemplo Subsegmento para uma chamada ao DynamoDB para salvar um item
{ "id": "24756640c0d0978a", "start_time": 1.480305974194E9, "end_time": 1.4803059742E9, "name": "DynamoDB", "namespace": "aws", "http": { "response": { "content_length": 60, "status": 200 } }, "aws": { "table_name": "scorekeep-user", "operation": "UpdateItem", "request_id": "UBQNSO5AEM8T4FDA4RQDEB94OVTDRVV4K4HIRGVJF66Q9ASUAAJG", } }

Ao acessar recursos nomeados, as chamadas para os serviços os seguir criam nós adicionais no mapa de serviço. As chamadas que não apontam para recursos específicos criam um nó genérico para o serviço.

  • Amazon DynamoDB: nome da tabela

  • Amazon Simple Storage Service: nome de chave e bucket

  • Amazon Simple Queue Service: nome da fila

Para instrumentar chamadas downstream para Serviços da AWS com AWS SDK for Java 2.2 e versões posteriores, você pode omitir o aws-xray-recorder-sdk-aws-sdk-v2-instrumentor módulo da sua configuração de compilação. Inclua o aws-xray-recorder-sdk-aws-sdk-v2 module em seu lugar e instrumente clientes individuais, configurando-os com um TracingInterceptor.

exemplo AWS SDK for Java 2.2 e posterior - interceptor de rastreamento
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(); //...

Rastrear chamadas para serviços da web HTTP subsequentes com o X-Ray SDK para Java

Quando a aplicação faz chamadas para microsserviços ou APIs HTTP públicas, você pode usar a versão HttpClient do X-Ray SDK para Java para instrumentar essas chamadas e adicionar a API ao gráfico de serviço como um serviço subsequente.

O X-Ray SDK for Java DefaultHttpClient inclui HttpClientBuilder classes que podem ser usadas no lugar dos equivalentes do HttpComponents Apache para instrumentar chamadas HTTP de saída.

  • com.amazonaws.xray.proxies.apache.http.DefaultHttpClient - org.apache.http.impl.client.DefaultHttpClient

  • com.amazonaws.xray.proxies.apache.http.HttpClientBuilder - org.apache.http.impl.client.HttpClientBuilder

Essas bibliotecas estão no submódulo aws-xray-recorder-sdk-apache-http.

Você pode substituir as instruções de importação existentes pelo X-Ray equivalente para instrumentar todos os clientes ou usar o nome totalmente qualificado quando inicializar um cliente para instrumentar clientes específicos.

exemplo HttpClientBuilder
import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; import com.amazonaws.xray.proxies.apache.http.HttpClientBuilder; ... public String randomName() throws IOException { CloseableHttpClient httpclient = HttpClientBuilder.create().build(); HttpGet httpGet = new HttpGet("http://names.example.com/api/"); CloseableHttpResponse response = httpclient.execute(httpGet); try { HttpEntity entity = response.getEntity(); InputStream inputStream = entity.getContent(); ObjectMapper mapper = new ObjectMapper(); Map<String, String> jsonMap = mapper.readValue(inputStream, Map.class); String name = jsonMap.get("name"); EntityUtils.consume(entity); return name; } finally { response.close(); } }

Quando você instrumenta uma chamada para uma API subsequente da web, o X-Ray SDK para Java registra um subsegmento com informações sobre a solicitação e a resposta HTTP. O X-Ray usa o subsegmento para gerar um segmento inferido para a API remota.

exemplo Subsegmento para uma chamada HTTP downstream
{ "id": "004f72be19cddc2a", "start_time": 1484786387.131, "end_time": 1484786387.501, "name": "names.example.com", "namespace": "remote", "http": { "request": { "method": "GET", "url": "https://names.example.com/" }, "response": { "content_length": -1, "status": 200 } } }
exemplo Segmento inferido para uma chamada HTTP de downstream
{ "id": "168416dc2ea97781", "name": "names.example.com", "trace_id": "1-62be1272-1b71c4274f39f122afa64eab", "start_time": 1484786387.131, "end_time": 1484786387.501, "parent_id": "004f72be19cddc2a", "http": { "request": { "method": "GET", "url": "https://names.example.com/" }, "response": { "content_length": -1, "status": 200 } }, "inferred": true }

Rastrear consultas SQL com o X-Ray SDK para Java

Interceptores SQL

Instrumente consultas SQL adicionando o interceptor JDBC do X-Ray SDK para Java à configuração da fonte de dados.

  • PostgreSQL: com.amazonaws.xray.sql.postgres.TracingInterceptor

  • MySQL: com.amazonaws.xray.sql.mysql.TracingInterceptor

Esses interceptores estão nos aws-xray-recorder-sql-postgres e aws-xray-recorder-sql-mysqlsubmódulos, respectivamente. Eles implementam org.apache.tomcat.jdbc.pool.JdbcInterceptor e são compatíveis com grupos de conexão do Tomcat.

nota

Interceptores SQL não registram a consulta SQL em si dentro de subsegmentos para fins de segurança.

Para Spring, adicione o interceptor em um arquivo de propriedades e crie a fonte de dados com o DataSourceBuilder do Spring Boot.

exemplo src/main/java/resources/application.properties – interceptador PostgreSQL JDBC
spring.datasource.continue-on-error=true spring.jpa.show-sql=false spring.jpa.hibernate.ddl-auto=create-drop spring.datasource.jdbc-interceptors=com.amazonaws.xray.sql.postgres.TracingInterceptor spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL94Dialect
exemplo src/main/java/myapp/WebConfig.java – fonte de dados
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import javax.servlet.Filter; import javax.sql.DataSource; import java.net.URL; @Configuration @EnableAutoConfiguration @EnableJpaRepositories("myapp") public class RdsWebConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource dataSource() { logger.info("Initializing PostgreSQL datasource"); return DataSourceBuilder.create() .driverClassName("org.postgresql.Driver") .url("jdbc:postgresql://" + System.getenv("RDS_HOSTNAME") + ":" + System.getenv("RDS_PORT") + "/ebdb") .username(System.getenv("RDS_USERNAME")) .password(System.getenv("RDS_PASSWORD")) .build(); } ... }

Para Tomcat, chame setJdbcInterceptors na fonte de dados JDBC com uma referência à classe do X-Ray SDK para Java.

exemplo src/main/myapp/model.java – fonte de dados
import org.apache.tomcat.jdbc.pool.DataSource; ... DataSource source = new DataSource(); source.setUrl(url); source.setUsername(user); source.setPassword(password); source.setDriverClassName("com.mysql.jdbc.Driver"); source.setJdbcInterceptors("com.amazonaws.xray.sql.mysql.TracingInterceptor;");

A biblioteca da fonte de dados JDBC Tomcat está incluída no X-Ray SDK para Java, mas é possível declará-la como uma dependência fornecida para documentar que você a usa.

exemplo pom.xml – fonte de dados JDBC
<dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jdbc</artifactId> <version>8.0.36</version> <scope>provided</scope> </dependency>

Decorador de rastreamento SQL nativo

  • Adicione aws-xray-recorder-sdk-sql às suas dependências.

  • Decore sua fonte de dados, conexão ou declaração Decorate banco de dados.

    dataSource = TracingDataSource.decorate(dataSource) connection = TracingConnection.decorate(connection) statement = TracingStatement.decorateStatement(statement) preparedStatement = TracingStatement.decoratePreparedStatement(preparedStatement, sql) callableStatement = TracingStatement.decorateCallableStatement(callableStatement, sql)

Gerar subsegmentos personalizados com o X-Ray SDK para Java

Os subsegmentos estendem o segmento de um rastreamento com detalhes sobre o trabalho realizado para atender a uma solicitação. Sempre que você faz uma chamada com um cliente instrumentado, o X-Ray SDK registra as informações geradas em um subsegmento. Você pode criar subsegmentos adicionais para agrupar outros subsegmentos, medir o desempenho de uma seção do código ou registrar anotações e metadados.

Para gerenciar subsegmentos, use os métodos beginSubsegment e endSubsegment.

exemplo GameModel.java - subsegmento personalizado
import com.amazonaws.xray.AWSXRay; ... public void saveGame(Game game) throws SessionNotFoundException { // wrap in subsegment Subsegment subsegment = AWSXRay.beginSubsegment("Save Game"); try { // check session String sessionId = game.getSession(); if (sessionModel.loadSession(sessionId) == null ) { throw new SessionNotFoundException(sessionId); } mapper.save(game); } catch (Exception e) { subsegment.addException(e); throw e; } finally { AWSXRay.endSubsegment(); } }

Neste exemplo, o código dentro do subsegmento carrega a sessão do jogo do DynamoDB com um método no modelo de sessão e usa o mapeador do DynamoDB para AWS SDK for Java salvar o jogo. O encapsulamento desse código em um subsegmento transforma as chamadas do DynamoDB em filhas do subsegmento Save Game na visualização de rastreamento no console.

Se o código no seu subsegmento lança exceções verificadas, encapsule-o em um bloco try e chame AWSXRay.endSubsegment() em um bloco finally para garantir que o subsegmento esteja sempre fechado. Se um subsegmento não estiver fechado, o segmento pai não poderá ser concluído e não será enviado para o X-Ray.

Para código que não lança exceções verificadas, você pode transmitir o código para AWSXRay.CreateSubsegment como uma função do Lambda.

exemplo Função de subsegmento do Lambda
import com.amazonaws.xray.AWSXRay; AWSXRay.createSubsegment("getMovies", (subsegment) -> { // function code });

Quando você cria um subsegmento dentro de um segmento ou outro subsegmento, o X-Ray SDK para Java gera um ID para ele e registra a hora de início e de término.

exemplo Subsegmento com metadados
"subsegments": [{ "id": "6f1605cd8a07cb70", "start_time": 1.480305974194E9, "end_time": 1.4803059742E9, "name": "Custom subsegment for UserModel.saveUser function", "metadata": { "debug": { "test": "Metadata string from UserModel.saveUser" } },

Para programação assíncrona e com vários threads, você deve passar manualmente o subsegmento para o método endSubsegment() para garantir que ele seja fechado corretamente, pois o contexto do X-Ray pode ser modificado durante a execução assíncrona. Se um subsegmento assíncrono for fechado após o fechamento do segmento pai, esse método transmitirá automaticamente o segmento inteiro para o daemon do X-Ray.

exemplo Subsegmento assíncrono
@GetMapping("/api") public ResponseEntity<?> api() { CompletableFuture.runAsync(() -> { Subsegment subsegment = AWSXRay.beginSubsegment("Async Work"); try { Thread.sleep(3000); } catch (InterruptedException e) { subsegment.addException(e); throw e; } finally { AWSXRay.endSubsegment(subsegment); } }); return ResponseEntity.ok().build(); }

Adicionar anotações e metadados aos segmentos com o X-Ray SDK para Java

Você pode usar anotações e metadados para registrar informações adicionais sobre solicitações, o ambiente ou seu aplicativo. Também é possível adicionar anotações e metadados aos segmentos que o X-Ray SDK cria ou aos subsegmentos personalizados que você cria.

Anotações são pares de chave-valor com valores boolianos, de string ou número. As anotações são indexadas para serem usadas com expressões de filtro. Use anotações para registrar dados que você deseja usar para agrupar rastreamentos no console ou ao chamar a API GetTraceSummaries.

Metadados são pares chave-valor que podem ter valores de qualquer tipo, incluindo objetos e listas, mas não são indexados para uso com expressões de filtro. Use metadados para registrar dados adicionais que você deseja armazenar no rastreamento e não precisa usar com a pesquisa.

Além de anotações e metadados, você também pode registrar strings de ID de usuário em segmentos. Os IDs de usuário são registrados em um campo separado nos segmentos e são indexados para serem usados com pesquisa.

Registrar anotações com o X-Ray SDK para Java

Use anotações para registrar informações em segmentos ou subsegmentos que você deseja indexar para pesquisa.

Requisitos de anotação
  • Teclas — A chave para uma anotação de X-Ray pode ter até 500 caracteres alfanuméricos. Você não pode usar espaços ou símbolos que não sejam o símbolo de sublinhado (_).

  • Valores — O valor de uma anotação X-Ray pode ter até 1.000 caracteres Unicode.

  • O número de anotações — Você pode usar até 50 anotações por rastreamento.

Como registrar anotações
  1. Obtenha uma referência para o segmento ou subsegmento atual no AWSXRay.

    import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Segment; ... Segment document = AWSXRay.getCurrentSegment();

    ou

    import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Subsegment; ... Subsegment document = AWSXRay.getCurrentSubsegment();
  2. Chame putAnnotation com uma chave de string e um valor de número, string ou booleano.

    document.putAnnotation("mykey", "my value");

O SDK registra anotações como pares de chave-valor em um objeto annotations no documento de segmentos. Chamar putAnnotation duas vezes com a mesma chave substitui os valores registrados anteriormente no mesmo segmento ou subsegmento.

Para encontrar rastreamentos que têm anotações com valores específicos, use a palavra-chave annotations.key em uma expressão de filtro.

exemplo src/main/java/scorekeep/GameModel.java: anotações e metadados
import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Segment; import com.amazonaws.xray.entities.Subsegment; ... public void saveGame(Game game) throws SessionNotFoundException { // wrap in subsegment Subsegment subsegment = AWSXRay.beginSubsegment("## GameModel.saveGame"); try { // check session String sessionId = game.getSession(); if (sessionModel.loadSession(sessionId) == null ) { throw new SessionNotFoundException(sessionId); } Segment segment = AWSXRay.getCurrentSegment(); subsegment.putMetadata("resources", "game", game); segment.putAnnotation("gameid", game.getId()); mapper.save(game); } catch (Exception e) { subsegment.addException(e); throw e; } finally { AWSXRay.endSubsegment(); } }

Registrar metadados com o X-Ray SDK para Java

Use metadados para registrar informações em segmentos ou subsegmentos dos quais você não precisa indexados para pesquisa. Valores de metadados podem ser strings, números, boolianos ou qualquer objeto que possa ser serializado em uma matriz ou objeto JSON.

Como registrar metadados
  1. Obtenha uma referência para o segmento ou subsegmento atual no AWSXRay.

    import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Segment; ... Segment document = AWSXRay.getCurrentSegment();

    ou

    import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Subsegment; ... Subsegment document = AWSXRay.getCurrentSubsegment();
  2. Chame putMetadata com um namespace de string e uma chave de string e um valor booleano, de número, string ou objeto.

    document.putMetadata("my namespace", "my key", "my value");

    ou

    Chame putMetadata com apenas uma chave e valor.

    document.putMetadata("my key", "my value");

Se você não especificar um namespace, o SDK usará default. Chamar putMetadata duas vezes com a mesma chave substitui os valores registrados anteriormente no mesmo segmento ou subsegmento.

exemplo src/main/java/scorekeep/GameModel.java: anotações e metadados
import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Segment; import com.amazonaws.xray.entities.Subsegment; ... public void saveGame(Game game) throws SessionNotFoundException { // wrap in subsegment Subsegment subsegment = AWSXRay.beginSubsegment("## GameModel.saveGame"); try { // check session String sessionId = game.getSession(); if (sessionModel.loadSession(sessionId) == null ) { throw new SessionNotFoundException(sessionId); } Segment segment = AWSXRay.getCurrentSegment(); subsegment.putMetadata("resources", "game", game); segment.putAnnotation("gameid", game.getId()); mapper.save(game); } catch (Exception e) { subsegment.addException(e); throw e; } finally { AWSXRay.endSubsegment(); } }

Registrar IDs de usuário com o X-Ray SDK para Java

Registre IDs de usuário em segmentos de solicitação para identificar o usuário que enviou a solicitação.

Para registrar IDs de usuário
  1. Obtenha uma referência para o segmento atual em AWSXRay.

    import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Segment; ... Segment document = AWSXRay.getCurrentSegment();
  2. Chame setUser com um ID de string do usuário que enviou a solicitação.

    document.setUser("U12345");

Você pode acionar setUser em seus controladores para registrar o ID de usuário assim que a aplicação começar a processar uma solicitação. Se pretende usar o segmento apenas para definir o ID de usuário, você pode vincular as chamadas em uma única linha.

exemplo src/main/java/scorekeep/ .java MoveController — ID do usuário
import com.amazonaws.xray.AWSXRay; ... @RequestMapping(value="/{userId}", method=RequestMethod.POST) public Move newMove(@PathVariable String sessionId, @PathVariable String gameId, @PathVariable String userId, @RequestBody String move) throws SessionNotFoundException, GameNotFoundException, StateNotFoundException, RulesException { AWSXRay.getCurrentSegment().setUser(userId); return moveFactory.newMove(sessionId, gameId, userId, move); }

Para encontrar rastreamentos para um ID de usuário, use a user palavra-chave em uma expressão de filtragem.

AWS X-Ray métricas para o X-Ray SDK for Java

Este tópico descreve o AWS X-Ray namespace, as métricas e as dimensões. Você pode usar o X-Ray SDK for Java para publicar métricas sem amostragem da CloudWatch Amazon a partir dos segmentos coletados do X-Ray. Essas métricas são derivadas da hora de início e término do segmento e dos sinalizadores de status de erro, falha e limitação. Use essas métricas de rastreamento para expor novas tentativas e problemas de dependência dentro de subsegmentos.

CloudWatch é um repositório de métricas. Uma métrica é o conceito fundamental CloudWatch e representa um conjunto de pontos de dados ordenado pelo tempo. Você (ou Serviços da AWS) publica pontos de dados de métricas CloudWatch e recupera estatísticas sobre esses pontos de dados como um conjunto ordenado de dados de séries temporais.

As métricas são definidas exclusivamente por um nome, um namespace e uma ou mais dimensões. Cada ponto de dados tem um timestamp e, opcionalmente, uma unidade de medida. Quando você solicita estatísticas, o fluxo de dados apresentado é identificado pelo namespace, pelo nome da métrica e pela dimensão.

Para obter mais informações sobre CloudWatch, consulte o Guia CloudWatch do usuário da Amazon.

CloudWatch Métricas de X-Ray

O namespace ServiceMetrics/SDK inclui as métricas a seguir.

Métrica Estatísticas disponíveis Descrição Unidades

Latency

Média, Mínimo Máximo, Contagem

A diferença entre a hora de início e de término. A média, o mínimo e o máximo descrevem a latência operacional. A contagem descreve a contagem de chamadas.

Milissegundos

ErrorRate

Média, Soma

A taxa de solicitações que falharam com um código de status 4xx Client Error, resultando em um erro.

Percentual

FaultRate

Média, Soma

A taxa de rastreamentos que falharam com um código de status 5xx Server Error, resultando em uma falha.

Percentual

ThrottleRate

Média, Soma

A taxa de rastreamentos limitados que retornam um código de status 429. Este é um subconjunto da métrica ErrorRate.

Percentual

OkRate

Média, Soma

A taxa de solicitações rastreadas que resultam em um código de status OK.

Percentual

CloudWatch Dimensões do X-Ray

Use as dimensões na tabela a seguir para refinar as métricas retornadas para seus aplicativos instrumentados Java por X-Ray.

Dimensão Descrição

ServiceType

O tipo do serviço, por exemplo, AWS::EC2::Instance ou NONE, se não for conhecido.

ServiceName

O nome canônico do serviço.

Ativar CloudWatch métricas de X-Ray

Use o procedimento a seguir para ativar métricas de rastreamento em seu Java aplicativo instrumentado.

Para configurar métricas de rastreamento
  1. Adicione o aws-xray-recorder-sdk-metrics pacote como uma Apache Maven dependência. Para obter mais informações, consulte Submódulos do X-Ray SDK para Java.

  2. Ative um novo MetricsSegmentListener() como parte da compilação global de gravador.

    exemplo src/com/myapp/web/Startup.java
    import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.AWSXRayRecorderBuilder; import com.amazonaws.xray.plugins.EC2Plugin; import com.amazonaws.xray.plugins.ElasticBeanstalkPlugin; import com.amazonaws.xray.strategy.sampling.LocalizedSamplingStrategy; @Configuration public class WebConfig { ... static { AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder .standard() .withPlugin(new EC2Plugin()) .withPlugin(new ElasticBeanstalkPlugin()) .withSegmentListener(new MetricsSegmentListener()); URL ruleFile = WebConfig.class.getResource("/sampling-rules.json"); builder.withSamplingStrategy(new LocalizedSamplingStrategy(ruleFile)); AWSXRay.setGlobalRecorder(builder.build()); } }
  3. Implante o CloudWatch agente para coletar métricas usando o Amazon Elastic Compute Cloud (Amazon EC2), o Amazon Elastic Container Service (Amazon ECS) ou o Amazon Elastic Kubernetes Service (Amazon EKS):

  4. Configure o SDK para se comunicar com o CloudWatch agente. Por padrão, o SDK se comunica com o CloudWatch agente no endereço. 127.0.0.1 É possível configurar endereços alternativos definindo a variável de ambiente ou a propriedade do Java como address:port.

    exemplo Variável de ambiente
    AWS_XRAY_METRICS_DAEMON_ADDRESS=address:port
    exemplo Propriedade do Java
    com.amazonaws.xray.metrics.daemonAddress=address:port
Para validar a configuração
  1. Faça login no AWS Management Console e abra o CloudWatch console em https://console.aws.amazon.com/cloudwatch/.

  2. Abra a guia Métricas para observar o influxo de suas métricas.

  3. (Opcional) No CloudWatch console, na guia Registros, abra o grupo de ServiceMetricsSDK registros. Procure um fluxo de log que corresponda às métricas do host e confirme as mensagens de log.

Passar o contexto do segmento entre threads em um aplicativo multithreaded

Quando você cria um novo thread em seu aplicativo, o AWSXRayRecorder não mantém uma referência à entidade do segmento atual ou subsegmento. Se você usar um cliente instrumentado na nova linha de execução, o SDK tentará gravar em um segmento que não existe, causando uma. SegmentNotFoundException

Para evitar o lançamento de exceções durante o desenvolvimento, você pode configurar o gravador com um ContextMissingStrategyque solicita que ele registre um erro em vez disso. Você pode configurar a estratégia no código com SetContextMissingStrategy, ou configurar opções equivalentes com uma variável de ambiente ou propriedade do sistema.

Uma maneira de resolver o erro é usar um novo segmento chamando beginSegment quando iniciar o thread e endSegment quando fechá-lo. Isso funciona se você estiver instrumentando código que não seja executado em uma solicitação HTTP, como código que é executado quando seu aplicativo é iniciado.

Se usar vários threads para lidar com solicitações de entrada, você poderá passar o segmento ou subsegmento atual para o novo thread e fornecê-lo ao gravador global. Isso garante que as informações gravadas no novo thread sejam associadas ao mesmo segmento como o restante das informações gravadas sobre essa solicitação. Quando o segmento estiver disponível no novo thread, você poderá executar qualquer executável com acesso ao contexto desse segmento usando o método segment.run(() -> { ... }).

Consulte Usar clientes instrumentais em threads de operador para ver um exemplo.

Usar o X-Ray com programação assíncrona

O X-Ray SDK for Java pode ser usado em programas Java assíncronos com. SegmentContextExecutors O SegmentContextExecutor implementa a interface do Executor, o que significa que ela pode ser passada para todas as operações assíncronas de um. CompletableFuture Isso garante que todas as operações assíncronas sejam executadas com o segmento correto no respectivo contexto.

exemplo Exemplo de App.java: Passando SegmentContextExecutor para CompletableFuture
DynamoDbAsyncClient client = DynamoDbAsyncClient.create(); AWSXRay.beginSegment(); // ... client.getItem(request).thenComposeAsync(response -> { // If we did not provide the segment context executor, this request would not be traced correctly. return client.getItem(request2); }, SegmentContextExecutors.newSegmentContextExecutor());

AOP com o Spring e X-Ray SDK para Java

Este tópico descreve como usar o X-Ray SDK e o Spring Framework para instrumentar a aplicação sem alterar a lógica central. Isso significa que agora existe uma forma não invasiva de instrumentar seus aplicativos executados remotamente. AWS

Configurar o Spring

Você pode usar o Maven ou o Gradle para configurar o Spring para usar AOP para instrumentar seu aplicativo.

Se você usar o Maven para compilar seu aplicativo, adicione a dependência a seguir no arquivo pom.xml.

<dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-spring</artifactId> <version>2.11.0</version> </dependency>

Para o Gradle, adicione a seguinte dependência no arquivo build.gradle.

compile 'com.amazonaws:aws-xray-recorder-sdk-spring:2.11.0'

Configurar o Spring Boot

Além da dependência do Spring descrita na seção anterior, se você estiver usando o Spring Boot, adicione a seguinte dependência se ela ainda não estiver no classpath.

Maven:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> <version>2.5.2</version> </dependency>

Gradle:

compile 'org.springframework.boot:spring-boot-starter-aop:2.5.2'

Adicionar um filtro de rastreamento à aplicação

Adicione um Filter à classe WebConfig. Passe o nome do segmento para o construtor AWSXRayServletFilter como uma string. Para obter mais informações sobre filtros de rastreamento e instrumentar solicitações de entrada, consulte Rastrear solicitações recebidas com o X-Ray SDK para Java.

exemplo src/main/java/myapp/ .java WebConfig - primavera
package myapp; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Bean; import javax.servlet.Filter; import com.amazonaws.xray.javax.servlet.AWSXRayServletFilter; @Configuration public class WebConfig { @Bean public Filter TracingFilter() { return new AWSXRayServletFilter("Scorekeep"); } }

Suporta a Jakarta

O Spring 6 usa Jakarta em vez de Javax na Enterprise Edition. Para oferecer compatibilidade com esse novo namespace, o X-Ray criou um conjunto paralelo de classes que residem em seu próprio namespace Jacarta.

Para as classes de filtro, substitua javax por jakarta. Ao configurar uma estratégia de nomeação de segmentos, adicione jakarta antes do nome da classe da estratégia, como no seguinte exemplo:

package myapp; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Bean; import jakarta.servlet.Filter; import com.amazonaws.xray.jakarta.servlet.AWSXRayServletFilter; import com.amazonaws.xray.strategy.jakarta.SegmentNamingStrategy; @Configuration public class WebConfig { @Bean public Filter TracingFilter() { return new AWSXRayServletFilter(SegmentNamingStrategy.dynamic("Scorekeep")); } }

Anotar o código ou implementar uma interface

Anote suas classes com a anotação @XRayEnabled ou implemente a interface XRayTraced. Isso informa ao sistema de AOP para encapsular as funções da classe afetada para a instrumentação do X-Ray.

Ativar o X-Ray na aplicação

Para ativar o rastreamento do X-Ray na aplicação, o código deve estender a classe abstrata BaseAbstractXRayInterceptor substituindo os métodos a seguir.

  • generateMetadata: esta função permite a personalização dos metadados anexados ao rastreamento da função atual. Por padrão, o nome de classe da função de execução é registrada nos metadados. Você pode adicionar mais dados se precisar de informações adicionais.

  • xrayEnabledClasses: esta função está vazia e deve permanecer assim. Ela serve como host para um pointcut, instruindo o interceptor sobre quais métodos devem ser encapsulados. Defina o pointcut especificando quais das classes que estão anotadas com @XRayEnabled serão rastreadas. A seguinte instrução de pointcut informa ao interceptor para encapsular todos os beans do controlador anotados com a anotação @XRayEnabled.

    @Pointcut(“@within(com.amazonaws.xray.spring.aop.XRayEnabled) && bean(*Controller)”)

Se seu projeto estiver usando o Spring Data JPA, considere a possibilidade de estender de AbstractXRayInterceptor em vez de BaseAbstractXRayInterceptor.

Exemplo

O código a seguir estende a classe abstrata BaseAbstractXRayInterceptor.

@Aspect @Component public class XRayInspector extends BaseAbstractXRayInterceptor { @Override protected Map<String, Map<String, Object>> generateMetadata(ProceedingJoinPoint proceedingJoinPoint, Subsegment subsegment) throws Exception { return super.generateMetadata(proceedingJoinPoint, subsegment); } @Override @Pointcut("@within(com.amazonaws.xray.spring.aop.XRayEnabled) && bean(*Controller)") public void xrayEnabledClasses() {} }

O código a seguir é uma classe que será instrumentada pelo X-Ray.

@Service @XRayEnabled public class MyServiceImpl implements MyService { private final MyEntityRepository myEntityRepository; @Autowired public MyServiceImpl(MyEntityRepository myEntityRepository) { this.myEntityRepository = myEntityRepository; } @Transactional(readOnly = true) public List<MyEntity> getMyEntities(){ try(Stream<MyEntity> entityStream = this.myEntityRepository.streamAll()){ return entityStream.sorted().collect(Collectors.toList()); } } }

Se você tiver configurado seu aplicativo corretamente, deverá ver a pilha de chamadas completa do aplicativo, do controlador até as chamadas de serviço, conforme mostrado na captura de tela do console a seguir.

A pilha de chamadas completa.