Traces na Observabilidade: o que são, span, trace_id e OpenTelemetry

Traces - Rastreamento Distribuído via Tracing
Pedro Tebaldi Autor: Pedro Tebaldi PM do KeepGreenEdnilson Correa Revisão técnica: Ednilson Correa SRE
Publicado dez/2025Atualizado ago/2026

Em arquiteturas monolíticas, debugar uma requisição lenta era relativamente simples: um único stack trace, um único banco de dados, logs centralizados em um servidor. Em arquiteturas de microsserviços, a mesma requisição pode atravessar 15, 20 ou 30 serviços diferentes antes de retornar uma resposta ao usuário.

Quando algo dá errado nessa cadeia, descobrir onde sem as ferramentas certas pode levar horas.

Traces — ou rastreamento distribuído — são o pilar da observabilidade que resolve esse problema. Eles registram a jornada completa de uma requisição por todos os serviços que ela atravessa, tornando a cadeia de dependências visível e navegável.

Este guia técnico explica o que são traces e como a estrutura de span e trace_id funciona. Em seguida, mostra como eles se integram com logs e métricas e como o padrão OpenTelemetry padroniza a instrumentação.

 

O que são traces (rastreamento distribuído)?

Um trace é a representação completa e cronológica da jornada de uma requisição por um sistema distribuído. Ele cobre do ponto de entrada até o retorno da resposta, com todas as operações intermediárias em todos os serviços envolvidos.

Cada trace é composto por um conjunto de spans: unidades de trabalho que representam uma operação individual. Um span captura o nome da operação, o serviço que executou e os timestamps de início e fim. Ele traz ainda o status (sucesso ou falha), atributos de contexto e a referência ao span pai.

A estrutura hierárquica de spans forma uma árvore que representa o fluxo da requisição. O span raiz é a requisição original; os spans filhos são as operações que ela disparou em outros serviços ou internamente.

 

trace_id e span_id: o DNA de uma requisição

O elemento que torna o rastreamento distribuído possível é o trace_id: um identificador único gerado quando a requisição entra no sistema. Cada serviço o repassa adiante, via headers HTTP, mensagens de fila ou protocolos de RPC.

Cada serviço lê o trace_id do contexto, cria seu próprio span com um span_id único e registra o span_id do serviço anterior como parent_span_id. Esse encadeamento permite reconstruir a árvore completa de spans.

O trace_id é também o elo de correlação com os outros pilares. Quando injetado nos logs gerados durante a requisição, permite filtrar exatamente os logs daquele trace. Quando presente nas métricas de erro, permite navegar do alerta para o trace específico que falhou.

 
Esse encadeamento fica visível fora da documentação em um laboratório com cinco serviços Python instrumentados por OpenTelemetry, um Collector e o Jaeger. Versões testadas em 28 de agosto de 2026: Jaeger 2.11.0, OpenTelemetry Collector Contrib 0.139.0 e SDK Python 1.44.0 com instrumentação automática 0.65b0.

A API do Jaeger devolve os spans crus em GET /api/traces/{trace_id}. Estes são dois spans vizinhos do mesmo trace, com os campos que interessam:




spans.json
[
  {
    "traceID": "90316b21da519f164ecfc94c1b21b760",
    "spanID": "06a50f174b801c01",
    "operationName": "GET /api/produto/<sku>",
    "references": [{ "refType": "CHILD_OF", "spanID": "16c67179c3195b81" }],
    "duration": 40955
  },
  {
    "traceID": "90316b21da519f164ecfc94c1b21b760",
    "spanID": "3c0f38b7294bfcaa",
    "operationName": "SELECT",
    "references": [{ "refType": "CHILD_OF", "spanID": "06a50f174b801c01" }],
    "duration": 40009
  }
]

 
O traceID é idêntico nos dois. Já o spanID do primeiro reaparece como CHILD_OF do segundo, e esse par é o que reconstrói a hierarquia. A duração vem em microssegundos: 40.955 no span HTTP e 40.009 no SELECT que ele disparou.

 

Anatomia de um trace real, span a span

A árvore completa do trace 90316b21da519f164ecfc94c1b21b760 tem 11 spans, cinco serviços e profundidade 4. Na captura, o span raiz é a requisição inteira; o span marcado logo abaixo é onde o tempo ficou.

 
Timeline do trace 90316b21 no Jaeger 2.11: o span raiz do api-gateway leva 72,97 ms e o span filho SELECT do product-service, marcado como gargalo, consome 40,01 ms desse total; o trace tem 11 spans e 5 serviços

 
A leitura é direta. Dos 72,97 ms da requisição, 40,01 ms couberam dentro de um único SELECT do product-service. São 55% do total, num span três níveis abaixo do ponto de entrada.

Os dois SELECT do mesmo trace dão a régua. O inventory-service busca pela chave indexada e responde em 148 µs; o product-service varre 180 mil linhas por uma coluna sem índice e responde em 40,01 ms. São 270 vezes mais, na mesma tabela e no mesmo banco.

Sem o trace, chegar a essa conclusão exigiria abrir o log de quatro serviços e correlacionar timestamp na mão.

 

Material gratuito · Observabilidade e FinOps

Ebook: Como sobreviver à fatura cloud?

Nosso framework, Observability Maturity Index, mede a maturidade das operações em nuvem das empresas. Você encontrará: os quatro perfis de empresas, as métricas que você deveria estar medindo, um checklist de avaliação e um plano de ação para 90 dias.

Só o e-mail. Sem spam, e seus dados protegidos pela LGPD.

Sampling: não rastrear tudo

Em sistemas de alto tráfego, rastrear 100% das requisições seria proibitivo em volume de dados e overhead de performance. A solução é o sampling: a decisão de quais requisições serão rastreadas.

O head-based sampling decide no início da requisição: é simples, mas pode perder traces de erros raros. Já o tail-based sampling decide ao final, depois de conhecer o resultado, e prioriza erros e requisições lentas ao custo de mais infraestrutura.

Em produção, a estratégia comum é rastrear 100% dos erros, 100% das requisições lentas e uma amostra configurável (1–10%) das demais.

 
No Collector, essa política tem nome e forma. As três regras abaixo rodaram no laboratório e foram o que decidiu quais traces chegaram ao Jaeger:




otel-collector.yaml
# processor tail_sampling do OpenTelemetry Collector Contrib 0.139.0
tail_sampling:
  decision_wait: 5s
  policies:
    - name: todo-erro
      type: status_code
      status_code:
        status_codes: [ERROR]
    - name: toda-requisicao-lenta
      type: latency
      latency:
        threshold_ms: 300
    - name: amostra-do-resto
      type: probabilistic
      probabilistic:
        sampling_percentage: 10

 
O decision_wait é a parte cara. O Collector segura os spans em memória por cinco segundos, esperando o trace fechar, para só então decidir. Esse é o preço do tail-based, e explica por que ele exige mais infraestrutura que o head-based.

 

A conta de volume que a amostragem esconde

Cada requisição ao gateway do laboratório gerou 11 spans, e cada span ocupou 1.021 bytes na saída do Collector, em OTLP/JSON. Com 500 requisições e 10% de amostragem, chegaram ao backend 539 spans e 550.456 bytes.

Esses dois números resolvem a conta de capacidade sem chute. Tome uma API com 20 milhões de requisições por mês e este mesmo trace de 11 spans. A 1% de amostragem ela produz cerca de 2,2 GB de spans por mês; a 10%, 22 GB.

Subir a amostragem de 1% para 10%, portanto, é decisão de fatura antes de ser decisão de configuração. O ganho de cobertura é real, o custo cresce na mesma proporção, e a retenção escolhida multiplica os dois lados.

 

OpenTelemetry e a padronização de traces

O OpenTelemetry é o padrão aberto que unificou a instrumentação de traces — anteriormente fragmentada entre OpenTracing, OpenCensus, Zipkin e Jaeger.

Ele define uma API e um SDK agnósticos ao backend. Instrumentar com OpenTelemetry significa exportar os traces para Jaeger, Grafana Tempo, Datadog ou outro backend compatível, sem alterar o código.

A especificação inclui convenções semânticas que padronizam os atributos dos spans: http.method, http.status_code, db.system, db.statement, entre outros. Essa padronização garante que traces de diferentes serviços e linguagens sejam navegáveis em uma única plataforma de observabilidade.

 
No span HTTP do product-service, esses atributos chegam ao Jaeger já preenchidos pela instrumentação automática. O serviço em si não tem nenhuma linha de código de OpenTelemetry:

 
Painel de atributos do span GET /api/produto no Jaeger 2.11, com http.method igual a GET, http.route, http.status_code 200 e a biblioteca opentelemetry.instrumentation.flask na versão 0.65b0

 
Compare http.route com http.target. O primeiro guarda o molde da rota, /api/produto/<sku>; o segundo guarda o caminho com o SKU dentro. No trace os dois convivem sem problema, porque cada span é um evento discreto que ninguém agrega.

