Os links de span são uma ferramenta essencial para melhorar a rastreabilidade e a observabilidade em sistemas distribuídos, permitindo que múltiplos spans compartilhem relações entre si de forma explícita. Enquanto um span tradicional pode ter apenas um único pai e múltiplos filhos, os links oferecem a flexibilidade de conectar spans de diferentes rastros, o que é crucial para cenários em que múltiplas mensagens são processadas simultaneamente.

Em sistemas que envolvem o processamento de múltiplas mensagens, como servidores de mensagens baseados em filas, a utilização de links de span torna-se uma estratégia indispensável. Ao extrair o contexto de rastreio de cada mensagem e criar um link de span correspondente, é possível relacionar diferentes spans entre si, independentemente de estarem no mesmo rastro ou não. Isso é particularmente útil em arquiteturas como pipelines de dados e sistemas de streaming em tempo real, onde a observabilidade precisa ser mantida ao longo de processos paralelos e assíncronos.

A principal utilidade dos links de span é a capacidade de representar a relação entre diferentes spans sem a necessidade de "quebrar" os rastros existentes. Isso permite que, em cenários como o MapReduce, múltiplos processos paralelos sejam correlacionados em um único span, o que facilita a visualização da execução de tarefas complexas. No caso da agregação de mensagens, como em sistemas de mensageria como Kafka Stream, os links de span tornam visível como cada mensagem individual contribui para o resultado final de um processamento agregado.

Quando se fala de mensagens transacionais, especialmente em arquiteturas que envolvem filas de mensagens, como Kafka ou RabbitMQ, os links de span têm um papel fundamental. Eles associam cada mensagem ao processo transacional global, proporcionando uma visão clara de como diferentes partes do sistema interagem para completar uma transação maior. Esse tipo de rastreamento é crucial para garantir que a integridade do processo seja mantida, mesmo em sistemas altamente distribuídos.

Outro campo importante onde os links de span são aplicáveis é o event sourcing, uma técnica que permite rastrear como múltiplas mensagens de mudança afetam o estado atual de uma entidade. Este tipo de rastreio é especialmente relevante em sistemas que utilizam eventos como a principal forma de comunicação entre microserviços, onde a consistência e a rastreabilidade dos dados são fundamentais.

Porém, para que a observabilidade seja efetiva, é necessário que o rastreio de mensagens seja acompanhado por identificadores únicos, como o ID da mensagem, que correlaciona o fluxo de uma mensagem desde seu envio até seu processamento final. Esses identificadores permitem que se compreenda não apenas a sequência de operações, mas também a performance do sistema como um todo. A adição de atributos específicos de mensagens aos spans facilita a visualização de toda a cadeia de processamento, ajudando na identificação de gargalos e problemas de desempenho.

Porém, a introdução de servidores de mensagens baseados em eventos, como Kafka ou JMS, coloca desafios adicionais. O uso desses servidores geralmente implica em um alto grau de flexibilidade, mas também em uma complexidade de instrumentação. Em sistemas que utilizam Kafka, por exemplo, os links de span podem ser usados para monitorar como diferentes produtores e consumidores interagem dentro de um cluster de dados em tempo real. Kafka, com sua capacidade de escalar facilmente, é uma escolha popular em ambientes de nuvem, enquanto JMS continua sendo prevalente em ambientes empresariais legados.

Em sistemas que utilizam JMS, a complexidade de instrumentação é exacerbada devido às diferenças internas dos servidores, como o TIBCO EMS, que é desenvolvido em C, e outras implementações de servidores JMS. Embora a instrumentação automática dos publishers e subscribers seja viável, a instrumentação do servidor JMS em si continua sendo um desafio. Apesar disso, a medição de latência nos tópicos e nas filas é possível, permitindo que a performance de toda a comunicação entre publisher e subscriber seja rastreada.

A boa prática em sistemas baseados em mensagens é garantir que, ao menos, as mensagens mais críticas e os spans essenciais sejam instrumentados corretamente. Assim, mesmo em cenários onde a instrumentação total é impossível, pode-se obter uma visão geral de como as mensagens estão sendo processadas, o que é vital para a manutenção da performance e da confiabilidade do sistema.

Como Propagar o Contexto de Rastreio entre Microserviços com o Uso de Tracestate

No contexto de microserviços, a correta propagação do contexto de rastreio entre os diferentes serviços é um desafio essencial para garantir que as métricas de desempenho sejam precisas e que os problemas sejam facilmente diagnosticados. Isso é especialmente importante quando se trabalha com tecnologias como OpenTelemetry e ferramentas de observabilidade comercial, que são projetadas para coletar dados de rastreamento distribuído e facilitar a análise de causa raiz (RCA).

