Pular para o conteúdo

PromQL

observabilidade
Expressão O que faz
http_requests_total Todas as séries da métrica
http_requests_total{job="loja"} Igual
http_requests_total{job!="loja"} Diferente
http_requests_total{status=~"5.."} Regex (ancorado automaticamente)
http_requests_total{status!~"2.."} Regex negada
http_requests_total{job="loja", route="/checkout"} Vários matchers (E lógico)
http_requests_total[5m] Intervalo (range vector)
http_requests_total offset 1w Desloca no tempo
http_requests_total @ 1725465600 Avalia em um instante fixo

Regex em PromQL é ancorado: status=~"5.." equivale a ^5..$.

Tipo Como ler
Counter Só cresce; use rate()/increase(), nunca o valor bruto
Gauge Sobe e desce; o valor bruto faz sentido
Histogram _bucket, _sum, _count; permite percentil agregável
Summary Quantis calculados no cliente; não agregáveis entre instâncias
Função Uso
rate(x[5m]) Taxa por segundo, média na janela. O padrão para alerta e painel
irate(x[5m]) Taxa dos dois últimos pontos. Só para gráfico de curta duração
increase(x[1h]) Aumento total na janela
delta(gauge[5m]) Diferença de um gauge
deriv(gauge[10m]) Derivada por segundo (tendência)
predict_linear(gauge[6h], 4*3600) Extrapola: “vai zerar em 4h?”
resets(x[1h]) Quantas vezes o counter reiniciou

A janela precisa conter pelo menos quatro amostras: com scrape de 30 s, use [2m] ou mais.

Expressão O que faz
sum(rate(x[5m])) Soma tudo
sum by (route) (rate(x[5m])) Soma mantendo a rota
sum without (instance) (rate(x[5m])) Soma descartando a instância
avg, min, max, count, stddev Outras agregações
topk(5, ...) / bottomk(5, ...) Maiores / menores
count_values("versao", build_info) Conta por valor de label
group by (job) (up) Séries distintas, valor 1

Sempre agregue depois da taxa: sum(rate(x[5m])) está certo; rate(sum(x)[5m:]) mente quando um alvo reinicia.

# p95 agregado por rota
histogram_quantile(0.95,
sum by (le, route) (rate(http_request_duration_seconds_bucket[5m])))
# latência média (quando faz sentido)
rate(http_request_duration_seconds_sum[5m])
/ rate(http_request_duration_seconds_count[5m])
# proporção abaixo de 300 ms — melhor que percentil para SLO
sum(rate(http_request_duration_seconds_bucket{le="0.3"}[5m]))
/ sum(rate(http_request_duration_seconds_count[5m]))

Ao agregar histogram, mantenha o label le no by, ou o quantil sai errado.

Expressão O que faz
a / b, a - b, a * 2 Aritmética entre séries com labels iguais
a > 0.05 Filtra (mantém séries que satisfazem)
a > bool 0.05 Devolve 0 ou 1
a and b / a or b / a unless b Conjunto
a / on(job) group_left b Junção com labels parciais
a * on(pod) group_left(versao) info Traz labels de uma métrica de metadados
Função Uso
absent(up{job="loja"}) 1 se a série não existe — alerta de ausência
absent_over_time(x[10m]) Ausência sustentada
clamp_max(x, 100) / clamp_min(x, 0) Limita valores
changes(x[1h]) Quantas vezes o valor mudou
avg_over_time(x[1h]) / max_over_time(x[1d]) Agregação temporal
quantile_over_time(0.95, x[7d]) Percentil ao longo do tempo
time() Timestamp atual (segundos)
label_replace(x, "novo", "$1", "antigo", "(.*)") Cria label derivado
# taxa de erro por rota
sum by (route) (rate(http_requests_total{status=~"5.."}[5m]))
/ sum by (route) (rate(http_requests_total[5m]))
# disponibilidade nos últimos 30 dias
sum(increase(http_requests_total{status!~"5.."}[30d]))
/ sum(increase(http_requests_total[30d]))
# CPU por Pod contra o request declarado
sum by (pod) (rate(container_cpu_usage_seconds_total{namespace="loja"}[5m]))
/ sum by (pod) (kube_pod_container_resource_requests{resource="cpu", namespace="loja"})
# memória contra o limite (candidatos a OOM)
sum by (pod) (container_memory_working_set_bytes{namespace="loja"})
/ sum by (pod) (kube_pod_container_resource_limits{resource="memory", namespace="loja"}) > 0.9
# throttling de CPU
sum by (pod) (rate(container_cpu_cfs_throttled_seconds_total[5m])) > 0
# reinícios na última hora
increase(kube_pod_container_status_restarts_total[1h]) > 3
# disco enche em 4 horas?
predict_linear(node_filesystem_avail_bytes{mountpoint="/"}[6h], 4*3600) < 0
# alvos fora do ar
up == 0
# cardinalidade: séries por métrica (via API)
# curl -s localhost:9090/api/v1/status/tsdb | jq '.data.seriesCountByMetricName[:10]'
  • rate() em gauge dá resultado sem sentido; use deriv ou delta.
  • Série que some (Pod removido) não vira zero: ela desaparece. Use absent() ou or vector(0).
  • Divisão por zero produz +Inf ou série ausente; proteja com > 0 no denominador.
  • irate em alerta oscila e dispara sozinho.
  • Janela menor que 4× o scrape_interval gera buracos no gráfico.
  • Label de alta cardinalidade (id, e-mail, URL completa) derruba o Prometheus.
  • Consulta cara em alerta falha justamente durante o incidente: use recording rules.