Observabilidade e monitoramento: guia completo para times de engenharia

Todo time de engenharia monitora a produção. Poucos conseguem responder à pergunta «por que o sistema está se comportando assim?» sem uma longa sessão de investigação. A diferença entre monitoramento e observabilidade não é uma escolha de ferramenta: é uma filosofia de projeto que determina a rapidez com que o time entende e responde a falhas que ninguém previu.

O monitoramento tradicional pressupõe que você sabe o que observar. Você define limiares de CPU, confere códigos de estado e chama alguém quando o disco passa de 90%. Isso funciona para falhas conhecidas. Mas sistemas distribuídos modernos quebram de maneiras que nenhum painel antecipou: uma piora sutil de latência num serviço entope uma fila, o que aparece como esgotamento do conjunto de conexões ao banco e só se manifesta nos picos. Sem poder fazer perguntas livres sobre o estado interno, você voa às cegas.

Por que a observabilidade vai além do monitoramento básico

Observabilidade é a propriedade de um sistema que permite inferir seu estado interno a partir das saídas externas. O monitoramento avisa que algo está errado; a observabilidade deixa você descobrir o que deu errado, mesmo numa falha que você nunca imaginou. A distinção é decisiva: o monitoramento é guiado por alertas e preso a painéis; a observabilidade é guiada por perguntas e rica em dados.

Quando o sistema emite dados estruturados de alta cardinalidade em registros, métricas e rastros, você consegue correlacionar eventos, descer até usuários ou requisições específicas e descobrir a causa de incidentes que nenhum alerta por limiar pegaria. Times que investem em observabilidade reduzem o tempo médio de resolução em uma ordem de grandeza, porque gastam menos tempo adivinhando e mais agindo sobre evidências.

«O monitoramento diz se um sistema está funcionando. A observabilidade deixa você perguntar por que não está. A segunda é pré-requisito para operar sistemas que você não entende por completo — ou seja, todo sistema em produção.»

Os três pilares: registros, métricas e rastros

O ecossistema da observabilidade se apoia em três tipos de dados complementares, cada um com um papel distinto. Tratá-los como um sinal único, e não como silos separados, é a chave para investigar com eficácia.

Registros: relatos imutáveis de eventos

Registros são anotações datadas de eventos discretos. São o sinal mais fino: capturam exatamente o que aconteceu num instante específico. Uma linha bem estruturada traz contexto suficiente — identificador da requisição, nome do serviço, duração, detalhe do erro — para reconstruir o caminho de execução sem cruzar várias fontes.

O erro mais comum é tratar registros como texto sem estrutura. Vasculhar arquivos planos funcionava com três servidores; em escala, registros sem estrutura são ruído. Cada linha precisa ser analisável, carregar metadados estruturados e seguir um esquema consistente em todos os serviços da sua arquitetura.

Métricas: medições agregadas ao longo do tempo

Métricas são representações numéricas do estado do sistema, medidas em intervalos. São feitas para armazenamento econômico e agregação rápida. Respondem a «quantas requisições por segundo?» ou «qual a latência no percentil 99?». Diferente dos registros, descartam o dado de cada requisição: trocam granularidade por compressão e velocidade.

Os tipos usuais — contadores, medidores, histogramas e resumos — servem a propósitos distintos. Contadores acompanham valores acumulados, como o total de requisições. Medidores registram valores instantâneos, como uso de memória. Histogramas distribuem observações em faixas configuráveis, por exemplo para distribuições de latência. Escolher o tipo certo evita agregações enganosas e cardinalidade desperdiçada.

Rastros: o ciclo de vida completo de uma requisição

Rastros distribuídos acompanham uma única requisição enquanto ela atravessa as fronteiras entre serviços. Cada rastro é composto de trechos: operações nomeadas, com marcas de início e fim, que capturam o trabalho feito por um serviço ou função. Rastros são o único sinal capaz de reconstruir o ciclo de vida completo de uma requisição numa arquitetura de microsserviços.

Sem rastros, uma página lenta poderia ser atribuída a qualquer um das dezenas de serviços envolvidos. Com rastros, você identifica que o gargalo é a consulta ao banco do serviço de usuários, que leva 800 milissegundos, enquanto todos os outros trechos terminam abaixo de 50. Essa precisão é impossível só com registros ou métricas.