Aí mora a armadilha de cardinalidade. Esse mesmo http.target, promovido a rótulo de métrica, cria uma série temporal por SKU. É assim que uma base de métricas sai do controle. O trace aceita o valor único; a métrica, não.

A documentação de referência é a especificação de Distributed Traces do OpenTelemetry, que cobre em detalhe a estrutura de spans, propagação de contexto e semântica de atributos.

 

Observabilidade & OpenTelemetry

Logs, métricas e traces unificados para diagnóstico em profundidade.

Instrumentamos aplicações corporativas com OpenTelemetry para correlacionar eventos e acelerar a análise de causa raiz em produção.

Fale com um Especialista →

 

Conclusão

Traces são o pilar de navegação da observabilidade. Eles tornam visível o caminho exato de uma requisição por um sistema distribuído e o tempo gasto em cada hop. Sem traces, diagnosticar gargalos de performance em arquiteturas de microsserviços é uma investigação manual e demorada.

A implementação começa pela instrumentação padronizada com OpenTelemetry e segue com uma estratégia de sampling que prioriza erros e requisições lentas. Ela amadurece na correlação automática com logs e métricas pelo trace_id. Para estruturar sua estratégia de rastreamento distribuído e observabilidade, fale com nossos especialistas.

 

Perguntas Frequentes

O que é um trace na observabilidade?
Um trace é a representação completa da jornada de uma requisição por um sistema distribuído — do ponto de entrada até o retorno da resposta, incluindo todas as operações em todos os serviços envolvidos. É composto por spans: unidades de trabalho encadeadas em uma hierarquia que mostra quais serviços foram chamados, em qual ordem e quanto tempo cada um levou.
O que é trace_id e span_id?
O trace_id é um identificador único gerado quando a requisição entra no sistema e propagado para todos os serviços que ela atravessa — identifica um trace completo. O span_id é o identificador de uma operação específica dentro do trace. O encadeamento de span_id e parent_span_id permite reconstruir a hierarquia completa de operações e é o elo de correlação entre traces, logs e métricas.
Qual a diferença entre traces e logs?
Logs registram eventos individuais com contexto textual completo — respondem “o que aconteceu”. Traces registram a jornada de uma requisição por múltiplos serviços — respondem “onde na cadeia aconteceu e quanto tempo levou”. Os dois são complementares: o trace aponta o serviço com problema, o log fornece o detalhe do erro naquele serviço. O trace_id injetado nos logs é o elo que conecta os dois.
O que é sampling em rastreamento distribuído?
Sampling é a estratégia de decidir quais requisições serão rastreadas. Em sistemas de alto tráfego, rastrear 100% seria proibitivo. As abordagens principais são: head-based sampling (decisão no início, simples mas pode perder erros raros) e tail-based sampling (decisão ao final, permite priorizar erros e requisições lentas). A estratégia comum em produção é rastrear 100% dos erros e requisições acima de um threshold de latência, mais uma amostra de 1–10% das demais.
Como implementar traces com OpenTelemetry?
O OpenTelemetry fornece SDKs com instrumentação automática das bibliotecas HTTP, banco de dados e frameworks web mais comuns. A implementação básica inclui: (1) adicionar o SDK e as instrumentações automáticas; (2) configurar o propagador de contexto (W3C TraceContext é o padrão); (3) configurar o exportador para o backend escolhido (Jaeger, Grafana Tempo, Datadog, etc.); (4) opcionalmente, adicionar atributos customizados aos spans para contexto específico do negócio.
Acompanhe a OpServices10.576 profissionais de TI já seguemSeguir

Estou na OpServices desde 2011, onde sou Gerente de Marketing e Product Manager do KeepGreen, plataforma de gestão de incidentes de TI que higieniza alertas, aponta causa raiz com IA, escreve o post-mortem e analisa custos de nuvem. Também lidero os projetos de governança de inteligência artificial da empresa. Escrevo neste blog desde 2013, com mais de 550 artigos publicados sobre monitoramento, observabilidade, SRE e ITSM. LinkedIn

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *