Pular para o conteúdo

Grafana: painéis que alguém usa

Intermediário16 min de leituraobservabilidade

Quase todo time tem dezenas de dashboards e usa dois. O resto foi criado no incidente, respondeu àquela pergunta e virou paisagem. Um painel bom não é o que mostra mais dados — é o que responde uma pergunta em segundos, para alguém com sono, às três da manhã.

Dois roteiros cobrem a maior parte dos casos:

  • RED, para serviços que atendem requisições: Rate (requisições por segundo), Errors (proporção de falha) e Duration (latência, em percentis).
  • USE, para recursos como nó, disco e fila: Utilization, Saturation e Errors.

Serviço quebra do jeito RED; infraestrutura quebra do jeito USE. Um dashboard de serviço começa com esses três painéis, lado a lado, e nada mais acima da dobra.

# Rate
sum by (route) (rate(http_requests_total{job="$job"}[$__rate_interval]))
# Errors — proporção, não contagem absoluta
sum(rate(http_requests_total{job="$job", status=~"5.."}[$__rate_interval]))
/ sum(rate(http_requests_total{job="$job"}[$__rate_interval]))
# Duration
histogram_quantile(0.95, sum by (le) (
rate(http_request_duration_seconds_bucket{job="$job"}[$__rate_interval])))

Use $__rate_interval em vez de [5m] fixo: o Grafana ajusta a janela ao zoom e você para de ver gráfico vazio quando olha a última hora.

Antes de adicionar um gráfico, escreva a pergunta que ele responde. Se não couber em uma frase, o painel não vai ser lido. Na prática:

  • Título é a pergunta (“Erros 5xx por rota”), não o nome da métrica.
  • Unidade e limiar configurados — número sem unidade não é resposta.
  • Percentil, nunca média: média de latência esconde exatamente quem está sofrendo.
  • Proporção para erro; contagem absoluta sobe junto com o tráfego e engana.
  • No máximo cinco a sete painéis na primeira tela; o resto vai para linhas colapsadas.

Dashboard por serviço multiplica manutenção. Uma variável resolve.

Nome: job Tipo: Query Consulta: label_values(http_requests_total, job)
Nome: pod Tipo: Query Consulta: label_values(http_requests_total{job="$job"}, pod)
Multi-value: sim Include All: sim

Com multi-valor, use =~"$pod" no seletor (regex), não ="$pod" — com = a consulta quebra assim que alguém escolhe dois valores.

Metade das perguntas de incidente é “mudou alguma coisa?”. Anote deploys na linha do tempo e a resposta fica visível no gráfico.

Janela do terminal
curl -sX POST http://grafana/api/annotations \
-H "Authorization: Bearer $GRAFANA_TOKEN" -H 'Content-Type: application/json' \
-d '{"tags":["deploy","loja"],"text":"loja 1.8.3","time":'"$(date +%s000)"'}'

Ligue também os pilares: com exemplars no histogram, um clique no ponto de latência abre o trace daquela requisição; com o trace_id no log, o painel de logs filtra sozinho. Sem essa ligação, cada investigação recomeça do zero em três abas.

Painel editado na interface é mudança sem revisão que ninguém consegue reproduzir depois de um restore. Exporte o JSON, versione no repositório e provisione:

/etc/grafana/provisioning/dashboards/loja.yaml
apiVersion: 1
providers:
- name: loja
folder: Serviços
type: file
allowUiUpdates: false # a interface deixa de ser a fonte da verdade
options: { path: /var/lib/grafana/dashboards }

Com allowUiUpdates: false, exploração continua possível (salvando cópia), mas o painel oficial só muda por pull request.

Próximo passo: o gráfico mostrou o “quando”; o log diz “o quê”. Continue em Logs estruturados e Loki.