Sumário
- Por que o Alertmanager não consegue fazer seu telefone tocar
- O que você vai precisar
- Passo 1 — Crie um canal que liga para você
- Passo 2 — Adicione um receiver webhook
- Passo 3 — Entenda o que realmente chega
- Passo 4 — Envie as recuperações como push silencioso
- Passo 5 — Roteie por severidade, não tudo
- Passo 6 — A armadilha do Watchdog
- Ajustes para não virar o menino que gritava lobo
- Tocar apenas fora do horário comercial
- Lidando com o problema do commonLabels vazio
- Mantendo o payload pequeno
- Compartilhando o alerta com sua equipe
- O que esta configuração não te dá
- Solução de problemas
- Perguntas frequentes
- O Prometheus Alertmanager consegue fazer uma ligação nativamente?
- A ligação passa pelo Não Perturbe?
- Funciona com o Alertmanager atrás de um firewall ou dentro do Kubernetes?
- Como paro de ser ligado quando um alerta se resolve?
- Por que meu telefone toca a cada quatro horas pelo mesmo alerta?
- Várias pessoas podem ser chamadas pelo mesmo alerta?
- Devo filtrar severidade no Alertmanager ou nas condições do Echobell?
- Fechamento
- Relacionados
O Alertmanager não tem receiver de voz. Para receber uma ligação quando um alerta do Prometheus dispara, adicione um receiver webhook_configs apontando para um canal do Echobell cujo tipo de assinatura seja Chamada. Este guia cobre o YAML exato, a condição que impede alertas resolvidos de ligarem para você, o roteamento por severidade e o alerta Watchdog que, se ignorado, fará seu telefone tocar a cada quatro horas para sempre.
O Prometheus é a stack de métricas padrão de quase toda infraestrutura construída na última década, e o Alertmanager é genuinamente bom nas partes difíceis: deduplicar alertas, agrupá-los, silenciá-los durante manutenções e inibir o ruído a jusante quando uma dependência a montante cai.
O que ele não vai fazer é acordar alguém.
Por que o Alertmanager não consegue fazer seu telefone tocar
O Alertmanager traz receivers para e-mail, Slack, PagerDuty, OpsGenie, Discord, Telegram, Pushover, Webex, MS Teams e mais uma dúzia. Todos entregam uma mensagem, e mensagens estão sujeitas à chave de silencioso, ao Não Perturbe e aos modos de Foco do iOS. Às 03:00, isso significa que o alerta chega e nada acontece.
Não existe voice_configs. As opções em que as pessoas costumam parar:
- PagerDuty / OpsGenie / Splunk On-Call — eles realmente ligam, e são plataformas completas de gestão de incidentes, com preço por assento à altura. A resposta certa se você precisa de escalas e árvores de escalonamento; pesada demais se você só quer que um telefone toque. (O OpsGenie, aliás, está sendo descontinuado, e é por isso que tantas equipes estão reavaliando essa camada agora.)
- Pontes de SMS como o Sachet — você opera mais um serviço, paga um gateway por mensagem, e o SMS continua chegando como mensagem. No iOS, um texto não rompe o modo Foco a menos que o remetente esteja na sua lista de permitidos.
- Cola sobre o Twilio — escrever um pequeno receiver de webhooks, comprar um número, pagar por chamada, e pronto: você agora é dono de um pedaço de infraestrutura de produção cuja única função é fazer um telefone tocar.
O receiver webhook genérico é a saída. Ele faz POST de um JSON documentado em qualquer URL, e é só disso que você precisa.
O que você vai precisar
- Um Prometheus + Alertmanager em execução e acesso para editar o
alertmanager.yml - Echobell instalado (App Store / Google Play)
- Dez minutos
Este guia foi escrito com o Alertmanager 0.31. O payload do webhook está em version: "4" há anos, então as versões 0.2x se comportam de forma idêntica.
Seu Alertmanager precisa de HTTPS de saída para hook.echobell.one. Ele não precisa ser alcançável pela internet, então um Alertmanager dentro de um cluster, de uma VPC ou de um homelab funciona perfeitamente.
Passo 1 — Crie um canal que liga para você
No Echobell, crie um canal chamado algo como Prometheus Critical. Defina o tipo de notificação da assinatura como Chamada. É essa a configuração que importa: alertas do tipo Chamada chegam como uma tela de chamada recebida e tocam através do modo Foco e do Não Perturbe do iOS, o que uma notificação push não faz.
Configure os templates para ler o payload do Alertmanager diretamente:
Title: 🔴 {{commonLabels.alertname}} on {{commonLabels.instance}}
Body: {{commonAnnotations.summary}}
{{commonAnnotations.description}}
E, nas Configurações avançadas, um template de link para que o registro da notificação salte direto para o gráfico:
{{alerts[0].generatorURL}}
Depois copie a URL do webhook do canal:
https://hook.echobell.one/t/<channel-token>
Trate essa URL como um segredo — qualquer pessoa com ela pode fazer seu telefone tocar.
Passo 2 — Adicione um receiver webhook
No alertmanager.yml:
route:
group_by: ["alertname", "cluster", "service"]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: echobell-critical
receivers:
- name: echobell-critical
webhook_configs:
- url: "https://hook.echobell.one/t/<channel-token>"
send_resolved: false
Recarregue com curl -X POST http://localhost:9093/-/reload ou com SIGHUP.
Repare no send_resolved: false. O padrão de um receiver webhook é true, diferentemente da maioria dos outros receivers do Alertmanager — então omitir isso significa que seu telefone toca quando o serviço quebra e toca de novo quando ele se conserta sozinho. É essa segunda ligação que ensina as pessoas a ignorar a primeira. O passo 4 mostra como recuperar o aviso de recuperação sem o toque.
Passo 3 — Entenda o que realmente chega
O Alertmanager agrupa os alertas e então faz um POST por grupo:
{
"version": "4",
"groupKey": "{}:{alertname=\"HighErrorRate\"}",
"truncatedAlerts": 0,
"status": "firing",
"receiver": "echobell-critical",
"groupLabels": { "alertname": "HighErrorRate" },
"commonLabels": { "alertname": "HighErrorRate", "severity": "critical" },
"commonAnnotations": { "summary": "Error rate above 5% for 10m" },
"externalURL": "http://alertmanager.internal:9093",
"alerts": [
{
"status": "firing",
"labels": { "alertname": "HighErrorRate", "instance": "api-7d9f:8080" },
"annotations": { "summary": "Error rate above 5% for 10m" },
"startsAt": "2026-09-04T02:41:07.351Z",
"endsAt": "0001-01-01T00:00:00Z",
"generatorURL": "http://prometheus:9090/graph?g0.expr=...",
"fingerprint": "a1b2c3d4e5f60718"
}
]
}
O Echobell lê o corpo JSON como está, então todos esses campos ficam disponíveis em templates e condições. O acesso aninhado funciona nas duas sintaxes — {{commonLabels.severity}} ou {{alerts[0].labels["instance"]}}.
Duas propriedades desse payload comandam tudo o que vem a seguir:
O status de nível superior é firing se qualquer alerta do grupo estiver ativo. Ele só vira resolved quando todos os alertas do grupo se resolveram. Isso o torna um critério limpo para filtrar.
commonLabels contém apenas os rótulos compartilhados por todos os alertas do grupo. Essa é a surpresa mais comum. Se o group_by for amplo a ponto de um webhook carregar HighErrorRate de três instâncias diferentes, commonLabels.instance fica ausente e {{commonLabels.instance}} é renderizado como string vazia. Há uma seção mais abaixo sobre como lidar com isso.
Passo 4 — Envie as recuperações como push silencioso
Você ainda quer saber quando algo se recupera — só não quer ser ligado por causa disso. Adicione um segundo canal no Echobell chamado Prometheus Recovered, defina o tipo como Normal e use estes templates:
Title: ✅ {{commonLabels.alertname}} resolved
Body: {{commonAnnotations.summary}}
e, nas Configurações avançadas, esta condição:
status == "resolved"
Condições são expressões avaliadas antes de qualquer entrega. Se a expressão for falsa, o Echobell aceita a requisição e não envia nada.
Depois aponte o mesmo receiver para os dois canais — um receiver pode ter vários webhook_configs:
receivers:
- name: echobell-critical
webhook_configs:
# Faz o telefone tocar. Apenas quando disparando.
- url: "https://hook.echobell.one/t/<calling-channel-token>"
send_resolved: false
# Push silencioso. A condição do canal descarta a metade "firing".
- url: "https://hook.echobell.one/t/<recovery-channel-token>"
send_resolved: true
O canal de recuperação recebe payloads de firing e de resolved e descarta os primeiros. Resultado: a queda toca, a recuperação chega como um push que você lê de manhã.
Passo 5 — Roteie por severidade, não tudo
Uma rota catch-all que manda todo alerta para um canal de chamada é uma máquina de produzir ligações ignoradas. Divida por severidade no Alertmanager, que é onde a árvore de roteamento pertence:
route:
group_by: ["alertname", "cluster", "service"]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: echobell-warning
routes:
# O Watchdog nunca chega a um humano. Ver Passo 6.
- matchers:
- alertname = "Watchdog"
receiver: "null"
- matchers:
- severity = "critical"
receiver: echobell-critical
group_wait: 10s
repeat_interval: 1h
receivers:
- name: "null"
- name: echobell-critical
webhook_configs:
- url: "https://hook.echobell.one/t/<calling-channel-token>"
send_resolved: false
- name: echobell-warning
webhook_configs:
- url: "https://hook.echobell.one/t/<normal-channel-token>"
send_resolved: true
As rotas são avaliadas de cima para baixo e a primeira correspondência vence — continue é false por padrão. Então a ordem importa: a rota do Watchdog precisa ficar acima de qualquer coisa que a engoliria.
Se você preferir manter um canal só e filtrar do lado do Echobell, a condição equivalente é:
status == "firing" && commonLabels.severity == "critical"
Fazer isso no Alertmanager costuma ser melhor, porque ali severity também governa group_wait e repeat_interval. Fazer no Echobell é melhor quando você não consegue aprovar uma mudança de configuração hoje.
Passo 6 — A armadilha do Watchdog
Se você usa o kube-prometheus-stack, você tem um alerta chamado Watchdog cuja expressão é vector(1). Ele é projetado para disparar para sempre: existe para que um sistema externo perceba quando o próprio Prometheus parou. A configuração padrão o roteia para um receiver null.
Aponte uma rota catch-all para um canal de chamada sem excluí-lo e o Watchdog ligará para o seu telefone a cada repeat_interval, para sempre, começando imediatamente. Esse é o motivo número um pelo qual as pessoas concluem que alertas por telefone "não funcionam".
Mantenha a rota null do passo 5. Depois, opcionalmente, faça algo útil com ela: transforme o Watchdog em um verdadeiro dead man's switch.
- matchers:
- alertname = "Watchdog"
receiver: deadmansswitch
group_wait: 0s
group_interval: 1m
repeat_interval: 50s
receivers:
- name: deadmansswitch
webhook_configs:
- url: "https://hc-ping.com/<your-check-uuid>"
send_resolved: false
O Echobell não pode ser o dead man's switch em si — ele alerta quando uma requisição chega, não quando ela deixa de chegar. Então envie o ping do Watchdog para um serviço feito para detectar silêncio (Healthchecks.io, Cronitor, Dead Man's Snitch) e depois aponte o webhook de "check caiu" desse serviço para o seu canal de chamada no Echobell. Agora uma ligação significa "o monitoramento em si morreu", que é o alerta pelo qual você mais quer ser acordado e o que ninguém configura.
Ajustes para não virar o menino que gritava lobo
Três configurações do Alertmanager fazem a maior parte do trabalho, mais uma do Prometheus:
| Configuração | Onde | O que faz |
|---|---|---|
for: | Regra de alerta | Por quanto tempo a condição precisa se manter antes de disparar. Sua primeira linha de defesa contra um soluço de dois segundos. |
group_wait | Rota | Quanto esperar por mais alertas antes da primeira notificação. 30s por padrão; baixe para 10s no crítico. |
group_interval | Rota | Intervalo mínimo antes de notificar sobre alertas novos em um grupo existente. 5m por padrão. |
repeat_interval | Rota | De quanto em quanto tempo um alerta não resolvido volta a notificar. 4h por padrão — ou seja, uma queda noturna liga às 03:00 e de novo às 07:00. |
repeat_interval é o que vale pensar com calma. Quatro horas é muito tempo para deixar algo quebrado; vinte minutos é uma máquina para você acabar desativando o canal. Uma hora no crítico é um bom ponto de partida.
Se você quer que uma ligação não atendida seja tentada de novo imediatamente, em vez de esperar o próximo repeat_interval, ative Repetir chamada com falha nas configurações do app do Echobell.
Tocar apenas fora do horário comercial
Durante o expediente você provavelmente já está olhando para um painel. As variáveis de tempo de sistema do Echobell (todas em UTC) permitem que um canal se comporte de forma diferente por hora, sem uma segunda rota no Alertmanager:
status == "firing" && (hour >= 17 || hour < 9)
Isso liga para você só fora de 09:00–17:00 UTC. Aponte um segundo canal, do tipo Normal, para a faixa inversa, para os pushes diurnos:
status == "firing" && hour >= 9 && hour < 17
Adicione dayOfWeek >= 1 && dayOfWeek <= 5 para tratar o fim de semana também como fora do horário. Lembre-se de que tudo é calculado em UTC — compense para o seu fuso. Há um tratamento mais completo em notificações por janela de tempo com condições UTC.
Lidando com o problema do commonLabels vazio
Quando um grupo contém alertas de várias instâncias, commonLabels.instance desaparece e o título da sua notificação fica 🔴 HighErrorRate on .
Três saídas, em ordem de preferência:
- Coloque o rótulo no
group_by. Se ogroup_byincluirinstance, todo alerta de um grupo o compartilha ecommonLabels.instanceestá sempre presente. O custo são mais notificações — uma por instância em vez de uma por nome de alerta. - Leia o primeiro alerta.
{{alerts[0].labels.instance}}sempre tem valor. É apenas um de possivelmente muitos, então combine com uma contagem:{{alerts[0].labels.instance}} (+{{alerts.length}} alertas). - Desenhe o rótulo para que vazio ainda se leia. O Echobell não tem operador de valor padrão —
{{a || "unknown"}}renderiza o texto literaltrue, não um fallback — então escrevaInstance: {{commonLabels.instance}}em uma linha própria, onde um valor vazio é obviamente vazio em vez de quebrar uma frase.
Mantendo o payload pequeno
Um grupo cobrindo cem pods produz um corpo JSON grande, e o Echobell rejeita corpos de gatilho acima de 1 MiB com HTTP 413. Limite isso no Alertmanager:
- url: "https://hook.echobell.one/t/<channel-token>"
send_resolved: false
max_alerts: 20
O Alertmanager então envia no máximo vinte alertas e coloca em truncatedAlerts o número que descartou, que você pode exibir no corpo:
Body: {{commonAnnotations.summary}}
Alerts: {{alerts.length}} (+{{truncatedAlerts}} truncados)
Compartilhando o alerta com sua equipe
Um canal do Echobell pode ser compartilhado por um link de assinatura, e cada assinante escolhe seu próprio tipo de notificação. A mesma rota pode, portanto, tocar o telefone de quem está de plantão e chegar como push normal para todos os demais — sem preço por assento e sem regras extras de roteamento no Alertmanager.
Isso também combina com a razão pela qual muitas equipes hospedam o Prometheus por conta própria: suas métricas e regras de alerta ficam na sua infraestrutura, e o Echobell mantém conteúdo e histórico de notificações no dispositivo, não nos servidores dele.
O que esta configuração não te dá
Ser honesto sobre o limite evita uma migração ruim mais adiante. O Echobell é uma camada de entrega, não uma plataforma de gestão de incidentes. Ele não tem:
- Escalas de plantão nem passagens follow-the-sun
- Árvores de escalonamento que acionam uma segunda pessoa quando a primeira não atende
- Linhas do tempo de incidente, rastreamento de reconhecimento ou ferramentas de postmortem
Se sua equipe precisa disso, você precisa do PagerDuty, do Grafana Cloud IRM ou similar. O que isto cobre é a lacuna específica que o Alertmanager deixa aberta: converter um alerta disparado em um telefone que realmente toca. Para operadores solo, equipes pequenas e homelabs, isso costuma ser o requisito inteiro.
Solução de problemas
Não chega absolutamente nada. Olhe primeiro os logs do próprio Alertmanager (level=error component=dispatcher) e depois confirme que a rota realmente resolve para o seu receiver: amtool config routes test severity=critical alertname=HighErrorRate diz em qual receiver um alerta cairia, sem esperar que um dispare.
O Echobell retorna HTTP 404. O token do canal está errado ou o canal foi excluído. Um token desconhecido é um 404, não um sucesso silencioso.
O Echobell retorna 200 com "notificationTriggered": false. Sua condição foi avaliada como falsa. O corpo da resposta também traz "conditionsMet": false, que é a forma mais rápida de distinguir "minha condição está errada" de "meu webhook nunca chegou". Verifique status == "firing" contra o que o Alertmanager realmente enviou — o status de nível superior, não alerts[0].status.
HTTP 413. O payload passou de 1 MiB. Configure max_alerts como acima.
HTTP 405. O canal está com POST Only ativado e algo enviou um GET. O Alertmanager faz POST, então isso geralmente significa que você testou a URL num navegador.
O título tem um buraco vazio. O commonLabels não continha aquele rótulo para aquele grupo. Veja a seção acima.
Não toca, mas a notificação chega. O tipo de notificação da assinatura é Normal ou Urgente, não Chamada. O tipo é escolhido por assinante, então confira no aparelho que não está tocando.
Testar sem quebrar a produção. Adicione uma regra com expr: vector(1), um alertname distinto e severity: critical, deixe disparar uma vez e apague. Ou dispare uma na mão:
curl -X POST http://localhost:9093/api/v2/alerts -H 'Content-Type: application/json' -d '[
{"labels":{"alertname":"EchobellTest","severity":"critical"},
"annotations":{"summary":"Testing the phone call path"}}
]'
Perguntas frequentes
O Prometheus Alertmanager consegue fazer uma ligação nativamente?
Não. O Alertmanager tem receivers para e-mail, Slack, PagerDuty, OpsGenie e muitos outros, mas não existe receiver de voz nem de SMS. Ligações exigem rotear o receiver webhook genérico para um serviço capaz de realizá-las, como o Echobell, ou pagar por uma plataforma de gestão de incidentes.
A ligação passa pelo Não Perturbe?
Sim. O tipo de notificação Chamada do Echobell se apresenta como uma chamada recebida, que toca através do modo Foco e do Não Perturbe do iOS. Detalhes e configurações envolvidas em como driblar o modo Foco do iOS para alertas críticos.
Funciona com o Alertmanager atrás de um firewall ou dentro do Kubernetes?
Sim. O webhook é uma requisição HTTPS de saída a partir do Alertmanager, então basta alcançar hook.echobell.one. Seu Alertmanager não precisa de endereço público nem de ingress.
Como paro de ser ligado quando um alerta se resolve?
Defina send_resolved: false na config de webhook que aponta para o canal de chamada. O receiver webhook usa true por padrão, diferentemente da maioria dos outros receivers do Alertmanager, então isso é opt-out e não opt-in. Para ainda receber as recuperações em silêncio, adicione um segundo canal com a condição status == "resolved".
Por que meu telefone toca a cada quatro horas pelo mesmo alerta?
É o repeat_interval, cujo padrão é 4h. O Alertmanager renotifica um alerta ainda ativo nessa cadência. Defina-o por rota — 1h no crítico é uma escolha comum. Se as ligações começaram logo depois de você adicionar uma rota catch-all, o culpado mais provável é o alerta Watchdog, sempre ativo; veja o passo 6.
Várias pessoas podem ser chamadas pelo mesmo alerta?
Sim. Compartilhe o canal com seus colegas e cada assinante escolhe seu tipo de notificação. Todos os inscritos no canal de chamada são chamados, sem custo por assento.
Devo filtrar severidade no Alertmanager ou nas condições do Echobell?
Prefira o Alertmanager: rotear ali também permite definir group_wait e repeat_interval por severidade, e a árvore de roteamento fica versionada junto com o resto da configuração. Use as condições do Echobell quando não puder alterar a config do Alertmanager, ou para filtros que o Alertmanager sequer contempla — como hora do dia.
Fechamento
A configuração é um receiver, um send_resolved: false e uma árvore de roteamento que mantém tudo que não seja severity: critical longe do canal de chamada. Ela deixa suas regras de alerta, agrupamentos, silêncios e inibições exatamente como estão, e fecha a lacuna entre "o Prometheus percebeu" e "um humano percebeu".
Baixe o Echobell para iPhone ou pegue no Google Play, e então dispare o alerta EchobellTest acima antes de confiar nesse caminho para algo real.