Skip to content

feature: alert-relay — alertas de dgb.ops.alerts no Telegram da equipe - #214

Merged
nitaibezerra merged 2 commits into
mainfrom
feat/alert-relay-telegram
Nov 3, 2026
Merged

nitaibezerra merged 2 commits into
mainfrom
feat/alert-relay-telegram

Conversation

@nitaibezerra

Copy link
Copy Markdown
Contributor

Objetivo

Entregar os alertas operacionais no canal do Telegram da equipe, o mesmo da skill enviar-telegram. A infraestrutura veio no destaquesgovbr/infra#220, já aplicado: tópico dgb.ops.alerts, notification channel Pub/Sub do Cloud Monitoring, alert policy enrichment-worker: instância morta pelo liveness, Cloud Run destaquesgovbr-alert-relay (placeholder) e secrets. Este PR traz o código do relay e o deploy.

alert policy ──► channel (pubsub) ──► dgb.ops.alerts ──push──► alert-relay ──► Telegram sendMessage
                                            ▲
                     qualquer job pode publicar {"text": "...", "title": "...", "severity": "..."}

Worker workers/alert_relay (genérico)

  • formatter.py: formata em HTML escapado, respeitando o limite de 4096 caracteres do Telegram. Testes (atributo test=true ou "test": true) saem com 🧪 [TESTE]. Entradas aceitas:
    • incidente do Cloud Monitoring ({"incident": {...}, "version": "1.2"}): 🔴 ALERTA ou ✅ RESOLVIDO, com resumo, condição, recurso, início/fim, documentação e link;
    • mensagem genérica {"text", "title"?, "severity"?, "source"?};
    • texto cru.
  • telegram.py: sendMessage com chat_id e message_thread_id opcional.
    • Um 400 é tentado de novo sem parse_mode.
    • Erro de rede vira só o nome da exceção, porque a URL da Bot API contém o token.
  • secrets.py: lê o token e o chat id do Secret Manager em runtime (REST e google-auth), com cache de 5 min.
    • Se a leitura falhar, usa o último valor conhecido.
    • O infra cria só o recurso do secret (o valor é adicionado à parte), então o serviço precisa subir antes de o valor existir.
    • Assim o token nunca fica em env nem na config da revisão.
  • app.py:
    • /health é async.
    • /process lê o envelope e roda o envio no threadpool.
    • Respostas: 200 quando entregue ou quando reentregar não resolve (envelope inválido, 400 persistente); 503 para reentregar (429, 5xx, rede, 401/403/404, secret indisponível).
    • Linha de log estável: alert_relay_sent status=<http> ok=<bool> kind=<incident|text|raw> state=… test=… policy=… message_id=….
  • Deploy: docker/alert-relay/Dockerfile, no padrão dos outros workers, e .github/workflows/alert-relay-deploy.yaml com o cloud-run-deploy reutilizável, que só troca a imagem.

Testes

  • Os commits seguem TDD: test: … (red) e depois feature:.
  • tests/unit/workers/alert_relay/test_alert_relay.py tem 32 testes: formatter, telegram (thread, retentáveis, 400 com fallback, erro de rede sem vazar o token), secrets (cache, fallback, valor vazio) e app (200, 503, ACK, token fora dos logs e da resposta).
  • tests/unit/test_alert_relay_deploy_workflow.py confere que o workflow aponta para os recursos do infra.
  • pytest tests/unit/ --cov=data_platform: 1340 passed, cobertura de 82,6%.

Depois do merge

  1. O deploy troca o placeholder pela imagem do relay.
  2. Com os valores dos secrets adicionados, faço um teste ponta a ponta com uma mensagem 🧪 [TESTE] publicada em dgb.ops.alerts.

Follow-up (fora deste PR)

O monitor_scraping_health (scraper) hoje só loga, por falta de webhook. Ele pode publicar {"text": ...} em dgb.ops.alerts.

🤖 Generated with Claude Code

nitaibezerra and others added 2 commits November 3, 2026 06:45
Contrato do worker genérico de alertas operacionais:
- formata incidentes do Cloud Monitoring (aberto/resolvido), mensagens
  {"text","title","severity","source"} e texto cru, com HTML escapado e limite
  de 4096 caracteres; marca [TESTE] (atributo test=true ou "test": true);
- envia com chat_id e message_thread_id opcional; 400 tenta de novo sem
  parse_mode;
- 200 quando o Telegram aceita; 503 em 429/5xx/rede/401/403/404 e secret
  indisponível; ACK em 400 persistente e envelope inválido;
- secrets lidos em runtime com cache; o token nunca aparece em log/resposta.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Worker genérico (Cloud Run, push do tópico dgb.ops.alerts) que entrega no canal
do Telegram da equipe:
- formatter: incidentes do Cloud Monitoring (notification channel pubsub,
  aberto/resolvido, com link e documentação), mensagens {"text","title",
  "severity","source"} de qualquer job e texto cru; HTML escapado, limite do
  Telegram e marca 🧪 [TESTE];
- telegram: sendMessage com message_thread_id opcional; 400 tenta de novo sem
  parse_mode; erro de rede vira só o nome da exceção (a URL tem o token);
- secrets: token e chat id lidos do Secret Manager em runtime, cache de 5 min e
  último valor conhecido em falha (o serviço sobe antes de o valor existir);
- app: /health async; /process responde 200 (entregue ou sem conserto), 503
  para reentregar (429/5xx/rede/401/403/404, secret indisponível); linha
  estável alert_relay_sent status=… ok=… kind=… state=… test=… policy=…;
- docker/alert-relay e alert-relay-deploy.yaml (cloud-run-deploy reutilizável,
  serviço destaquesgovbr-alert-relay criado no infra, ops-alerts.tf).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nitaibezerra
nitaibezerra merged commit 06d03a5 into main Nov 3, 2026
1 check passed
@nitaibezerra
nitaibezerra deleted the feat/alert-relay-telegram branch November 3, 2026 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant