OpenTelemetry Não Vai Bem na Sua Empresa. Conserte em 90 Dias.

Por Diogo Hudson Dias
Senior engineer reviewing service traces and latency metrics on large monitors in a modern office at dusk.

Sua fatura de observabilidade dobrou no último trimestre e ninguém consegue encontrar o trace da única requisição de que vocês realmente precisam. Enquanto isso, engenheiros ainda dão grep em logs enquanto bilhões de spans fluem para um fornecedor ao qual você não quer ficar preso. Se você leu os threads recentes de "OTel não vai bem", você não está sozinho. O problema não é o OpenTelemetry. É a forma como vocês o adotaram.

Este é um plano de resgate de 90 dias, orientado por SLOs, que corta custos em 50–70%, evita explosões de cardinalidade e torna traces mensuravelmente úteis na resposta a incidentes. Funciona para monólitos, microsserviços, serverless e funções na borda. Foi testado em produção em SaaS nos EUA de 100–10.000 RPS e stacks poliglotas.

Por que Seu Rollout de OTel Saiu dos Trilhos

  • Você enviou tudo, cru. Head-sampling em 1% e empurrar spans direto para um vendor dá a ilusão de adoção e a realidade de dor. Eventos de cauda não chegam. Caminhos quentes ficam sub-representados. Sua “linha de base” é ruído.
  • A cardinalidade detonou suas séries temporais. Alguém adicionou user_id, email ou request_path como labels. Dez labels com 100 valores cada é 10^10 séries teóricas. Seu backend de métricas derreteu, então você desativou exemplars ou fez downsampling até ficar inútil.
  • A propagação de contexto está quebrada nos pontos que importam. HTTP está ok. Seu gateway gRPC, o barramento de mensagens, o cron e os gatilhos serverless não. Os links pai‑filho são cortados; baggage carrega PII; exemplars não têm para onde ir.
  • Sem governança semântica. service.name deriva entre linguagens. Times inventam suas próprias chaves de atributo. Seu grafo de serviços é um emoji de ombros encolhidos.
  • Logs são um lixão, não um pipeline. Tudo vai para hot; nada é estruturado; request_id não faz a ponte entre logs, métricas e traces. O plantonista depende de conhecimento tribal e sorte.

As Estrelas do Norte (Decida Isso Primeiro)

OpenTelemetry é só encanamento. Decida por que você está instalando esses canos.

  1. SLOs de resposta a incidentes: Você quer p50 MTTR abaixo de 30 minutos e o primeiro sinal útil em menos de 5. Cada decisão deste plano é avaliada contra esses SLOs.
  2. Orçamento de dados: Limite a um número que você consiga defender para o seu CFO. Regra de bolso: 0,1–0,3% da receita ou US$ 20–50 por host por mês. Se você está pagando 2–3x isso, está subsidiando entropia.
  3. Caminhos dourados: Escolha 2–3 jornadas que pagam as contas. Elas recebem traces mais ricos, retenção de 100% de erros e exemplars. Todo o resto recebe tratamento probabilístico.

Arquitetura Que Não Luta Contra Você

Há muitas escolhas corretas. Estas funcionam na realidade de hoje:

  • Sempre coloque um OpenTelemetry Collector no meio. Collectors são seu plano de controle: amostragem, limpeza de atributos, guardas de cardinalidade e roteamento. Rode-os como um DaemonSet em k8s e como sidecar/VM na borda. Veja OpenTelemetry Collector.
  • Amostragem tail-based em vez de head-based para tráfego de usuários em produção. Mantenha 100% dos erros e dos traces lentos. Amostre traces normais até caber no orçamento. Use tail_sampling com orçamentos por regra e um disjuntor global.
  • Exemplars conectam métricas a traces. Sem exemplars você só construiu duas ilhas. Use span-to-metrics para popular RED (Requests, Errors, Duration) e anexe exemplars aos gráficos principais.
  • Logs são um pipeline em duas camadas. Hot (7–14 dias) estruturados e com escopo de requisição; Cold (90–365 dias) em storage de objetos com busca barata on‑read. Não pague preço de hot por retenção de compliance.
  • Escolha um storage que você possa manter. Vendor ou self-host é uma decisão de negócio. Se for self-host, um stack pragmático é Grafana Tempo para traces, Prometheus/Mimir para métricas e ClickHouse ou Loki para logs. Custo de storage: ~20–30% dos vendors gerenciados em escala, com operações que você precisa assumir.

Números Concretos (Para Não Ficar no Achismo)

Suponha que você rode 10.000 RPS em dez serviços. O trace mediano tem 10 spans. Um span mínimo fica em 400–800 bytes quando em batch. Com 100% de amostragem, você grava 10.000 × 10 × 600 B ≈ 60 MB/s, ou ~5 TB/dia só de traces. Isso é uma cratera no orçamento.

  • Faça tail-sampling em 5% (mantenha 100% de 5xx + latência p95): ~250 GB/dia de traces.
  • Elimine atributos de alta cardinalidade de que você não precisa (user_id, request_path com parâmetros): redução de 30–50% no tamanho do span.
  • Batching + compressão no Collector normalmente rende mais 20–30% de redução na rede.

Resultado: de 5 TB/dia para ~100–150 GB/dia sem perder o que o plantonista precisa. Isso é uma redução de 97% no volume armazenado com melhor sinal para incidentes.

O Plano de 90 Dias

Dias 0–30: Pare a Hemorragia e Defina Guardrails

  1. Faça um inventário e mapeie. Liste cada workload que emite telemetria por runtime, versão, biblioteca e destino. Capture o que está de fato ligado: métricas, traces, logs, profilers. Espere surpresas.
  2. Insira uma camada centralizada de Collector. Roteie toda a telemetria para Collectors regionais. Habilite processadores: batch, memory_limiter, attributes (limpeza de PII), k8sattributes (se em k8s) e transform para correções semânticas. Apenas os Collectors falam com vendors ou storage.
  3. Padronize a identidade de serviço. Faça cumprir service.namespace, service.name e service.version entre linguagens. Quebre builds que não cumprem. Sem identidade, nada mais importa.
  4. Mate baggage por padrão. Baggage vaza PII e explode a cardinalidade. Desative globalmente. Mantenha uma whitelist mínima e não‑PII se você realmente precisar.
  5. Lista de permissão (allowlist) de atributos, não denylist. Para spans e métricas, envie apenas chaves aprovadas. Comece com: http.method, http.route (templatizado), http.status_code, db.system, db.operation, messaging.system, net.peer.name (quantizado). Elimine qualquer coisa no escopo do usuário.
  6. Limite o head sampling a algo razoável. Até o tail-based estar no ar, rode head sampling em 10–20% nos serviços de alto tráfego e 100% nos de baixo tráfego ou APIs de administração. Mantenha 100% em canários e staging interno.
  7. Suba um dashboard dos Caminhos Dourados. Instruma 2–3 caminhos que trazem receita, de ponta a ponta. Construa métricas RED e anexe exemplars. Adicione um painel "Encontrar Trace" que funcione em 2 cliques durante incidentes.

Dias 31–60: Faça os Traces Responderem Perguntas

  1. Ligue a amostragem tail-based. No Collector, adicione regras: mantenha se status_code ≥ 500; mantenha se latency ≥ p95; mantenha se release.version for nova; caso contrário probabilistic 5%. Defina orçamentos por regra e globais com uma política de backpressure (descarte primeiro o tráfego normal).
  2. Propague contexto pelos trechos esquisitos. Audite e corrija W3C TraceContext em gRPC, barramentos de mensagens e gatilhos serverless. Para messaging, escreva traceparent nos cabeçalhos da mensagem e crie links entre os spans de produtor e consumidor. Para cron/batch, inicie novos traces e leve IDs de correlação para os logs.
  3. Exemplars em todo lugar que importa. Configure span-to-metrics para que gráficos de latência, erro e throughput anexem IDs de trace. Garanta que seu backend de métricas suporte consultar exemplars por clique.
  4. Estabeleça SLOs de cardinalidade. Faça cumprir: nenhuma métrica com cardinalidade de label acima de 1.000 valores únicos/dia; nenhuma nova chave de label sem design review; nenhuma chave de alta cardinalidade em métricas quentes. Adicione checks de CI que consultem seu backend por churn de séries e falhem PRs que excedam limites.
  5. Reestruture os logs. Faça de request_id um campo de primeira classe. Registre linhas JSON com um schema fixo. Roteie logs hot (7–14 dias) para busca rápida; todo o resto vai para storage de objetos com uma camada de consulta. Adicione regras de descarte para DEBUG verboso e health checks no Collector ou no Vector/Fluentd.
  6. Construa o primeiro runbook de incidentes movido por OTel. Um checklist que começa em um dashboard de métricas, salta para exemplars, abre o trace certo e busca logs correlacionados por request_id. Cronometre. Mire em menos de 5 minutos até o “primeiro sinal útil”.

Dias 61–90: Trave os Custos, Prove os Resultados e Automate

  1. Coloque guardrails de custo no código. Defina orçamentos por serviço para traces (ex.: máx. 2 GB/dia), séries de métricas (máx. N séries ativas) e logs (GB/dia). Conecte autoscaling ou backpressure no Collector para descartar dados não críticos quando o orçamento estourar.
  2. Rode um game day. Quebre algo benigno (aumente a latência em um serviço folha). Meça do alerta à causa raiz com e sem exemplars. Espere um diagnóstico 2–3× mais rápido quando configurado direito. Se não vir isso, sua amostragem ou exemplars precisam de tuning.
  3. Codifique as convenções semânticas. Documente quais OTel semantic conventions você segue. Forneça trechos específicos por linguagem e linters. Adicione um checklist de pré-merge.
  4. Dimensione corretamente sua retenção. Traces: 7 dias hot, 30 dias warm se você faz RCA com frequência. Métricas: 18 meses com downsampling. Logs: 7–14 dias hot, 90–365 dias cold. Se você não consegue justificar o dia extra, não pague por ele.
  5. Decida vendor vs self-host para o próximo ano. Se você não consegue operar storage com confiabilidade, compre. Se seu volume é previsível e >200 GB/dia, rodar Tempo/Mimir/ClickHouse por conta própria pode custar 20–30% do preço de vendors. A troca é headcount de SRE. Um pod nearshore focado pode fechar a lacuna com 20–30% menos custo de mão de obra que as taxas dos EUA com 6–8 horas de sobreposição de fuso horário.
  6. Publique o Contrato de Observabilidade. Uma página: SLOs, orçamentos, atributos aprovados, regras de amostragem, regras de identidade de serviço e runbooks. Trate mudanças como ADRs.

Trade-offs Que Você Deve Abraçar (Não Evitar)

  • Amostragem não é pecado. Você não pode pagar 100% de traces em escala. Você não precisa deles. O que o plantonista precisa é “manter o que é ruim e o que é estranho”. Amostragem tail-based alinhada a SLOs faz exatamente isso.
  • Logs não substituem traces, e vice-versa. Traces contam tempo e causalidade; logs contam fatos. Correlacione com request_id e exemplars. Se você não consegue clicar de um pico para o trace, você não terminou o trabalho.
  • Não persiga cobertura semântica perfeita. 80% de convenções consistentes agora vencem 100% de conformidade teórica nunca. Congele as chaves e itere.
  • Observabilidade self‑hosted não é de graça. Sim, o custo de storage cai dramaticamente. Não, não vai se operar sozinho. Orce 0,25–0,5 FTE de SRE por 1 TB/dia de ingestão para cuidado e alimentação se você quiser SLOs nos quais pode apostar uma semana de plantão.

Como É o Bom aos 90 Dias

  • O plantonista começa em um único lugar. Um único dashboard RED com exemplars, de onde você clica para traces e depois para logs correlacionados sem trocar de ferramentas ou abas.
  • Custos sob guardrails, não na base da esperança. Você sabe os GB diários por tipo de telemetria, como a amostragem muda isso e quando os orçamentos vão acionar backpressure.
  • A cobertura de traces é intencional. 100% dos 5xx mantidos; traces lentos p95 mantidos; requisições normais amostradas em 2–10% dependendo da criticidade do serviço. Você consegue responder “o que aconteceu” e “por que agora”.
  • A cardinalidade está domada. Nenhuma métrica com >1.000 valores únicos de label/dia. Nenhuma PII em atributos. Dados de alta cardinalidade vivem em logs, não em métricas quentes.
  • A propagação funciona nos limites que antes falhavam. Você consegue seguir a jornada do usuário em HTTP → fila → worker → serverless sem o trace se desfazer.

Armadilhas Comuns (E Como Desviá-las)

  • “A gente arruma a amostragem depois.” Depois nunca chega. Coloque amostragem tail-based no Collector até o Dia 60 com regras e orçamentos explícitos.
  • Deixar a autonomia por time atropelar a identidade de serviço. Você pode descentralizar muita coisa. Isto não. Quebre builds que não definem service.name corretamente.
  • Misturar labels crus e com escopo de usuário em métricas quentes. Se você precisa de analytics por usuário, isso é problema de data warehouse ou ClickHouse. Mantenha qualquer coisa por usuário fora de Prometheus/Mimir.
  • Perseguir 100% de autoinstrumentação. Auto ajuda, mas spans de negócio nos caminhos dourados exigem trabalho manual. Dê aos times uma receita de 1–2 horas para “adicionar um span em torno deste caso de uso”.
  • Enviar ruído de dev/test para backends de produção. Roteie não‑prod para um pipeline separado. Melhor: descarte a maior parte. Observabilidade deve espelhar a realidade de produção, não testes unitários.

Uma Nota Sobre Compliance e Privacidade

OTel é um ímã de PII se você for descuidado. Trate a governança de atributos como um controle de privacidade:

  • Elimine identificadores de usuário na borda. Se um caso de uso realmente exigir, faça hash ou bucket e documente a política de retenção e acesso.
  • Limpe segredos no Collector. Adicione processadores que redijam bearer tokens, chaves de API e e‑mails antes do storage. Nunca dependa dos times de app para “lembrar”.
  • Audite. Consultas mensais por padrões de PII em atributos e logs. Se você não consegue provar que a limpeza funcionou, ela não funcionou.

Checklist de Ferramentas Para Usar Amanhã

  • Processadores do Collector: batch, memory_limiter, tail_sampling, attributes (drop/redact), transform (normalizar atributos), k8sattributes, spanmetrics, probabilistic_sampler (para serviços de baixo tráfego), resourcedetection.
  • Dashboards: RED por serviço; grafo global de serviços; SLOs por jornada com orçamentos de erro; “Encontrar Trace” com filtros para service.name, http.route, status_code e release.version.
  • Runbooks: 1) Comece no painel de SLO. 2) Clique no exemplar. 3) Inspecione o caminho crítico do trace. 4) Vá para logs pelo request_id. 5) Capture a timeline. 6) Decida rollback vs mitigar.

OpenTelemetry é a aposta certa. A dor inicial não é um veredito; é um sinal de que você instalou canos sem decidir o que queria fazer fluir por eles. Dê às suas equipes uma estrela do norte, coloque o Collector no comando e faça orçamento por SLOs, não por feeling. Daqui a noventa dias você terá custos menores, resposta a incidentes mais rápida e um sistema que engenheiros de plantão realmente usam.

Principais Lições

  • Decida seus SLOs e orçamentos primeiro; conecte cada escolha de OTel a eles.
  • Coloque o OTel Collector no meio e migre para amostragem tail-based até o Dia 60.
  • Faça cumprir identidade e semântica: service.name, service.namespace, service.version são inegociáveis.
  • Use exemplars para ligar métricas a traces; torne “Encontrar Trace” uma ação em 2 cliques.
  • Interrompa a cardinalidade: allowlist de atributos, mate baggage por padrão e adicione checks de CI.
  • Reestruture logs em hot estruturado + cold barato; correlacione via request_id.
  • Trave custos com orçamentos de dados por serviço e backpressure no Collector.
  • Espere reduções de 50–70% no custo e diagnósticos 2–3× mais rápidos após o tuning.

Ready to scale your engineering team?

Tell us about your project and we'll get back to you within 24 hours.

Start a conversation