Exemplo de instrumentação Java

Este documento descreve como modificar uma app Java para recolher dados de rastreio e métricas através da framework de código aberto OpenTelemetry e como escrever registos JSON estruturados para a saída padrão. Este documento também fornece informações sobre uma app de exemplo do Java Spring Boot que pode instalar e executar. A app está configurada para gerar métricas, rastreios e registos. Os passos são os mesmos, quer esteja ou não a usar o Spring Boot Framework.

Para saber mais sobre a instrumentação, consulte os seguintes documentos:

Acerca da instrumentação manual e sem código

A instrumentação descrita neste documento baseia-se na instrumentação de código zero do OpenTelemetry para enviar telemetria para o seu Google Cloud projeto. Para Java, a instrumentação sem código refere-se à prática de injetar dinamicamente bytecode em bibliotecas e frameworks para capturar telemetria. A instrumentação sem código pode recolher telemetria para itens como chamadas HTTP de entrada e saída. Para mais informações, consulte o artigo Agente Java.

O OpenTelemetry também fornece uma API para adicionar instrumentação personalizada ao seu próprio código. O OpenTelemetry refere-se a isto como instrumentação manual. Este documento não descreve a instrumentação manual. Para ver exemplos e informações sobre esse tópico, consulte o artigo Instrumentação manual.

