Alertmanager: alertas do Prometheus para Slack e email

Alertmanager é o componente do Prometheus responsável por receber alertas disparados pelas regras de alerta e encaminhar para os canais corretos, Slack, email, PagerDuty, Telegram. Mais importante: ele deduplica, agrupa e inibe alertas para que você receba notificações úteis, não spam.

Instalar e configurar o Alertmanager

Adicionar Alertmanager ao stack Prometheus:

yaml
# docker-compose.yml — adicionar Alertmanager:
services:
  alertmanager:
    image: prom/alertmanager:latest
    container_name: alertmanager
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
      - alertmanager-data:/alertmanager
    command:
      - '--config.file=/etc/alertmanager/alertmanager.yml'
      - '--storage.path=/alertmanager'
      - '--web.external-url=https://alertmanager.seudominio.com.br'
    ports:
      - "127.0.0.1:9093:9093"
    restart: unless-stopped

# prometheus.yml — apontar para o Alertmanager:
alerting:
  alertmanagers:
    - static_configs:
        - targets: ['alertmanager:9093']

rule_files:
  - "alerts/*.yml"   # pasta com arquivos de regras de alerta

volumes:
  alertmanager-data:

Configurar receivers: Slack e email

alertmanager.yml com roteamento para múltiplos canais:

yaml
# alertmanager.yml:
global:
  resolve_timeout: 5m

  # Email (SMTP):
  smtp_smarthost: 'smtp.gmail.com:587'
  smtp_from: 'alertas@seudominio.com.br'
  smtp_auth_username: 'alertas@seudominio.com.br'
  smtp_auth_password: 'SENHA_APP_GOOGLE'
  smtp_require_tls: true

route:
  group_by: ['alertname', 'cluster', 'service']
  group_wait: 30s        # aguardar 30s para agrupar alertas do mesmo grupo
  group_interval: 5m     # intervalo mínimo entre notificações do mesmo grupo
  repeat_interval: 4h    # reenviar alerta não resolvido a cada 4h
  receiver: 'slack-critico'

  routes:
    # Alertas críticos → Slack #alertas-criticos + email
    - match:
        severity: critical
      receiver: 'critico-multi'
      continue: false

    # Alertas de warning → Slack #alertas-warning apenas
    - match:
        severity: warning
      receiver: 'slack-warning'

receivers:
  - name: 'slack-critico'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/SEU/WEBHOOK/TOKEN'
        channel: '#alertas-criticos'
        send_resolved: true
        title: '{{ if eq .Status "firing" }}🔴{{ else }}✅{{ end }} {{ .GroupLabels.alertname }}'
        text: |
          *Ambiente:* {{ .GroupLabels.cluster }}
          *Serviço:* {{ .GroupLabels.service }}
          {{ range .Alerts }}
          *Descrição:* {{ .Annotations.description }}
          *Desde:* {{ .StartsAt.Format "02/01/2006 15:04" }}
          {{ end }}

  - name: 'critico-multi'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/SEU/WEBHOOK/TOKEN'
        channel: '#alertas-criticos'
        send_resolved: true
    email_configs:
      - to: 'oncall@seudominio.com.br'
        send_resolved: true
        subject: '[CRITICO] {{ .GroupLabels.alertname }} - {{ .GroupLabels.service }}'

  - name: 'slack-warning'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/SEU/WEBHOOK/TOKEN'
        channel: '#alertas-warning'
        send_resolved: true

Regras de alerta para API Node.js

Definir alertas PromQL para latência, erros e disponibilidade:

yaml
# alerts/nodejs-api.yml:
groups:
  - name: nodejs-api
    interval: 30s
    rules:

      # Alta taxa de erros 5xx:
      - alert: ApiAltaTaxaErros
        expr: |
          sum(rate(http_request_duration_seconds_count{status_code=~"5.."}[5m]))
          /
          sum(rate(http_request_duration_seconds_count[5m])) > 0.05
        for: 2m        # disparar apenas se a condição persistir por 2 minutos
        labels:
          severity: critical
          service: nodejs-api
        annotations:
          summary: "Taxa de erros acima de 5%"
          description: "Taxa atual: {{ $value | humanizePercentage }}. Endpoint com mais erros pode ser visto no Grafana."

      # Latência P99 alta:
      - alert: ApiLatenciaAlta
        expr: |
          histogram_quantile(0.99,
            sum by (le) (rate(http_request_duration_seconds_bucket[5m]))
          ) > 2
        for: 5m
        labels:
          severity: warning
          service: nodejs-api
        annotations:
          summary: "P99 de latência acima de 2s"
          description: "P99 atual: {{ $value | humanizeDuration }}"

      # API fora do ar (sem métricas):
      - alert: ApiForaDoAr
        expr: up{job="nodejs-api"} == 0
        for: 1m
        labels:
          severity: critical
          service: nodejs-api
        annotations:
          summary: "API Node.js inacessível"
          description: "O endpoint de métricas da API não responde há mais de 1 minuto."

      # Memória Node.js alta:
      - alert: NodejsMemoriaAlta
        expr: |
          process_resident_memory_bytes{job="nodejs-api"}
          / 1024 / 1024 > 512
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Uso de memória acima de 512MB"
          description: "Memória atual: {{ $value | humanize1024 }}B"

Inibições e silêncios

Evitar notificação de alertas derivados e silenciar durante manutenção:

yaml
# alertmanager.yml — seção inhibit_rules:
inhibit_rules:
  # Se API está fora do ar (critical), inibir alertas de latência (warning):
  # Evita receber "latência alta" quando o problema real é "api fora do ar"
  - source_match:
      alertname: 'ApiForaDoAr'
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['service']   # mesmo serviço

  # Se servidor está down, inibir alertas de aplicação no mesmo servidor:
  - source_match:
      alertname: 'ServidorForaDoAr'
    target_match_re:
      alertname: 'Api.*|Nodejs.*|Postgres.*'
    equal: ['instance']

# Silêncio via API do Alertmanager (para manutenção planejada):
# POST /api/v2/silences
curl -X POST http://alertmanager:9093/api/v2/silences   -H 'Content-Type: application/json'   -d '{
    "matchers": [{"name": "service", "value": "nodejs-api", "isRegex": false}],
    "startsAt": "2026-06-08T02:00:00Z",
    "endsAt": "2026-06-08T04:00:00Z",
    "comment": "Manutenção programada, deploy v2.0",
    "createdBy": "admin"
  }'

# Listar silêncios ativos:
curl http://alertmanager:9093/api/v2/silences

# Verificar configuração do Alertmanager sem reiniciar:
curl -X POST http://alertmanager:9093/-/reload

Testar e depurar alertas

Ferramentas para validar regras e simular alertas:

bash
# Validar arquivo de regras de alerta:
docker run --rm -v $(pwd)/alerts:/alerts   prom/prometheus:latest   promtool check rules /alerts/nodejs-api.yml

# Testar expressão PromQL no Prometheus:
# Acessar http://localhost:9090/graph e colar a expr do alerta

# Verificar alertas ativos no Prometheus:
# http://localhost:9090/alerts

# Forçar disparo de um alerta para testar:
# Opção 1: usar amtool (CLI do Alertmanager):
docker run --rm prom/alertmanager:latest   amtool alert add alertname=TestAlerta     service=nodejs-api     severity=critical     --alertmanager.url=http://alertmanager:9093     --annotation=summary="Teste de alerta"     --annotation=description="Verificando integração Slack"

# Opção 2: criar uma regra que sempre dispara (para teste):
# - alert: TesteSempreFire
#   expr: vector(1) > 0
#   annotations:
#     summary: "Alerta de teste — remover após verificar"

# Verificar roteamento sem enviar notificações:
amtool config routes test   --alertmanager.url=http://alertmanager:9093   --config.file=alertmanager.yml   severity=critical service=nodejs-api

Não quer configurar manualmente?

Implante o VPS para Node.js em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Perguntas frequentes

group_wait: tempo de espera após o primeiro alerta de um grupo antes de enviar, permite agrupar alertas que chegam juntos (padrão: 30s). group_interval: tempo mínimo entre notificações adicionais do mesmo grupo quando novos alertas chegam (padrão: 5m). repeat_interval: com que frequência reenviar um alerta que continua disparando mas não foi resolvido, evita silêncio prolongado (padrão: 4h). Configuração típica para produção: group_wait: 30s, group_interval: 5m, repeat_interval: 4h.

O Alertmanager não tem receiver nativo para Telegram, mas tem webhook. Use um receiver webhook que aponta para um bot intermediário, ou use a integração com webhook_configs apontando para um endpoint Node.js que encaminha para a API do Telegram. Alternativa mais simples: usar Grafana OnCall ou o webhook nativo do Alertmanager com um pequeno script que traduz para a API do Telegram. Para simplificar: o campo webhook_configs do Alertmanager aceita qualquer endpoint HTTP que receba o JSON de alerta.

O Prometheus avalia todas as regras a cada intervalo de scrape (padrão: 15s ou o que você configurar em interval). Centenas de regras simples têm impacto negligenciável. Regras com subqueries ou funções como predict_linear() são mais custosas. Boas práticas: use recording rules para pré-computar expressões complexas usadas em múltiplos alertas, agrupe regras relacionadas no mesmo grupo para avaliação em paralelo, evite for: muito curto (< 1m) para evitar flap.

Recording rules pré-computam expressões PromQL e armazenam o resultado como nova série temporal. Úteis quando: a mesma expressão complexa aparece em múltiplos alertas ou dashboards (evita recalcular), a expressão é lenta (muitos dados históricos), você quer reduzir a carga de consultas no Grafana. Exemplo: em vez de calcular histogram_quantile(0.99, ...) em 5 alertas, crie uma recording rule api:request_latency_p99:rate5m que calcula uma vez e é reutilizada.

Prometheus mostra os alertas em /alerts, você vê estado INACTIVE/PENDING/FIRING. PENDING significa que a condição foi atendida mas o for ainda não passou. FIRING significa que o alerta foi enviado ao Alertmanager. No Alertmanager (/api/v2/alerts), você vê alertas ativos e receivers que receberam. Para confirmar envio do Slack: verifique logs do container (docker logs alertmanager). Para e-mail: verifique logs SMTP e spam. Use amtool alert add para injetar um alerta de teste sem precisar que a condição seja verdadeira.