01 - Métricas (Prometheus, CloudWatch, Datadog)
video: https://youtu.be/... no frontmatter da nota.Métricas (Prometheus, CloudWatch, Datadog)
Métricas são medições numéricas coletadas ao longo do tempo, armazenadas como séries temporais identificadas por um nome e um conjunto de rótulos. Elas representam a camada mais barata e mais agregada da observabilidade, permitindo responder perguntas do tipo "quanto", "com que frequência" e "a que velocidade" sobre o comportamento do sistema. Em produção, métricas sustentam três funções críticas: alertas baseados em limiares e SLOs, painéis de acompanhamento da saúde dos serviços e análise de tendências de capacidade. Diferentemente de logs e traces, uma métrica ocupa poucos bytes e pode ser consultada de forma agregada em segundos, mesmo sobre milhares de instâncias. Ferramentas como Prometheus, Amazon CloudWatch e Datadog dominam esse espaço, com modelos de coleta e modelos de custo bastante distintos. Dominar o modelo de dados de cada uma é pré-requisito para construir um sistema de monitoramento confiável e economicamente sustentável.
O problema que as métricas resolvem
Sem métricas, a única forma de saber se um serviço está saudável é acessá-lo manualmente ou esperar reclamação de usuário, o que significa descobrir incidentes tarde demais. A vibração subjetiva de "está lento" precisa ser convertida em números comparáveis, como p99 de latência, taxa de erro por segundo e utilização de recursos. Métricas tornam esse estado mensurável, historico e alertável, permitindo detectar regressões antes que virem indisponibilidades e comparar o comportamento de hoje com a linha de base de semanas anteriores. Elas também servem como linguagem comum entre times: engenharia, produto e negócio podem olhar a mesma série temporal e conversar sobre o mesmo fato. Por fim, sem contadores confiáveis de requisições, erros e duração, é impossível calcular SLOs e error budgets de maneira objetiva.
Modelo de dados e tipos de métrica
Uma série temporal em Prometheus é identificada pelo nome da métrica mais o conjunto de pares chave-valor chamados labels. Cada combinação única de nome e labels forma uma série distinta, e o servidor armazena amostras com timestamp para cada série. Escolher os tipos corretos é essencial, porque cada um serve a um propósito de cálculo diferente.
| Tipo | Comportamento | Uso típico | Cuidado principal |
|---|---|---|---|
| Counter | Só cresce, reinicia em restart | Total de requisições, erros, bytes processados | Nunca use o valor absoluto, use rate() |
| Gauge | Sobe e desce livremente | Memória usada, fila pendente, conexões ativas | Cuidado com picos momentâneos em alertas |
| Histogram | Distribui amostras em buckets | Latência e tamanho de payload, cálculo de quantis | Buckets mal definidos distorcem p99 |
| Summary | Calcula quantis no cliente | Quantis exatos para uma única instância | Não é agregável entre instâncias |
A regra prática é usar counters para eventos cumulativos, gauges para estado instantâneo, histograms para distribuições que precisam ser agregadas entre instâncias e summaries apenas em casos muito específicos. O erro clássico é tentar calcular p95 a partir de uma média de summaries de várias réplicas, o que não tem significado estatístico. Vale documentar, em um catálogo interno, o tipo e a unidade de cada métrica, porque a unidade, sejam segundos, milissegundos ou bytes, precisa ser explícita no nome para evitar comparações sem sentido.
Ciclo de coleta e configuração de scrape
No modelo pull, o ciclo começa com a descoberta de alvos por service discovery, seja a API do Kubernetes, DNS ou arquivos estáticos. Em seguida, o Prometheus aplica relabeling, que permite filtrar, renomear e descartar alvos antes da coleta, e dispara requisições HTTP contra o endpoint de métricas de cada alvo dentro do intervalo configurado. O resultado é gravado na TSDB local, com compressão eficiente, e fica disponível para consulta imediata pela API HTTP. A configuração abaixo resume um bloco de scrape típico.
scrape_configs:
# Descobre pods automaticamente pelas anotações do Kubernetes
- job_name: "kubernetes-pods"
kubernetes_sd_configs:
- role: pod
relabel_configs:
# Coleta apenas pods que anunciam o endpoint de métricas
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: "true"
# Renomeia a porta anotada para o alvo do scrape
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
target_label: __param_target
scrape_interval: 30s # Janela de amostragem por alvo
scrape_timeout: 10s # Tempo máximo de resposta por alvo
metrics_path: /metrics # Endpoint exposto pela aplicação
O intervalo de scrape é uma decisão de arquitetura: janelas curtas aumentam a resolução dos alertas e o custo de armazenamento, enquanto janelas longas podem atrasar a detecção de incidentes. Regra comum é 15 a 30 segundos para serviços críticos e 60 segundos para infraestrutura estável.
Modelo pull versus push
Prometheus adota o modelo pull: o servidor consulta endpoints HTTP expostos pelas aplicações em intervalos fixos, normalmente a cada 15 ou 30 segundos. Isso simplifica a detecção de instâncias mortas, já que uma instância que não responde ao scrape fica marcada como up == 0, e evita que a aplicação bloqueie enviando telemetria. CloudWatch e Datadog funcionam com agentes que enviam dados por push, o que facilita ambientes com componentes não expostos na rede, como funções serverless e cargas atrás de firewalls. O push também é o caminho natural para jobs curtos que terminam antes de qualquer scrape acontecer; para esses casos, o ecossistema Prometheus oferece o Pushgateway como ponte. Na prática, arquiteturas híbridas são comuns: pull para serviços de longa duração em Kubernetes, push para Lambda e para métricas de negócio de baixa frequência.
Labels e cardinalidade
Labels são a maior força do modelo Prometheus e, ao mesmo tempo, sua maior armadilha. Cada par adicional de label multiplica o número de séries armazenadas, e labels de alta cardinalidade, como ID de usuário, ID de requisição ou endereço IP, explodem o consumo de memória e disco do servidor. A orientação é manter cardinalidade finita e limitada: identificador de serviço, ambiente, região, método HTTP, código de status e tipo de erro são bons candidatos. Detalhes por requisição pertencem a logs e traces, não a métricas. Um exemplo típico de incidente de custo é instrumentar uma rota com o parâmetro de caminho como label e descobrir que um identificador dinâmico gerou centenas de milhares de séries. Vale lembrar que a fase de exportação do OpenTelemetry permite controlar quais atributos viram labels no backend, o que dá um ponto único de governança.
PromQL básico
PromQL é a linguagem de consulta do Prometheus e opera sobre seletores de séries com funções de janela temporal. O bloco a seguir mostra consultas usadas no dia a dia de operação.
# Taxa de requisições por segundo nas últimas 5 minutos, por handler
sum(rate(http_requests_total{job="checkout-api"}[5m])) by (handler)
# Taxa de erro (proporção de respostas 5xx) para calcular SLO de disponibilidade
sum(rate(http_requests_total{job="checkout-api", status=~"5.."}[5m]))
/ sum(rate(http_requests_total{job="checkout-api"}[5m]))
# Percentil 99 de latência a partir de histogram, em segundos
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
# Fila pendente acima do limite: gauge de consumidor com atraso
kafka_consumergroup_lag{group="pagamentos"} > 10000
Três detalhes evitam a maioria dos erros: rate() deve ser aplicado somente a counters e já lida com reinícios; divisões devem combinar agregações idênticas dos dois lados para que as séries façam pareamento correto; e histogram_quantile exige que a soma seja agrupada pelo label le, caso contrário o resultado é inconsistente entre réplicas.
CloudWatch e Datadog como alternativas gerenciadas
CloudWatch é a opção nativa da AWS, com ingestão automática de métricas de todos os serviços gerenciados e cobrança por métrica armazenada, alarmes e consultas. Sua linguagem de consulta, o CloudWatch Logs Insights e o Metric Math, é menos expressiva que PromQL, mas a integração com alarmes, EventBridge e SNS é imediata. Datadog é uma plataforma SaaS completa, com agentes universais, mais de mil integrações prontas, APM e um modelo de cobrança por host e por métrica customizada. As duas abstraem operação de armazenamento e alta disponibilidade, trocando custo operacional por custo financeiro, que cresce rápido quando a cardinalidade cresce sem controle.
| Aspecto | Prometheus | CloudWatch | Datadog |
|---|---|---|---|
| Modelo de coleta | Pull, scrape HTTP | Push via agentes e APIs | Push via agente universal |
| Modelo de custo | Infra própria, sem licença | Por métrica, alarme e consulta | Por host, por métrica customizada |
| Consulta | PromQL, muito expressiva | Metric Math e Insights | Language do Datadog, Editor visual |
| Ecossistema | Grafana e milhares de exporters | Nativo AWS | Mais de mil integrações |
| Custo de operação | Alta, exige gerenciar HA e retenção | Praticamente nula | Baixa, plataforma gerenciada |
| Melhor cenário | Kubernetes e ambientes cloud native | Cargas fortemente ancoradas na AWS | Empresas que querem plataforma única |
Da métrica ao SLO
Métricas só viram governança quando são vinculadas a objetivos de serviço. O caminho usual define um indicador de nível de serviço, por exemplo a proporção de requisições bem-sucedidas em menos de 300 ms, e um objetivo, como 99,9 por cento em janelas de 30 dias. Com counters de sucesso e falha em mãos, o cálculo cabe em uma única consulta, e o resultado alimenta tanto painéis de error budget quanto alertas de burn rate. O exemplo abaixo mostra o cálculo de disponibilidade e a fração de orçamento consumida.
# Disponibilidade acumulada em 30 dias para o serviço de checkout
1 - (
sum(increase(http_requests_total{job="checkout-api", status=~"5.."}[30d]))
/ sum(increase(http_requests_total{job="checkout-api"}[30d]))
)
# Taxa de consumo do error budget nas últimas 6 horas
# Compara quebras recentes com o ritmo tolerado pelo objetivo de 99,9 por cento
(
sum(increase(http_requests_total{job="checkout-api", status=~"5.."}[6h]))
/ sum(increase(http_requests_total{job="checkout-api"}[6h]))
) / 0.001
Essa translação muda o papel das métricas no time: deixam de ser um painel decorativo e passam a regular decisões de priorização, como pausar entregas de features quando o orçamento de erro se esgota. Times que adotam esse ciclo relatam menos discussões subjetivas sobre qualidade, porque o número define o limite.
RED e USE
RED e USE são dois métodos de cobertura que garantem que nada relevante deixe de ser instrumentado. RED se aplica a serviços que atendem requisições e pede três métricas por endpoint: Rate, taxa de requisições por segundo; Errors, proporção de falhas; e Duration, distribuição de latência. USE se aplica a recursos de infraestrutura e pede: Utilization, quanto do recurso está ocupado; Saturation, quanto trabalho está na fila esperando; e Errors, contagem de falhas internas. A combinação cobre a aplicação de fora para dentro: RED descreve a experiência de quem consome o serviço, USE descreve a saúde dos recursos que o sustentam. Uma estratégia madura adota RED como padrão obrigatório em bibliotecas de instrumentação internas e USE como checklist de saúde de nós, bancos e filas.
Erros comuns
Alguns deslizes aparecem repetidamente em ambientes reais e têm consequência direta em custo e confiabilidade.
- Labels de alta cardinalidade, como IDs de requisição em métricas, causam explosão de séries e podem derrubar o servidor Prometheus ou inflar a fatura mensal do backend gerenciado.
- Alertar sobre o valor absoluto de um counter em vez de sua taxa, o que dispara alarmes falsos toda vez que o contador reinicia.
- Usar média de latência como principal indicador, escondendo os outliers que afetam de verdade a experiência dos usuários no p99.
- Instrumentar sem padronização de nomes e unidades, gerando métricas como
http_timeem milissegundos em um serviço e em segundos em outro. - Coletar tudo "por precaução", sem uso declarado para painel ou alerta, o que aumenta custo de armazenamento e destrói a legibilidade dos dados.
Boas práticas
O conjunto de práticas abaixo consolida o que separa monitoramento maduro de instrumentação acidental.
- Padronize nomes de métricas, unidades e labels em uma biblioteca interna de instrumentação, aplicando RED por padrão em todos os serviços.
- Defina buckets de histograma com base no p99 atual do serviço, revisitando após mudanças arquiteturais significativas.
- Prefira métricas de negócio, como pedidos concluídos por minuto, pois elas conectam a saúde técnica ao impacto comercial e funcionam como alerta de sintoma.
- Estabeleça um contrato de cardinalidade: qualquer label nova em produção precisa de revisão, com limite documentado de séries por serviço.
- Mantenha a retenção diferenciada, com dados brutos de alta resolução por poucas semanas e agregados de baixa resolução por anos para análise de tendência.