Antes de começar

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.

  3. Se estiver a usar um fornecedor de identidade (IdP) externo, primeiro, tem de iniciar sessão na CLI gcloud com a sua identidade federada.

  4. Para inicializar a CLI gcloud, execute o seguinte comando:

    gcloud init
  5. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the Cloud Logging, Cloud Monitoring, and Cloud Trace APIs:

    gcloud services enable logging.googleapis.com monitoring.googleapis.com cloudtrace.googleapis.com
  8. Install the Google Cloud CLI.

  9. Se estiver a usar um fornecedor de identidade (IdP) externo, primeiro, tem de iniciar sessão na CLI gcloud com a sua identidade federada.

  10. Para inicializar a CLI gcloud, execute o seguinte comando:

    gcloud init
  11. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  12. Verify that billing is enabled for your Google Cloud project.

  13. Enable the Cloud Logging, Cloud Monitoring, and Cloud Trace APIs:

    gcloud services enable logging.googleapis.com monitoring.googleapis.com cloudtrace.googleapis.com
  14. Instrumente a sua app para recolher rastreios, métricas e registos

    Para instrumentar a sua app de modo a recolher dados de rastreio e métricas, e para escrever JSON estruturado para a saída padrão, siga os passos descritos nas secções subsequentes deste documento:

    1. Configure a sua app para usar o agente Java do OpenTelemetry
    2. Configure o OpenTelemetry
    3. Configure o registo estruturado
    4. Escreva registos estruturados

    Configure a sua app para usar o agente Java OpenTelemetry

    Para configurar a app para escrever registos estruturados e recolher métricas e dados de rastreio através do OpenTelemetry, atualize a invocação da sua app para usar o agente Java do OpenTelemetry. Este método de instrumentação da sua app é conhecido como instrumentação automática porque não requer a modificação do código da app.

    O seguinte exemplo de código ilustra um Dockerfile que transfere o ficheiro JAR do agente Java do OpenTelemetry e atualiza a invocação da linha de comandos para transmitir a flag -javaagent.

    Para ver o exemplo completo, clique em Mais e, de seguida, selecione Ver no GitHub.

    RUN wget -O /opentelemetry-javaagent.jar https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v1.31.0/opentelemetry-javaagent.jar
    CMD sh -c "java -javaagent:/opentelemetry-javaagent.jar -cp app:app/lib/* com.example.demo.DemoApplication \
    	2>&1 | tee /var/log/app.log"

    Em alternativa, também pode definir a flag -javaagent na JAVA_TOOL_OPTIONSvariável de ambiente:

    export JAVA_TOOL_OPTIONS="-javaagent:PATH/TO/opentelemetry-javaagent.jar"
    

    Configure o OpenTelemetry

    A configuração predefinida do agente Java OpenTelemetry exporta rastreios e métricas através do protocolo OTLP. Também configura o OpenTelemetry para usar o formato W3C Trace Context para propagar o contexto de rastreio. Esta configuração garante que os intervalos têm a relação principal-secundário correta numa rastreabilidade.

    Para mais informações e opções de configuração, consulte o artigo Instrumentação automática do Java OpenTelemetry.

    Configure o registo estruturado

    Para incluir as informações de rastreio como parte dos registos formatados em JSON escritos para a saída padrão, configure a sua app para gerar registos estruturados no formato JSON. Recomendamos que use o Log4j2 como implementação de registo. O seguinte exemplo de código ilustra um ficheiro log4j2.xml configurado para gerar registos estruturados JSON através do esquema de modelo JSON:

    <!-- Format JSON logs for the Cloud Logging agent
    https://cloud.google.com/logging/docs/structured-logging#special-payload-fields -->
    
    <!-- Log4j2's JsonTemplateLayout includes a template for Cloud Logging's special JSON fields
    https://logging.apache.org/log4j/2.x/manual/json-template-layout.html#event-templates -->
    <JsonTemplateLayout eventTemplateUri="classpath:GcpLayout.json">
      <!-- Extend the included GcpLayout to include the trace and span IDs from Mapped
      Diagnostic Context (MDC) so that Cloud Logging can correlate Logs and Spans
    
      Since log4j2 2.24.0, GcpLayout.json already includes trace context logging from MDC and
      the below additional fields are no longer needed -->
      <EventTemplateAdditionalField
        key="logging.googleapis.com/trace"
        format="JSON"
        value='{"$resolver": "mdc", "key": "trace_id"}'
      />
      <EventTemplateAdditionalField
        key="logging.googleapis.com/spanId"
        format="JSON"
        value='{"$resolver": "mdc", "key": "span_id"}'
      />
      <EventTemplateAdditionalField
        key="logging.googleapis.com/trace_sampled"
        format="JSON"
        value="true"
      />
    </JsonTemplateLayout>

    A configuração anterior extrai informações sobre o intervalo ativo do Mapped Diagnostic Context do SLF4J e adiciona essas informações como atributos ao registo. Estes atributos podem ser usados para correlacionar um registo com um rastreio:

    • logging.googleapis.com/trace: nome do recurso do rastreio associado à entrada do registo.
    • logging.googleapis.com/spanId: o ID do intervalo com o rastreio associado à entrada do registo.
    • logging.googleapis.com/trace_sampled: o valor deste campo tem de ser true ou false.

    Para mais informações sobre estes campos, consulte a LogEntry estrutura.

    Escreva registos estruturados

    Para escrever registos estruturados que sejam associados a um rastreio, use a API de registo SLF4J. Por exemplo, a seguinte declaração mostra como chamar o método Logger.info():

    logger.info("handle /multi request with subRequests={}", subRequests);
    

    O agente Java OpenTelemetry preenche automaticamente o contexto de diagnóstico mapeado do SLF4J com o contexto do intervalo do intervalo ativo atual no contexto do OpenTelemetry. O contexto de diagnóstico mapeado é, em seguida, incluído nos registos JSON, conforme descrito em Configure o registo estruturado.

    Execute uma app de exemplo configurada para recolher telemetria

    A app de exemplo usa formatos independentes do fornecedor, incluindo JSON para registos e OTLP para métricas e rastreios, e a estrutura Spring Boot. Para encaminhar a telemetria para Google Cloud, este exemplo usa o OpenTelemetry Collector configurado com exportadores da Google. A app tem dois pontos finais:

    • O ponto final /multi é processado pela função handleMulti. O gerador de carga na app envia pedidos para o ponto final /multi. Quando este ponto final recebe um pedido, envia entre três e sete pedidos para o ponto final /single no servidor local.

      /**
       * handleMulti handles an http request by making 3-7 http requests to the /single endpoint.
       *
       * <p>OpenTelemetry instrumentation requires no changes here. It will automatically generate a
       * span for the controller body.
       */
      @GetMapping("/multi")
      public Mono<String> handleMulti() throws Exception {
        int subRequests = ThreadLocalRandom.current().nextInt(3, 8);
      
        // Write a structured log with the request context, which allows the log to
        // be linked with the trace for this request.
        logger.info("handle /multi request with subRequests={}", subRequests);
      
        // Make 3-7 http requests to the /single endpoint.
        return Flux.range(0, subRequests)
            .concatMap(
                i -> client.get().uri("http://localhost:8080/single").retrieve().bodyToMono(Void.class))
            .then(Mono.just("ok"));
      }
    • O ponto final /single é processado pela função handleSingle. Quando este ponto final recebe um pedido, fica inativo durante um breve período e, em seguida, responde com uma string.

      /**
       * handleSingle handles an http request by sleeping for 100-200 ms. It writes the number of
       * milliseconds slept as its response.
       *
       * <p>OpenTelemetry instrumentation requires no changes here. It will automatically generate a
       * span for the controller body.
       */
      @GetMapping("/single")
      public String handleSingle() throws InterruptedException {
        int sleepMillis = ThreadLocalRandom.current().nextInt(100, 200);
        logger.info("Going to sleep for {}", sleepMillis);
        Thread.sleep(sleepMillis);
        logger.info("Finishing the request");
        return String.format("slept %s\n", sleepMillis);
      }

    Transfira e implemente a app

    Para executar o exemplo, faça o seguinte:

    1. In the Google Cloud console, activate Cloud Shell.

      Activate Cloud Shell

      At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

    2. Clone o repositório:

      git clone https://github.com/GoogleCloudPlatform/opentelemetry-operations-java
      
    3. Aceda ao diretório de exemplo:

      cd opentelemetry-operations-java/examples/instrumentation-quickstart
      
    4. Crie e execute o exemplo:

      docker compose up --abort-on-container-exit
      

      Se não estiver a usar o Cloud Shell, execute a aplicação com a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS a apontar para um ficheiro de credenciais. As Credenciais padrão da aplicação fornecem um ficheiro de credenciais em $HOME/.config/gcloud/application_default_credentials.json.

      # Set environment variables
      export GOOGLE_CLOUD_PROJECT="PROJECT_ID"
      export GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/gcloud/application_default_credentials.json"
      export USERID="$(id -u)"
      
      # Run
      docker compose -f docker-compose.yaml -f docker-compose.creds.yaml up --abort-on-container-exit
      
    5. Veja as suas métricas

      A instrumentação do OpenTelemetry na app de exemplo gera métricas do Prometheus que pode ver através do Explorador de métricas:

      • Prometheus/http_server_duration_milliseconds/histogram registam a duração dos pedidos do servidor e armazenam os resultados num histograma.

      • Prometheus/http_client_duration_milliseconds/histogram regista a duração dos pedidos do cliente e armazena os resultados num histograma.

      Para ver as métricas geradas pela app de amostra, faça o seguinte:
      1. Na Google Cloud consola, aceda à página  Explorador de métricas:

        Aceda ao Metrics Explorer

        Se usar a barra de pesquisa para encontrar esta página, selecione o resultado cujo subtítulo é Monitorização.

      2. Na barra de ferramentas da Google Cloud consola, selecione o seu Google Cloud projeto. Para configurações do App Hub, selecione o projeto anfitrião do App Hub ou o projeto de gestão da pasta com apps ativadas.
      3. No elemento Métrica, expanda o menu Selecionar uma métrica, introduza http_server na barra de filtro e, de seguida, use os submenus para selecionar um tipo de recurso e uma métrica específicos:
        1. No menu Recursos ativos, selecione Alvo do Prometheus.
        2. No menu Categorias de métricas ativas, selecione Http.
        3. No menu Métricas ativas, selecione uma métrica.
        4. Clique em Aplicar.
      4. Configure a forma como os dados são vistos.

        Quando as medições de uma métrica são cumulativas, o explorador de métricas normaliza automaticamente os dados medidos pelo período de alinhamento, o que resulta na apresentação de uma taxa no gráfico. Para mais informações, consulte o artigo Tipos, tipos e conversões.

        Quando são medidos valores inteiros ou duplos, como com as duas métricas counter, o explorador de métricas soma automaticamente todas as séries cronológicas. Para ver os dados das rotas HTTP /multi e /single, defina o primeiro menu da entrada Agregação como Nenhuma.

        Para mais informações sobre como configurar um gráfico, consulte o artigo Selecione métricas quando usar o explorador de métricas.

      Veja os seus rastreios

      Pode demorar vários minutos até que os dados de rastreio estejam disponíveis. Por exemplo, quando o seu projeto recebe dados de rastreio, o Google Cloud Observability pode ter de criar uma base de dados para armazenar esses dados. A criação da base de dados pode demorar alguns minutos e, durante esse período, não estão disponíveis dados de rastreio para visualização.

      Para ver os dados de rastreio, faça o seguinte:

      1. Na Google Cloud consola, aceda à página Explorador de rastreios:

        Aceda ao Explorador de rastreios

        Também pode encontrar esta página através da barra de pesquisa.

      2. Na secção de tabelas da página, selecione uma linha com o nome do intervalo /multi.
      3. No gráfico de Gantt no painel Detalhes do rastreio, selecione o intervalo etiquetado como /multi.

        É aberto um painel que apresenta informações sobre o pedido HTTP. Estes detalhes incluem o método, o código de estado, o número de bytes e o agente do utilizador do autor da chamada.

      4. Para ver os registos associados a este rastreio, selecione o separador Registos e eventos.

        O separador mostra registos individuais. Para ver os detalhes da entrada do registo, expanda a entrada do registo. Também pode clicar em Ver registos e ver o registo através do Explorador de registos.

      Para mais informações sobre como usar o explorador do Cloud Trace, consulte o artigo Encontre e explore rastreios.

      Veja os seus registos

      No Explorador de registos, pode inspecionar os seus registos e também ver rastreios associados, quando existirem.

      1. Na Google Cloud consola, aceda à página Explorador de registos:

        Aceda ao Explorador de registos

        Se usar a barra de pesquisa para encontrar esta página, selecione o resultado cuja legenda é Registo.

      2. Localize um registo com a descrição de handle /multi request.

        Para ver os detalhes do registo, expanda a entrada do registo.

      3. Clique em Rastreios numa entrada de registo com a mensagem "handle /multi request" e, de seguida, selecione Ver detalhes do rastreio.

        É aberto um painel Detalhes do rastreio que apresenta o rastreio selecionado.

        Os dados de registo podem estar disponíveis vários minutos antes dos dados de rastreio. Se encontrar um erro ao ver os dados de rastreio pesquisando um rastreio por ID ou seguindo os passos desta tarefa, aguarde um ou dois minutos e tente novamente a ação.

      Para mais informações sobre a utilização do Explorador de registos, consulte o artigo Veja registos através do Explorador de registos.

      O que se segue?