Monitoramento e observabilidade em produção: logs, métricas e traces que funcionam
Guia prático de observabilidade com OpenTelemetry, Grafana, Prometheus e Sentry. Alertas que não gritam à toa e padrões reais de resposta a incidentes.
O problema real: "caiu e ninguém viu"
Toda equipe que mantém software em produção já passou por isso. O cliente liga reclamando que o sistema está lento. A equipe abre o servidor, olha uns logs, não encontra nada óbvio, reinicia o serviço e torce. O problema some por duas horas e volta.
Isso acontece porque a maioria das aplicações em produção não tem observabilidade. Tem, no máximo, um console.log perdido e um healthcheck que retorna 200 mesmo quando metade das queries estão demorando 30 segundos.
Observabilidade é a capacidade de entender o estado interno de um sistema a partir dos dados que ele emite. Não é um dashboard bonito. É conseguir responder, em menos de cinco minutos, por que um request específico falhou para um usuário específico às 14h32 de uma terça-feira.
Os três pilares: logs, métricas e traces
Esses três tipos de dados se complementam. Nenhum deles sozinho resolve o problema.
| Pilar | O que responde | Exemplo |
|---|---|---|
| Logs | O que aconteceu? | ERROR: connection refused to postgres:5432 |
| Métricas | Qual o comportamento agregado? | p99 de latência subiu de 200ms para 1.2s |
| Traces | Qual o caminho de um request? | Request passou por API > Auth > Cache miss > DB > Response em 850ms |
Logs são úteis para debug pontual, mas péssimos para entender tendências. Se você tem 50 mil requests por minuto, ninguém vai ler log linha por linha.
Métricas mostram o panorama. Latência subindo, taxa de erro aumentando, fila crescendo. Mas não dizem por quê.
Traces conectam os pontos. Mostram o caminho completo de um request através dos serviços, com tempo gasto em cada etapa. É onde você descobre que o gargalo está na chamada ao serviço de nota fiscal, não no banco de dados.
OpenTelemetry: o padrão que unifica tudo
Antes do OpenTelemetry (OTel), cada ferramenta de monitoramento tinha seu SDK próprio. Você instrumentava o código para o Datadog, depois queria migrar para o Grafana Cloud e precisava reescrever tudo.
O OpenTelemetry resolve isso. É um padrão aberto, mantido pela CNCF, que define como coletar e exportar logs, métricas e traces. Você instrumenta uma vez e manda os dados para qualquer backend compatível.
Instrumentação com OTel em Node.js
// tracing.ts
import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({
url: 'http://otel-collector:4318/v1/traces',
}),
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({
url: 'http://otel-collector:4318/v1/metrics',
}),
exportIntervalMillis: 15000,
}),
instrumentations: [
getNodeAutoInstrumentations({
'@opentelemetry/instrumentation-http': { enabled: true },
'@opentelemetry/instrumentation-express': { enabled: true },
'@opentelemetry/instrumentation-pg': { enabled: true },
}),
],
});
sdk.start();
O auto-instrumentations-node já captura automaticamente chamadas HTTP, queries no PostgreSQL, operações Redis e mais. Sem precisar alterar o código de negócio.
Prometheus e Grafana: métricas que fazem sentido
Prometheus coleta métricas via pull (ele vai buscar nos seus serviços) e armazena em série temporal. Grafana renderiza essas métricas em dashboards.
A combinação funciona bem, mas só se você souber o que medir. Quatro métricas obrigatórias para qualquer serviço HTTP (os "golden signals" do Google SRE):
- Latência: quanto tempo os requests demoram
- Tráfego: quantos requests por segundo
- Erros: taxa de respostas 5xx
- Saturação: uso de CPU, memória, conexões de banco
Configuração do Prometheus
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "alerts.yml"
alerting:
alertmanagers:
- static_configs:
- targets: ['alertmanager:9093']
scrape_configs:
- job_name: 'api-gateway'
metrics_path: '/metrics'
static_configs:
- targets: ['api:3000']
relabel_configs:
- source_labels: [__address__]
target_label: instance
- job_name: 'postgres'
static_configs:
- targets: ['postgres-exporter:9187']
- job_name: 'redis'
static_configs:
- targets: ['redis-exporter:9121']
PromQL: queries que importam
Não adianta coletar métrica se você não sabe consultar. Algumas queries que usamos em projetos reais:
# Taxa de erro nos últimos 5 minutos
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m])) * 100
# Latência p95 por rota
histogram_quantile(0.95,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le, route)
)
# Conexões ativas no PostgreSQL vs limite
pg_stat_activity_count / pg_settings_max_connections * 100
Alertas que não gritam à toa
Aqui está a opinião forte: a maioria das equipes configura alertas errados. Alerta para CPU acima de 70%. Alerta para disco acima de 80%. Alerta para qualquer erro 500.
O resultado é alert fatigue. Depois de duas semanas recebendo 40 notificações por dia, todo mundo ignora. E quando o alerta real aparece, ninguém reage.
Regras para alertas que funcionam:
Alerte sobre sintomas, não causas. CPU alta não é problema se a latência está normal. O que importa para o usuário é: o sistema está respondendo? Está correto? Está rápido o suficiente?
Use janelas de tempo adequadas. Um spike de 30 segundos na latência não precisa de alerta. Latência p95 acima de 500ms por mais de 5 minutos, sim.
Defina severidades reais. Crítico significa "acorde alguém às 3h da manhã". Se não justifica isso, não é crítico.
# alerts.yml
groups:
- name: api-alerts
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m])) > 0.05
for: 5m
labels:
severity: critical
annotations:
summary: "Taxa de erro acima de 5% por mais de 5 minutos"
- alert: HighLatency
expr: |
histogram_quantile(0.95,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le)
) > 0.5
for: 5m
labels:
severity: warning
annotations:
summary: "Latência p95 acima de 500ms"
- alert: DatabaseConnectionSaturation
expr: pg_stat_activity_count / pg_settings_max_connections > 0.85
for: 3m
labels:
severity: critical
annotations:
summary: "Pool de conexões PostgreSQL acima de 85%"
Sentry: erros com contexto
Prometheus e Grafana são ótimos para métricas, mas quando um erro acontece, você precisa de contexto: stack trace, dados do request, estado do usuário. É onde o Sentry entra.
O Sentry captura exceções automaticamente e agrupa erros similares. A diferença entre um log ERROR: something failed e um evento no Sentry é que o segundo vem com stack trace completo, breadcrumbs (ações que o usuário fez antes do erro), tags customizadas e histórico de ocorrências.
Uma prática que funciona bem: configure o Sentry para capturar apenas erros não tratados e erros de negócio marcados explicitamente. Capturar todo catch polui a ferramenta e reduz o sinal.
Resposta a incidentes: o processo importa mais que a ferramenta
Quando algo quebra em produção, a ferramenta não resolve sozinha. O que resolve é ter um processo claro.
1. Detectar. Alerta chega no canal certo (Slack, PagerDuty). Alguém assume como responsável em até 10 minutos.
2. Mitigar. Primeiro, pare o sangramento. Rollback, feature flag, scale up. Não é hora de debugar a causa raiz.
3. Diagnosticar. Com o sistema estável, use traces para encontrar o request que falhou, métricas para entender a amplitude do problema e logs para o detalhe técnico.
4. Corrigir e prevenir. Fix deployado, post-mortem escrito. O post-mortem não é para culpar. É para documentar o que aconteceu, o que foi feito e o que vai mudar para não repetir.
Equipes que pulam o post-mortem repetem os mesmos incidentes. Equipes que fazem post-mortem sem action items também.
O que recomendamos na prática
Depois de implementar observabilidade em diversos projetos de diferentes portes, algumas conclusões:
Comece pelo Prometheus + Grafana. É open-source, tem comunidade enorme e resolve 80% dos casos. Não precisa de Datadog no dia um.
Adote OpenTelemetry desde o início. Instrumentar depois é muito mais caro. O OTel tem auto-instrumentação que cobre os casos básicos com poucas linhas de código.
Sentry para erros, não para métricas. Cada ferramenta tem sua função. Misturar responsabilidades gera ruído.
Invista nos alertas. Um alerta bem calibrado vale mais que dez dashboards. Revise os alertas a cada trimestre e delete os que ninguém olha.
Trate o monitoramento como código. Dashboards, alertas e configurações do Prometheus versionados no repositório, deployados via CI/CD. Se alguém precisa clicar na interface do Grafana para criar alerta, o processo está frágil.
Observabilidade não é um projeto com data de entrega. É uma disciplina contínua que melhora conforme a equipe aprende com os próprios incidentes. Se a sua equipe precisa de ajuda para implementar monitoramento que funciona de verdade, fale com a Bradata. Trabalhamos com times de engenharia que querem dormir tranquilos quando o sistema está em produção.
Precisa de um talento tech agora?
Fale com a Bradata e receba uma proposta em 24 horas úteis.