Propagação de contexto

Entenda os conceitos que tornam possível o Rastreamento Distribuído.

Com a propagação de contexto, sinais (rastros, métricas e logs) podem ser correlacionados entre si, independentemente de onde são gerados. Embora não se limite ao rastreamento, a propagação de contexto permite que os rastros criem informações causais sobre um sistema através de serviços que estão arbitrariamente distribuídos através de limites de processos e redes.

Para compreender a propagação de contexto, você precisa entender dois conceitos distintos: contexto e propagação.

Contexto

O contexto é um objeto que contém as informações necessárias para que o serviço emissor e receptor, ou unidade de execução, correlacionem um sinal com outro.

Quando o serviço A chama o serviço B, o serviço A inclui um ID de rastro (trace ID) e um ID de trecho (span ID) como parte do contexto. O serviço B utiliza estes valores para criar um novo trecho que pertence ao mesmo rastro, definindo o trecho do serviço A como seu pai. Isso torna possível acompanhar todo o fluxo de uma requisição através dos limites dos serviços.

Propagação

Propagação é o mecanismo que move o contexto entre serviços e processos. Ele serializa ou desserializa o objeto de contexto e fornece as informações relevantes a serem propagadas de um serviço para outro.

A propagação geralmente é gerenciada por bibliotecas de instrumentação e é transparente para o usuário. Caso precise propagar o contexto manualmente, você pode usar a API de Propagadores.

O OpenTelemetry mantém vários propagadores oficiais. O propagador padrão utiliza os cabeçalhos definidos na especificação W3C TraceContext.

Exemplo

Um serviço chamado Frontend, que fornece diferentes rotas HTTP, como POST /cart/add e GET /checkout/, acessa um serviço chamado Product Catalog (Catálogo de Produto) através de uma rota HTTP GET /product para receber detalhes sobre os produtos que um usuário deseja adicionar ao carrinho ou que fazem parte do checkout. Para entender as atividades no serviço Product Catalog dentro do contexto das requisições vindas do Frontend, o contexto (neste caso: Trace ID e Span ID como “Parent ID”) é propagado utilizando o cabeçalho traceparent, conforme definido na especificação W3C TraceContext. Isso significa que os IDs são incorporados nos campos do cabeçalho:

<version>-<trace-id>-<parent-id>-<trace-flags>

Por exemplo:

00-a0892f3577b34da6a3ce929d0e0e4736-f03067aa0ba902b7-01

Rastros

Como mencionado, a propagação de contexto permite que os rastros construam informações causais entre serviços. Neste exemplo, as duas chamadas para a rota HTTP GET /product do serviço Product Catalog podem ser correlacionadas com suas chamadas no serviço Frontend através da extração do contexto remoto do cabeçalho traceparent e sua injeção no contexto local para definir o ID de rastro (trace ID) e o ID de pai (parent ID). Com isso, é possível em um backend como Jaeger ver duas requisições como trechos de um mesmo rastro.

Exemplo de propagação mostrando correlação de rastros entre serviços

Logs

Os SDKs do OpenTelemetry são capazes de correlacionar automaticamente logs com rastros. Isso significa que o contexto (ID de rastro, ID de trecho) pode ser injetado em um registro de log. Isso não apenas permite que você veja os logs no contexto do rastro e do trecho ao qual pertencem, mas também possibilita ver os logs que pertencem juntos através dos limites de serviços ou unidades de execução.

Métricas

No caso de métricas, a propagação de contexto permite que você agregue medições naquele contexto. Por exemplo, em vez de apenas olhar para o tempo de resposta de todas as requisições GET /product, você também pode obter métricas para combinações de POST /cart/add > GET /product e GET /checkout < GET /product.

NomeChamadas por SegundoTempo Médio de Resposta
* > GET /product370300ms
POST /card/add > GET /product330130ms
GET /checkout > GET /product401703ms

Propagação de contexto personalizada

Para a maioria dos casos de uso, você encontrará bibliotecas de instrumentação ou instrumentação nativa de bibliotecas que lidam com a propagação de contexto para você. Em alguns casos, este suporte não está disponível e você desejará criar esse suporte por conta própria. Para isso, você precisa aproveitar a API de Propagadores mencionada anteriormente:

  • No lado do emissor, o contexto é injetado no transportador (carrier), por exemplo, nos cabeçalhos de uma requisição HTTP. Em outros casos, você precisa encontrar um local onde possa armazenar metadados para sua requisição.
  • No lado do receptor, o contexto é extraído do transportador. Novamente, no caso de HTTP, isso é recuperado dos cabeçalhos. Em outros casos, você escolhe o local selecionado no lado emissor para armazenar o contexto.

Note que é possível propagar o contexto em protocolos que não possuem um campo dedicado para metadados, mas você deve garantir que no lado receptor eles sejam extraídos e removidos antes que os dados sejam processados, caso contrário você poderá criar um comportamento indefinido.

Para as seguintes linguagens, existe um tutorial passo a passo para propagação de contexto personalizada:

Melhores práticas de segurança

A propagação envolve o envio e recebimento de dados através de limites de serviço, o que pode ter implicações de segurança.

Serviços externos

Quando seu serviço interage com serviços externos (serviços que você não possui ou não confia), considere o seguinte:

  • Contexto de entrada: Tenha cautela ao aceitar contexto de fontes externas. Atores maliciosos podem enviar cabeçalhos de rastreamento forjados para manipular seus dados de rastreamento ou potencialmente explorar vulnerabilidades na análise de contexto. Você pode querer ignorar ou sanitizar o contexto de entrada de fontes não confiáveis.
  • Contexto de saída: Tenha cuidado com o que você propaga para serviços externos. IDs de rastros internos, IDs de trechos ou itens de bagagem podem revelar informações sensíveis sobre sua arquitetura interna ou lógica de negócios. Você pode querer configurar seus propagadores para não enviar contexto para rotas externas ou públicas.

Bagagem

Bagagem permite propagar pares arbitrários de chave-valor. Como esses dados são propagados através de limites de serviço, evite colocar informações sensíveis (como credenciais de usuário, chaves de API ou informações pessoais identificáveis) na bagagem, pois elas podem ser registradas ou enviadas para serviços downstream não confiáveis.

Suporte nos SDKs de Linguagem

Para as implementações individuais específicas de linguagem da API & SDK do OpenTelemetry, você encontrará detalhes sobre o suporte à propagação de contexto nas respectivas páginas de documentação:

Especificação

Para saber mais sobre a Propagação de Contexto, consulte a Especificação de Contexto.