«Registros dizem o que aconteceu. Métricas dizem quantas vezes aconteceu. Rastros dizem como tudo se encaixa. Você precisa dos três para atravessar um incidente de produção sem fazer suposições.»

Configuração e instrumentação com OpenTelemetry

O OpenTelemetry é o padrão do setor para gerar, coletar e exportar telemetria. Oferece, entre linguagens, um único conjunto de APIs e kits que emitem registros, métricas e rastros num formato neutro em relação ao fornecedor. Adotá-lo elimina o aprisionamento a um fabricante e garante que sua instrumentação funcione tanto com uma plataforma comercial quanto com uma esteira própria.

Instrumentação automática e manual

A maioria dos kits oferece instrumentação automática: ganchos sem código em bibliotecas e arcabouços populares. Uma única chamada de inicialização pode instrumentar servidores HTTP, clientes de banco, filas de mensagens e chamadas gRPC. O automático cobre os caminhos comuns; para código crítico do negócio, middleware próprio e operações do domínio, é preciso instrumentar à mão.

import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc";
import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
import { ExpressInstrumentation } from "@opentelemetry/instrumentation-express";
import { PgInstrumentation } from "@opentelemetry/instrumentation-pg";
import { Resource } from "@opentelemetry/resources";
import { SEMRESATTRS_SERVICE_NAME } from "@opentelemetry/semantic-conventions";

const sdk = new NodeSDK({
  resource: new Resource({
    [SEMRESATTRS_SERVICE_NAME]: "payment-service",
  }),
  traceExporter: new OTLPTraceExporter({
    url: "http://otel-collector:4317",
  }),
  metricExporter: new OTLPMetricExporter({
    url: "http://otel-collector:4317",
  }),
  instrumentations: [
    new HttpInstrumentation(),
    new ExpressInstrumentation(),
    new PgInstrumentation(),
  ],
});

sdk.start();
process.on("SIGTERM", () => sdk.shutdown());

A arquitetura do coletor do OpenTelemetry

O coletor do OpenTelemetry é um intermediário neutro que recebe, processa e exporta telemetria. É a espinha dorsal de qualquer esteira de observabilidade em produção. Implantar um coletor por máquina, ou como conjunto na sua infraestrutura de Kubernetes, desacopla a instrumentação da escolha do destino e permite agrupar, filtrar, amostrar e transformar os dados antes que cheguem à plataforma.

Os coletores podem receber processadores de amostragem no fim do rastro: guardam rastros completos de requisições lentas ou com erro e descartam a maior parte do tráfego saudável. O custo de armazenamento cai muito sem sacrificar a capacidade de investigar justamente as requisições que importam.

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
    timeout: 1s
    send_batch_size: 1024
  memory_limiter:
    check_interval: 1s
    limit_mib: 512
  filter:
    error_mode: ignore
    traces:
      span:
        - 'attributes["http.target"] == "/healthz"'
        - 'attributes["http.target"] == "/metrics"'
  attributes:
    actions:
      - key: environment
        value: production
        action: upsert

exporters:
  otlp:
    endpoint: "collector.example.com:443"

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, filter, batch, attributes]
      exporters: [otlp]
    metrics:
      receivers: [otlp]
      processors: [memory_limiter, batch, attributes]
      exporters: [otlp]
    logs:
      receivers: [otlp]
      processors: [memory_limiter, batch, attributes]
      exporters: [otlp]

Padrões de registro estruturado

Registrar de forma estruturada significa emitir entradas num formato legível por máquina — normalmente JSON — com nomes de campo consistentes entre serviços. Os registros deixam de ser um problema de busca e viram um problema de consulta. Quando todos os times usam as mesmas convenções para identificadores de requisição, nomes de serviço, códigos de erro e durações, você consulta toda a infraestrutura sem escrever analisadores sob medida.

Projetar o esquema dos registros

Todo evento estruturado deveria trazer um mínimo de atributos: marca de tempo, nível de severidade, nome do serviço, identificador de rastro, identificador de trecho e mensagem. Além disso, acrescente campos do domínio, mas respeite as convenções de nome. Use sempre a mesma grafia, ponha um prefixo comum nos campos ligados ao usuário e guarde o detalhe do erro num objeto aninhado, em vez de concatená-lo à mensagem.

  • Inclua sempre trace_id e span_id para correlacionar registros com rastros
  • Use um nível (debug, info, warn, error) que corresponda a sinais acionáveis, não à conveniência de quem programa
  • Nunca registre dados sensíveis — dados pessoais, segredos ou tokens —, nem em desenvolvimento
  • Mantenha as mensagens fixas e ponha os dados variáveis em campos estruturados, para poder agregar
  • Uniformize o formato da marca de tempo em todos os serviços: RFC 3339 ou milissegundos Unix

Armadilhas frequentes

O erro mais caro é registrar demais. Campos de alta cardinalidade, como identificadores de usuário ou endereços IP, podem inflar o volume em ordens de grandeza. Amostre os registros de depuração volumosos e reserve o detalhe para rastros específicos ou condições de erro. O segundo erro é a inconsistência de nomes: um serviço com user_id, outro com customerId e um terceiro com user.id tornam impossíveis as consultas entre serviços sem camadas de transformação.

«Uma linha de registro que não pode ser consultada bem poderia não existir. O registro estruturado não é sobre legibilidade: é sobre tornar cada entrada uma cidadã de primeira classe da sua plataforma de observabilidade.»

Rastros distribuídos em microsserviços

Rastros distribuídos são a ferramenta mais eficaz para investigar arquiteturas de microsserviços. Um rastro que atravessa vinte serviços mostra exatamente onde o tempo é gasto, quais requisições falham e como os erros se propagam. Sem rastros, investigar um fluxo de compra lento significa olhar registros em uma dúzia de serviços e adivinhar a causalidade.

Propagação do contexto de rastro

O contexto de rastro precisa ser propagado em cada fronteira de serviço: cabeçalhos HTTP, metadados de filas de mensagens, metadados gRPC e até através de fronteiras assíncronas, como tarefas agendadas ou processos em segundo plano. O OpenTelemetry cuida disso sozinho se você usar suas bibliotecas para HTTP, gRPC e mensageria. O identificador de rastro flui do portal de entrada por cada serviço seguinte, recolhendo trechos pelo caminho.

  • Instrumente todos os pontos de entrada: portais de API, balanceadores de carga, controladores de entrada
  • Propague o contexto pelas filas de mensagens usando cabeçalhos ou metadados da mensagem
  • Inclua o identificador de rastro na saída dos registros, para permitir a correlação
  • Adote uma amostragem que preserve os rastros com erro ou latência alta
  • Acrescente atributos próprios aos trechos para o contexto de negócio: faixa do cliente, código do produto, região

Ler e interpretar um rastro

Um rastro bem anotado revela o caminho crítico de uma requisição. Olhe o trecho de maior duração: é o seu gargalo. Procure trechos com eventos de erro ou com muitos atributos distintos. Compare rastros de requisições bem-sucedidas e fracassadas para achar padrões. Se os rastros mostram sistematicamente uma chamada seguinte estourando o tempo, você tem um problema de dependência, não um defeito da aplicação.

Alertas: sobre o que alertar e como evitar a fadiga

A fadiga de alertas é a maior ameaça à resposta a incidentes. Quando um time recebe cinquenta avisos por plantão, todos são ignorados. O objetivo de uma boa estratégia não é detectar toda anomalia, e sim produzir um conjunto pequeno e de alto sinal de notificações que exijam julgamento humano. Todo o resto pertence a um painel ou a uma consulta.

O sistema de níveis

Organize os alertas em três níveis. O nível 1 aciona imediatamente quem está de plantão, porque indica um problema visível ao usuário: taxa de erro alta, serviço totalmente fora do ar, ou consumo do orçamento de erro acima do limiar. O nível 2 abre um chamado para triagem no próximo dia útil: latência elevada, componentes degradados mas não caídos. O nível 3 é informativo: certificado prestes a expirar, limites de armazenamento se aproximando.

  • Alerte apenas por sintomas, não por causas. O usuário vê um erro 5xx: alerte sobre isso, não sobre o uso de CPU
  • Use condições múltiplas que exijam desvio sustentado antes de disparar (por exemplo, cinco minutos acima do limiar)
  • Estabeleça no máximo três alertas que acordam alguém por pessoa e por plantão, para preservar a qualidade do sinal
  • Revise e pode as regras a cada trimestre: alertas obsoletos corroem a confiança no sistema
  • Inclua em cada alerta o link de um guia de atuação, para que quem responde saiba os três primeiros passos

Alertas por ritmo de consumo

Esses alertas disparam quando o orçamento de erro está sendo consumido mais rápido que o previsto. Diferente de limiares fixos, estão ligados diretamente aos seus objetivos de serviço. Se o objetivo é 99,9% de disponibilidade em 30 dias, você dispõe de cerca de 43 minutos de indisponibilidade. O alerta dispara quando o ritmo projetado esgotaria a janela antes do planejado, dando tempo de reagir antes de descumprir o objetivo.

Construir painéis úteis

A maioria dos painéis é um cemitério de gráficos sem uso. Um painel é útil quando responde a uma pergunta específica sem exigir interpretação. Os melhores são feitos para um único perfil e um único uso: um painel de plantão para triar incidentes, um painel semanal para planejar capacidade e um painel de time para acompanhar o cumprimento dos objetivos.

O painel de plantão

Deve caber numa tela e responder a quatro perguntas: o serviço está no ar? qual é a taxa de erro? como está a distribuição de latência? o orçamento de erro foi estourado? Cada gráfico precisa de uma linha de limiar clara, para que se veja de imediato se o valor atual é saudável. Não coloque mais de seis gráficos: durante um incidente, a carga mental importa.

  • Comece pelas métricas RED: ritmo (requisições por segundo), erros (requisições que falharam), duração (percentis de latência)
  • Acrescente as métricas USE para a infraestrutura: utilização, saturação e erros por recurso
  • Mostre o cumprimento do objetivo e o ritmo de consumo como indicadores bem visíveis
  • Ligue cada gráfico aos seus registros ou à sua consulta de rastros, para descer ao detalhe com um clique
  • Use escalas logarítmicas para latência: as lineares escondem variações importantes nas caudas

Antipadrões comuns

O antipadrão mais comum é o painel que mostra todas as métricas que sua infraestrutura produz. Essas «paredes verdes» criam falsa sensação de segurança e tornam impossível achar o sinal durante um incidente. Outros: gráficos de pizza para séries temporais, várias métricas empilhadas em eixos inconsistentes, linhas de limiar sem rótulo. Se um gráfico precisa de um comentário para ser entendido, ele não pertence ao painel.

SLI, SLO e orçamentos de erro

Indicadores, objetivos e orçamentos de erro formam o contrato entre o seu time e os seus usuários. Os indicadores são as medições brutas: latência, taxa de erro, vazão. Os objetivos são os compromissos assumidos: 99,9% das requisições abaixo de 200 milissegundos. O orçamento de erro é a margem de falha admitida — aquele 0,1% que dá ao time permissão para publicar, experimentar e iterar sem medo de quebrar promessas.

Escolher indicadores com sentido

Um bom indicador olha para o usuário, é mensurável e leva à ação. Disponibilidade (parcela de requisições bem-sucedidas), latência (parcela abaixo de um limiar) e frescor (idade dos dados servidos) são os mais comuns em serviços web. O essencial é medir da perspectiva de quem usa: uma requisição que o seu servidor resolve em 50 milissegundos mas leva dois segundos numa rede móvel lenta é, para o usuário, um fracasso.

Definir objetivos realistas

Um objetivo de 99,999% soa impressionante, mas traz um custo de engenharia enorme. Cada nove a mais exige cerca de dez vezes mais investimento em redundância, testes e ferramental de operação. Comece com 99,9% na maioria dos serviços e guarde objetivos maiores para os caminhos críticos voltados ao cliente. Seja honesto sobre o que consegue sustentar: um objetivo constantemente descumprido é pior do que nenhum, porque normaliza a falha e corrói a confiança nas métricas.

Como o orçamento de erro dá velocidade

O orçamento de erro transforma a confiabilidade de restrição em risco mensurável. Quando está cheio, o time publica à vontade, sabendo que há folga. Quando se esgota, ele suspende entregas não críticas e se dedica só à confiabilidade. Surge assim um processo de decisão claro e baseado em dados, que substitui discussões subjetivas sobre se uma entrega é «segura o bastante».

Observabilidade em ambientes sem servidor e na borda

Computação sem servidor e na borda trazem dificuldades próprias. As funções são efêmeras, a infraestrutura é abstraída e a execução se espalha por pontos de presença mundo afora. O monitoramento clássico por agente não serve, porque não há máquina onde hospedá-lo. Aqui é preciso outra abordagem: telemetria enviada pelo próprio código, rastros finos para as partidas a frio e controle cuidadoso da cardinalidade em implantações globais.

Padrões próprios do sem servidor

A partida a frio domina a latência. Instrumente a inicialização separada do tratamento da requisição, para distinguir a latência de partida da latência da lógica de negócio. Use registro estruturado para capturar o contexto da invocação — identificador da requisição, região, versão da função, ambiente de execução — e emita métricas próprias de número de invocações, duração e taxa de erro de forma assíncrona, para não bloquear a resposta.

  • Meça a duração da partida a frio como métrica própria: ela é invisível nas métricas padrão do provedor
  • Use propagadores do OpenTelemetry compatíveis com o mecanismo de extensão da sua plataforma
  • Exporte a telemetria em lotes, para não somar latência ao tempo de execução da função
  • Configure métricas derivadas de registros onde não houver API para métricas próprias
  • Marque toda a telemetria com ambiente, região e versão da função, para filtrar com eficácia

Particularidades da borda

Plataformas de borda executam código em dezenas de locais pelo mundo. Essa dispersão torna impraticável a coleta centralizada clássica. Use ferramentas pensadas para a borda, que coletem telemetria em cada ponto e a agreguem centralmente com pouco peso. Acompanhe a taxa de erro por região: um problema de rede local pode degradar o serviço numa área enquanto a média global parece saudável.

Construir uma cultura de observabilidade

Ferramentas e esteiras são necessárias, mas não bastam. A parte mais difícil da observabilidade é cultural. O time precisa valorizar o código instrumentado tanto quanto o código testado. Toda funcionalidade nova deveria incluir instrumentação na sua definição de pronto, assim como inclui testes unitários e revisão. Isso exige infraestrutura: bibliotecas compartilhadas, convenções documentadas e, em cada time, alguém que puxe o assunto.

Tornar a observabilidade assunto de primeira ordem

Comece escrevendo um documento de projeto da telemetria, que defina os campos padrão, as convenções de nome das métricas e os requisitos de rastreamento para cada serviço. Faça dele parte da entrada em operação de todo serviço novo. Coloque na integração contínua verificações automáticas que exijam instrumentação mínima: rejeite, por exemplo, mudanças que acrescentem manipuladores HTTP sem o rastreamento ou os registros estruturados correspondentes.

  • Inclua a instrumentação na definição de pronto de cada funcionalidade
  • Faça periodicamente dias de exercício em que o time investiga usando apenas painéis e consultas de rastros
  • Comemore os acertos: divulgue análises de incidentes que mostrem como boa telemetria levou a uma resolução rápida
  • Designe responsáveis rotativos que revisem a cada ciclo a qualidade da telemetria entre os times
  • Invista em bibliotecas de instrumentação compartilhadas, que tornem o certo mais fácil do que o errado

O ciclo de realimentação

Observabilidade não é uma implantação única, e sim um ciclo contínuo: instrumentar, entregar, observar, aprender e melhorar. Quando um incidente revela um ponto cego — uma métrica que não era acompanhada, um campo de registro ausente, um rastro descartado —, trate isso como um defeito da sua plataforma de observabilidade e corrija. Com o tempo, a telemetria fica mais completa, a investigação acelera e o time ganha a confiança de saber que consegue entender qualquer falha, inclusive as que nunca viu.

«O objetivo da observabilidade não é evitar incidentes. É garantir que, quando eles acontecerem, o time tenha os dados, as ferramentas e a confiança para resolvê-los antes que os usuários percebam.»

Adotar observabilidade é um caminho, não uma compra. Comece pequeno: instrumente de ponta a ponta um serviço crítico, construa um único painel útil e escreva um objetivo de serviço que faça sentido. Deixe o valor falar por si. Depois que o time viver, em pleno incidente, a diferença entre adivinhar e saber, não vai querer voltar atrás.

See what your own repository can account for.

Thirty minutes on a repository you choose, including the part the record cannot attribute.