Pular para o conteúdo

Alertar por consumo de error budget

Avançado16 min de leituraobservabilidade

Ao final deste guia, o alerta do seu serviço dispara quando o usuário está sendo afetado numa velocidade que importa — e para de disparar por picos irrelevantes de madrugada.

taxa_de_erro > 5% por 5 minutos erra dos dois lados. De madrugada, com 20 requisições no período, uma falha vira 5% e acorda alguém à toa. No pico, 2% de erro sustentado por três horas passa despercebido — e consome mais orçamento que qualquer pico curto.

O burn rate resolve porque mede velocidade de consumo do orçamento de erro, e não um número solto.

O SLI precisa medir o que o usuário sente. Para uma API, a proporção de requisições bem-sucedidas:

sum(rate(http_requests_total{service="loja", status!~"5.."}[5m]))
/ sum(rate(http_requests_total{service="loja"}[5m]))

Com SLO de 99,9% mensal, o orçamento de erro é 0,1% — cerca de 43 minutos de falha total por mês. Esse 0,001 é o denominador de tudo que vem a seguir.

Exclua do SLI o que não é responsabilidade do serviço (erros 4xx de cliente, por exemplo) — mas documente a exclusão, porque ela é uma decisão discutível.

Alerta não pode depender de consulta cara: no incidente, o Prometheus está sob pressão.

groups:
- name: slo-loja-gravacao
interval: 30s
rules:
- record: slo:erro:ratio_rate5m
expr: |
sum(rate(http_requests_total{service="loja", status=~"5.."}[5m]))
/ sum(rate(http_requests_total{service="loja"}[5m]))
- record: slo:erro:ratio_rate1h
expr: |
sum(rate(http_requests_total{service="loja", status=~"5.."}[1h]))
/ sum(rate(http_requests_total{service="loja"}[1h]))
- record: slo:erro:ratio_rate30m
expr: |
sum(rate(http_requests_total{service="loja", status=~"5.."}[30m]))
/ sum(rate(http_requests_total{service="loja"}[30m]))
- record: slo:erro:ratio_rate6h
expr: |
sum(rate(http_requests_total{service="loja", status=~"5.."}[6h]))
/ sum(rate(http_requests_total{service="loja"}[6h]))
- record: slo:erro:ratio_rate3d
expr: |
sum(rate(http_requests_total{service="loja", status=~"5.."}[3d]))
/ sum(rate(http_requests_total{service="loja"}[3d]))

Burn rate é quantas vezes mais rápido que o previsto você está gastando o orçamento. Taxa 1 consome o mês inteiro em um mês; taxa 14,4 consome 2% do orçamento em uma hora.

Gravidade Burn rate Janelas Consome Destino
Rápida 14,4× 1h e 5m 2% em 1h página
Média 6h e 30m 5% em 6h página (horário comercial)
Lenta 3d e 6h 10% em 3d ticket

O par de janelas é o truque que evita ruído: a janela longa confirma o problema, a curta garante que ele ainda está acontecendo — sem ela, o alerta continua tocando depois de resolvido.

groups:
- name: slo-loja-alertas
rules:
- alert: LojaBurnRateRapida
expr: |
(slo:erro:ratio_rate1h > 14.4 * 0.001)
and (slo:erro:ratio_rate5m > 14.4 * 0.001)
for: 2m
labels: { severity: page, service: loja }
annotations:
summary: "Loja consumindo orçamento de erro 14x acima do previsto"
description: "Erro em 1h: {{ $value | humanizePercentage }}. SLO 99,9%."
runbook: "https://portal.exemplo.com/guias/kubernetes/rollback-deploy/"
- alert: LojaBurnRateLenta
expr: |
(slo:erro:ratio_rate6h > 6 * 0.001)
and (slo:erro:ratio_rate30m > 6 * 0.001)
for: 15m
labels: { severity: ticket, service: loja }
annotations:
summary: "Degradação persistente no serviço loja"

Substitua 0.001 pelo orçamento do seu SLO (99,5% → 0.005; 99,95% → 0.0005).

Toda regra que pagina precisa de um runbook na anotação. Alerta sem runbook não está pronto.

Esta é a etapa que dá confiança — e a mais pulada.

Janela do terminal
promtool check rules regras-slo.yaml
promtool test rules testes-slo.yaml # casos de teste com séries sintéticas

Depois, olhe para trás: pegue dois ou três incidentes reais dos últimos meses e verifique na interface do Prometheus se a expressão teria disparado, e quando. Faça o mesmo com um período tranquilo, para confirmar que ela não dispararia.

# quanto do orçamento mensal já foi consumido — bom painel ao lado do alerta
1 - (
sum(increase(http_requests_total{service="loja", status!~"5.."}[30d]))
/ sum(increase(http_requests_total{service="loja"}[30d]))
) / 0.001
route:
group_by: [alertname, service]
routes:
- matchers: [severity="page"]
receiver: plantao
- matchers: [severity="ticket"]
receiver: fila-do-time
Sintoma Causa provável
Nunca dispara Multiplicador ou orçamento errado; teste com promtool
Dispara sem impacto 4xx entrando no SLI, ou serviço com tráfego baixo demais
Continua tocando após resolver Faltou a janela curta no and
$value estranho na notificação A expressão devolve proporção, não porcentagem
Alerta some no incidente Consulta cara sem recording rule

Serviço com pouco tráfego é o caso difícil: com dezenas de requisições por hora, qualquer proporção é ruidosa. Ali, alerte por contagem absoluta de erros ou por disponibilidade medida com sonda sintética.

  • SLI medindo sintoma do usuário, com exclusões documentadas.
  • SLO acordado com produto e escrito.
  • Recording rules para todas as janelas usadas.
  • Duas janelas por alerta, rápida e lenta separadas por severidade.
  • Runbook na anotação de toda regra que pagina.
  • Regras testadas com promtool e conferidas contra incidentes passados.
  • Painel de orçamento consumido publicado.