O problema comum enfrentado ao usar sistemas distribuídos é a falha na propagação adequada do contexto de rastreio. Esse erro pode resultar em rastreamentos incompletos ou com spans (intervalos de rastreio) ausentes ou corrompidos. Um dos principais mecanismos para resolver essa questão é o uso do "tracestate", um campo dentro do cabeçalho de rastreamento que permite a associação de informações adicionais sobre o rastreamento entre os serviços. Este mecanismo é crucial para garantir que diferentes tipos de contextos de rastreio sejam corretamente conectados.

Por exemplo, ao usar o tracestate, é possível observar que dois tipos diferentes de contextos de rastreio estão interligados, conforme ilustrado na figura 3-42. Para que isso funcione corretamente, os serviços A e B precisam ser configurados com agentes OpenTelemetry, e ambos devem estar configurados para utilizar o tracestate. Um ponto interessante é que o tracestate pode incluir informações específicas do fornecedor, como o caso do serviço B, que pode adicionar seu identificador exclusivo ao tracestate. No entanto, isso gera uma prioridade distinta, onde o cabeçalho x-, utilizado pelas ferramentas comerciais de observabilidade, assume a maior prioridade no rastreamento.

Em um cenário típico, o processo de propagação de rastreio segue os seguintes passos: o serviço A adiciona o cabeçalho traceparent ao tracestate, o serviço B copia o tracestate propagado e adiciona o x- ao seu próprio tracestate, e o serviço C, ao receber essa informação, também insere o traceparent e gera o valor x- correspondente. Dessa forma, os serviços A, B e C conseguem propagar corretamente o contexto do rastreio.

No entanto, nem sempre o contexto de rastreio se propaga sem dificuldades. Em alguns cenários, como quando o upstream não possui o cabeçalho x-, será necessário realizar ajustes adicionais no desenvolvimento para configurar corretamente o rastreamento. Como o x- é um recurso suportado apenas pelas soluções comerciais de observabilidade, é necessário configurar o rastreamento end-to-end (E2E) para reconhecer o ID de rastreio associado ao produto de observabilidade comercial.

O uso do tracestate pode se tornar mais complexo quando não se tem a visibilidade de todo o processo de propagação do rastreio, especialmente se a instrumentação falha ou se o agente comercial não está instalado corretamente. Nesse caso, se o cabeçalho x- não for gerado, será necessário criar manualmente esse cabeçalho e associá-lo aos rastreamentos. O OpenTelemetry, por exemplo, não gera tracestates automaticamente, o que implica que os desenvolvedores terão que se encarregar de configurar a propagação do rastreio e garantir que a transferência de dados ocorra corretamente.

Outro aspecto importante é a questão da "agent chaos", que ocorre quando múltiplos agentes estão em uso ao mesmo tempo, mas a instrumentação de observabilidade comercial falha ao instrumentar corretamente o upstream. Para evitar esse tipo de problema, pode-se utilizar o OpenTelemetry para realizar a instrumentação manual, associando corretamente os tracestates entre os serviços.

A integração do tracestate no rastreamento distribuído exige uma atenção especial aos detalhes da implementação e à compreensão profunda do fluxo de dados entre os serviços. Deve-se ter claro onde o rastreamento falha e garantir que a instrumentação seja adequada para permitir a propagação sem erros. A automação da instrumentação é essencial, e o uso de extensões do OpenTelemetry e agentes Java pode ajudar a reduzir o esforço necessário para configurar manualmente os rastreamentos em todos os microserviços.

Além disso, o papel dos SREs (Site Reliability Engineers) é fundamental nesse processo. Eles devem entender as limitações das soluções de observabilidade comercial e do OpenTelemetry, guiando os desenvolvedores e ajudando a criar uma estratégia de instrumentação eficiente. Como muitas vezes as equipes de desenvolvimento não têm experiência com programação de nível de sistema, os SREs precisam trabalhar de forma colaborativa com os desenvolvedores para implementar as melhores soluções de rastreamento. Esse processo pode ser desafiador e envolver muitas tentativas e erros, mas é essencial para garantir uma observabilidade eficaz nos sistemas distribuídos.

Por fim, ao aplicar essas tecnologias em ambientes reais, como servidores de mensagens, frameworks de servidores e sistemas de integração de aplicações empresariais (EAI), é importante que os SREs forneçam uma orientação clara para os desenvolvedores. Isso garantirá que a análise de causa raiz (RCA) seja eficaz e que os problemas possam ser identificados e resolvidos de forma rápida e precisa. Embora a tecnologia ofereça as ferramentas necessárias para implementar uma observabilidade robusta, os desafios organizacionais também devem ser considerados. Para que a implementação de uma solução bem-sucedida aconteça, é crucial obter o apoio das lideranças, caso contrário, será difícil criar resultados duradouros.