Monitorado no papel
Os produtos tinham Prometheus, Grafana e regras de alerta. Em qualquer checklist, estariam marcados como monitorados. O que me fez desconfiar foi uma API pública que ficou dez minutos fora do ar e quem percebeu foi um monitor externo, e não o nosso.
Resolvi seguir o caminho completo de um alerta, da métrica até uma pessoa recebendo a mensagem. Em vários clusters, a rota raiz do Alertmanager apontava para um receptor nulo: o alerta era avaliado e descartado. Num deles, 36 alertas ativos iam para o vazio. Um roteador de mensagens descartava em silêncio tudo de um produto porque o prefixo do nome tinha um ponto, e um canal ficou 113 dias vazio sem ninguém notar. Além disso, as regras eram quase todas de saturação, como CPU, disco e conexões. Um banco, uma fila ou um cache podia cair sem abrir incidente nenhum.
Medir o que o cliente usa
Comecei pelo que o cliente sente. Implantei o Blackbox Exporter para sondar a API pública a cada 30 segundos, com alerta crítico depois de dois minutos fora e rota direta para o NOC. Os manifestos ficaram versionados e o token do webhook em Secret, fora do Git.
Num produto em que o serviço crítico é a conexão das instâncias com o canal de mensagens, não existia métrica pronta. Criei o sinal a partir dos logs: um pipeline no Grafana Alloy que coleta só os eventos de conexão e desconexão, descartando cerca de 99% do volume na origem, e uma regra que detecta desconexão em massa.
Regras de queda, com cuidado
Escrevi regras de indisponibilidade para PostgreSQL, Redis, Dragonfly, RabbitMQ, Elasticsearch, MongoDB e Kafka nos diferentes produtos, configuradas para que a métrica sumir também conte como queda. Antes de ligar qualquer uma, medi a cobertura de 24 horas de cada sinal e as oscilações dos cinco dias anteriores, para que as regras novas não virassem ruído.
Numa delas, a conta não fechava. O alerta de broker do Kafka esperava três brokers fora, mas o cluster tinha cinco e um tópico interno com fator de replicação 1. Um único broker fora já era incidente. Corrigi o limiar e versionei as regras no Git do produto.
Provar que chega
Reescrevi o roteamento do Alertmanager com destinos separados para o NOC, o canal do produto e o chat do time, com os alertas críticos indo para o NOC e o ruído conhecido contido de propósito. Antes de aplicar, testei a matriz de roteamento com o amtool em 12 casos e, depois, conferi o log do operator.
No caminho, corrigi detalhes que matavam a entrega sem erro nenhum: o prefixo com ponto, um agrupamento que deixava o nome do alerta vazio para o roteador e uma rota que exigia um label com um espaço no final.
A prova final foi com alertas sintéticos: 38 disparos em quatro produtos, 38 entregues no chat e no canal do produto e a contagem batendo um a um no NOC. Na auditoria seguinte, ainda encontrei uma regressão: um webhook que eu tinha validado dias antes tinha deixado de existir no gateway do NOC. Ficou documentado e corrigido.
Por fim, eliminei um falso positivo recorrente (uma regra que, sem dados, mantinha o último estado e ficava travada em disparo depois que o problema já tinha passado) e padronizei o nome de todas as regras com o prefixo do produto em quatro clusters, por script, preservando os labels de roteamento.
O que mudou
A queda de qualquer banco, fila ou cache principal passou a abrir incidente, o que antes não acontecia em vários produtos. Os alertas que eram descartados passaram a chegar a três destinos, com a entrega comprovada por teste. A API pública ganhou o próprio monitoramento de disponibilidade.
O que eu levo disso
Um alerta só existe quando alguém o recebe. Criar a regra é a parte fácil; o monitoramento é o caminho inteiro até uma pessoa, testado. Por isso nenhuma mudança de roteamento minha foi validada com "a configuração parece certa".
E regra de saturação não substitui regra de queda. Um banco a 50% de CPU está bem. Um banco que sumiu também não está saturado.