🧠FFVAcademy
📉

Métricas RED e USE: os frameworks que cobrem 90% dos casos

14 min de leitura·+70 XP
Pré-requisitos (0/1)0%

Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.

"O que eu devo monitorar?" é a pergunta que todo dev faz na primeira vez que sobe algo pra produção. Resposta ruim: "tudo que parecer útil". Resposta boa: dois frameworks complementares que cobrem 90% dos casos — RED pra serviços, USE pra recursos. Combinados com os Four Golden Signals do Google, você tem um checklist testado em escala massiva.

Este módulo mostra os 3 frameworks, quando aplicar cada um, por que percentiles matam média, e armadilhas clássicas (histogramas com buckets errados, averaging p99s, labels explosivos).

RED Method: para serviços (request-driven)

Proposto por Tom Wilkie (Weaveworks, depois Grafana Labs) em 2016. Simplifica drasticamente o "o que medir em cada serviço":

MétricaO que éPergunta que responde
RateRequisições por segundo (throughput)Quanto tráfego o serviço recebe?
ErrorsTaxa de erros (req com falha / total)Quantas requisições falham?
DurationDistribuição de latência (percentiles)Quão rápido o serviço responde?
Cada endpoint/serviço:

 Rate     ───►  http_requests_total{service, endpoint, status} (Counter)
 Errors   ───►  derivado do Rate: filtro por status 5xx / total
 Duration ───►  http_request_duration_seconds{service, endpoint} (Histogram)

Dashboard por serviço:
  ┌──────────────────────────────────────────┐
  │ Rate (req/s):   ████▇▆▅▅▄▃▃▃▃      200    │
  │ Error rate:     ──────────            0.2% │
  │ Duration p50:   ──────────            45ms │
  │ Duration p95:   ▅───────              180ms│
  │ Duration p99:   ▇▅──                  320ms│
  └──────────────────────────────────────────┘
python
# app.py — instrumentação RED com prometheus_client
from prometheus_client import Counter, Histogram
import time

REQUESTS = Counter(
    "http_requests_total",
    "Total de requisições HTTP",
    ["method", "endpoint", "status"],   # cardinalidade controlada
)

DURATION = Histogram(
    "http_request_duration_seconds",
    "Latência de requisições HTTP",
    ["method", "endpoint"],
    buckets=(0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10),
)

async def middleware(request, call_next):
    start = time.time()
    status = "500"
    try:
        response = await call_next(request)
        status = str(response.status_code)
        return response
    finally:
        elapsed = time.time() - start
        REQUESTS.labels(request.method, request.url.path, status).inc()
        DURATION.labels(request.method, request.url.path).observe(elapsed)
promql
# Queries PromQL que derivam as 3 métricas RED

# Rate (req/s nos últimos 5min)
sum by (endpoint) (rate(http_requests_total[5m]))

# Errors (% erros 5xx)
sum by (endpoint) (rate(http_requests_total{status=~"5.."}[5m]))
  / sum by (endpoint) (rate(http_requests_total[5m]))

# Duration p99
histogram_quantile(0.99,
  sum by (endpoint, le) (rate(http_request_duration_seconds_bucket[5m]))
)

USE Method: para recursos (resource-driven)

Proposto por Brendan Gregg (Netflix, performance guru) em 2012. Para cada recurso do sistema (CPU, memória, disco, NIC, connection pool, thread pool, fila):

MétricaO que éIndica
Utilization% do tempo que o recurso está ocupadoQuão "cheio" está — alto pode ser normal se não tem fila
SaturationQuantidade de trabalho em fila / não atendido aindaDemanda excede capacidade — causa latência
ErrorsEventos de erro específicos do recursoHardware/driver falhando

Exemplos:

RecursoUtilizationSaturationErrors
CPU% CPU user+systemRun-queue length, load averageThrottles, machine checks
Memória% RAM usadaSwap usage, kswapd busyECC errors, OOM kills
Disco% busy (iostat util)IO queue depth, avg waitBad sectors, retries
Rede (NIC)% bandwidth usadaTX/RX queue dropped packetsCRC errors, collisions
Connection pool (DB)% connections activeWaiters on acquireTimeouts acquiring
Thread pool% threads busyQueue size de tasks pendentesTask rejections
💡
Gotcha comum — Saturation é mais útil que Utilization: CPU a 95% é normal num batch job. Mas CPU a 80% com load average 40 em máquina de 8 cores (saturação) = sistema em colapso. Utilization alto sem saturation = eficiência. Utilization moderado com saturation alta = gargalo.

Four Golden Signals (Google SRE Book)

Definidos no livro Site Reliability Engineering (Google, 2016, cap. 6). É o superset que sintetiza RED e USE aplicado a serviços:

SignalDescriçãoRED/USE equivalente
LatencyTempo de resposta — separe success vs failureDuration do RED
TrafficDemanda — req/s, tx/s, user-session countRate do RED
ErrorsTaxa de falhas — explícitas E implícitas (latency alta)Errors do RED
Saturation"Cheio" do sistema — recurso mais saturado limita performanceSaturation do USE
💡
Prática Google SRE: todo serviço deve ter dashboard com os 4 signals visíveis em uma tela. Alertas baseados em SLOs derivados deles. Esse é o padrão de fato pra "production-grade service".

Quando usar RED vs USE vs Golden Signals

ContextoFramework principal
Serviço HTTP/gRPC/fila-requestRED
Recurso de infra (CPU, disco, pool)USE
Serviço + visão de capacidadeGolden Signals (RED + Saturation)
Banco de dadosUSE + métricas específicas (slow queries, locks, replication lag)
Fila/broker (Kafka, SQS, RabbitMQ)USE (queue depth, consumer lag) + Traffic
Batch jobsRuntime, success rate, throughput de items
Mobile/web clientRUM — Largest Contentful Paint, CLS, FID, INP

Na prática, combine. Um dashboard típico de serviço tem:

  • Topo (RED/Golden): Rate, Error rate, Latency p50/p95/p99
  • Meio (Saturation): CPU, memory, connection pool, thread pool, queue depth
  • Fundo (dependencies): DB query p99, cache hit ratio, external API error rate
  • Lateral (deploy/release): build version, feature flag state

Armadilhas clássicas

🚨
#1: Reportar média ao invés de percentile. Média esconde outliers. Sempre use percentis (p50, p95, p99, p99.9). Não tire média de p99s entre réplicas — é matematicamente incorreto. Use histogramas agregáveis (Prometheus) + histogram_quantile.
🚨
#2: Buckets de histograma errados. Prometheus histogram precisa de buckets pré-definidos. Se seu p99 real é 2s mas o maior bucket é 1s, p99 reportado vira "+Inf" ou ruim. Escolha buckets que cubram 10x o p99 esperado. Ex:(0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10).
🚨
#3: Label explosion. {user_id}, {trace_id}, {session} em métricas matam Prometheus. Use events/logs pra essas dimensões, não métricas.
🚨
#4: Errors não inclui "latency igual a timeout". Request que durou 30s e timed out no cliente conta como error, mesmo que servidor respondeu 200. Instrumente no cliente também, não só no servidor.
🚨
#5: Esquecer saturation. Sem saturation, você só vê o problema depois que virou latency/error. Saturation antecipa.

Exemplo: aplicando tudo numa API real

yaml
# dashboard-checkout-api.yaml — estrutura de um dashboard production-grade

panels:
  - title: "Traffic (RED:Rate)"
    query: |
      sum by (endpoint) (rate(http_requests_total{service="checkout"}[5m]))

  - title: "Error Rate (RED:Errors, Golden:Errors)"
    query: |
      sum(rate(http_requests_total{service="checkout",status=~"5.."}[5m]))
      / sum(rate(http_requests_total{service="checkout"}[5m]))
    alert: "> 1% por 5min"

  - title: "Latency p50/p95/p99 (RED:Duration, Golden:Latency)"
    queries:
      - histogram_quantile(0.50, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
      - histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
      - histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

  - title: "CPU Saturation (USE)"
    query: |
      sum by (pod) (rate(container_cpu_usage_seconds_total{pod=~"checkout-.*"}[5m]))
      / sum by (pod) (kube_pod_container_resource_limits{resource="cpu",pod=~"checkout-.*"})
    alert: "> 85% por 10min"

  - title: "DB Connection Pool Saturation (USE)"
    query: |
      pool_connections_active{pool="checkout_db"}
      / pool_connections_max{pool="checkout_db"}
    alert: "> 90%"

  - title: "DB Query p99 (RED aplicado ao DB)"
    query: |
      histogram_quantile(0.99,
        sum by (query_type, le) (rate(db_query_duration_seconds_bucket[5m]))
      )
    alert: "> 500ms por 10min"

  - title: "Queue Saturation (SQS consumer lag)"
    query: aws_sqs_approximate_number_of_messages_visible{queue="checkout-events"}
    alert: "> 10000 por 15min"

Decisões reais

📋 API REST nova, quero dashboard mínimo útil

RED + 2-3 métricas de Saturation (CPU, pool conexão)

RED te dá 'o serviço tá bem?'. Saturation te antecipa problemas ('CPU em 90%, logo vai degradar'). Com 5 painéis, você já está 90% lá. Adicione mais conforme necessidade — evite dashboard com 50 painéis que ninguém lê.

Alt: Golden Signals completoEssencialmente o mesmo — use como checklist.

📋 Serviço de batch processing (worker consumindo fila)

Saturation-heavy: queue depth + throughput de items + error rate

Workers não têm 'latência por request' tradicional — são throughput-oriented. Métricas chave: queue depth (consumer lag), items processed/s, error rate, duração média por item (se variável). RED clássico não se aplica bem.

Alt: RED tradicionalMeh — o "request" do worker é ambíguo.

📋 Monitorar Postgres em produção

USE no nível de recursos + métricas específicas (slow queries, locks, replication lag, WAL size)

Postgres tem idiossincrasias que genéricos não cobrem: VACUUM lag, bloat, replication slot size, xid wrap. Use postgres_exporter + queries customizadas. USE cobre CPU/disco/memória mas faltam as métricas de DB que matam.

Alt: Só USE genéricoPerde alertas específicos de DB — risco.

Perguntas típicas (Q&A)

Quantas métricas por serviço são "muitas"?

Regra prática: ~20-50 métricas distintas por serviço. Inclui RED, saturation de recursos, métricas de negócio (orders_created_total, revenue_cents). Se tem 200 métricas, provavelmente há duplicação ou lixo.

Dashboards por serviço ou por time?

Ambos. Service dashboards (detalhe, on-call do serviço). Team/squad dashboards (visão macro dos serviços que o time dono). Exec dashboards(uptime, revenue impact). Camadas servem audiências diferentes.

Devo alertar em todas as métricas?

Não. Alerte em consequências de usuário (latency/error afetando SLO) e leading indicators (saturation alto) que te dariam tempo de agir. Alertar em cada spike de CPU = alert fatigue = alerta ignorado quando realmente importa.

Como monitorar serviço async/event-driven?

Adapte RED: "Rate" = events processed/s, "Errors" = events falhados, "Duration" = tempo end-to-end (produção → consumo). Adicione "age" do evento mais antigo não processado (alerta se passa de threshold).

Métricas de negócio no mesmo lugar?

Sim! Orders/s, signup rate, conversion% são as MAIS importantes. Quando elas caem, algo está errado mesmo que RED/USE estejam verdes. Misture técnicas com negócio nos dashboards principais.

Take-aways:
  • RED (Rate, Errors, Duration): o mínimo pra todo serviço request-driven.
  • USE (Utilization, Saturation, Errors): o mínimo pra todo recurso.
  • Four Golden Signals (Google SRE): Latency + Traffic + Errors + Saturation. Superset operacional.
  • Sempre percentiles (p50, p95, p99), nunca média. Histogramas agregáveis com histogram_quantile.
  • Saturation antecipa problemas que viram latência/error. Monitorar o "quão cheio" o recurso.
  • Cuidado com label explosion em métricas — use events/traces pra contexto rico.
  • Complemente frameworks com métricas de negócio (orders/s, revenue, conversion).

Próximo módulo: o SDK unificado pra instrumentar tudo — OpenTelemetry end-to-end.

🧩

Quiz rápido

4 perguntas · Acerte tudo e ganhe o badge 🎯 Gabarito

Continue lendo