Skip to content

Optional monitor integration: alert receiver, silences, monitor metrics, cometduty export - #22

Merged
abhijitkrm merged 13 commits into
mainfrom
feat/monitor-integration
Oct 14, 2026
Merged

abhijitkrm merged 13 commits into
mainfrom
feat/monitor-integration

Conversation

@abhijitkrm

@abhijitkrm abhijitkrm commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

cometcli works with a monitor (cometduty, or Prometheus + Alertmanager) and without one. Everything here is off until configured, and each link works with either monitor.

What's new

  • watch --listen receives cometduty's webhook or Alertmanager's.
    • cometduty alerts are checked against their HMAC signature, and replays and stale timestamps are refused. Alertmanager alerts need the bearer token.
    • The node an alert names is triaged at once. When triage finds nothing, the alert itself becomes the incident (monitor:<kind>), and the monitor's resolve clears it.
    • An alert about no single node runs a fleet sweep.
    • Only kind, target, labels and severity steer the work. Alert text, which can quote node logs, never reaches the agent.
  • Silences during planned work: node service stop/restart, node recreate and provision --reconfigure silence the node's alerts for 15 minutes; upgrade switch silences the whole chain's for 30.
    • They use the Alertmanager v2 API at the node's endpoints.monitor and at monitor.silence, going through ssh when the API is on the node's loopback.
    • The chain instance's no-nodes/stalled are silenced too when its source node is the one being worked on.
    • A monitor that can't be reached never blocks the work.
  • endpoints.monitor: triage reads the monitor's /metrics as monitor.* signals. New cases: monitor-unreachable and monitor-alerts-silenced.
  • network export <chain> --format cometduty writes a sidecar per node plus the chain-role instance from the profiles.
    • Metrics and the API listen on loopback by default.
    • --deploy starts them on the hosts (run as the node home's owner).
    • --link records them in the config.
    • --webhook-url and --silence-api generate secrets and save them as credentials.
  • Smaller fixes: fleet commands no longer need an active profile; watch summarizes issues left from an earlier run in one line.

Live test (primium-6, 4 hosts, 2026-10-14 IST)

  • Deploy: built the cometduty branch image on the hosts. network export --silence-api --webhook-url … --link --deploy started 5 instances in 47s.
  • Triage: reads every node's monitor through ssh (signing streak, window %, signer height, disk, alerts, silences).
  • Unplanned outage (archive container stopped directly): the chain instance's alert reached watch in seconds and a fleet sweep found the archive down. On recovery, watch re-triaged the archive and reported it resolved.
  • Planned stop (node service stop): silenced at the sidecar and the chain instance; no node-down reached watch in 4+ minutes. Found and fixed the chain instance's no-nodes leak.
  • Four cometduty bugs found along the way, fixed in Webhook payload v1, signed webhooks, silence API, generic sidecar kit + 4 live-found fixes cometduty#2: evm-lag false positive, node-down never firing after catch-up, signer-stalled on non-signers, chains.d permission.
  • Tests: 427 pass. TestCometdutyAcceptsExport validates every generated config with the real cometduty binary (set COMETDUTY_BIN).

Depends on

Telegram and live fixes (2026-10-14)

  • network export --telegram (or --telegram-chat) points cometduty's Telegram notifier at the bot and chat watch uses, so both tools post to one chat.
  • One card per issue: in Telegram, watch posts each issue as one card and edits it as the work goes on. The card has a bold headline, a plain reason (new optional plain: field on KB cases; the 54 critical/high cases have one), the raw evidence and the agent's report as collapsed quotes, and a status line. A reply marks the resolve. Notifiers that can't edit get the card when it opens and when it's done. Approvals have a bold headline and plain Approve / Deny buttons. No emoji.
  • Planned work: watch leaves planned work alone. Planned operations are recorded locally in planned.json (so this works with no monitor) and checked against active silences at the monitors. An issue under planned work is posted once and not worked; if it outlasts the work it's handled then; if it clears, nothing is posted.
  • Queued alerts: alerts that pile up during long work collapse to each condition's latest state. Live, an already-resolved evm-down had started an agent run.
  • Cooldown: an issue that returns within the cooldown is now reported ("back again — not acting automatically"). Before, it was silent.
  • Redeploy: a redeploy restarts cometduty when its config changed. compose up -d alone kept the old config.
  • fleet tools: fleet status/exec/shell now set a call deadline that covers --timeout. A fixed 90s had cut long commands short.
  • Live run: archive stopped on primium-6 → cometduty cards → watch card → approval in Telegram → restart → resolved. About 7 messages, against 15+ before.

Standalone layout

  • network export --layout standalone writes one cometduty for the whole network, run on the --chain-on host. It covers every validator's signing, the active set, chain health, and each node whose RPC it can reach. --rpc adds endpoints such as a public RPC; they serve as data sources and don't page.
  • It has no disk, signer-state or log alerts; those need the sidecar layout (the default). Its default metrics port is 28696, so it can run next to sidecars.
  • Fix: a validator profile that saved only its account address had no valoper, so neither layout watched its signing. The valoper is now derived from the account address.
  • Live: one standalone instance on primium-6's archive host saw all 3 validators bonded and signing, through that host's RPC alone.

🤖 Generated with Claude Code

abhijitkrm and others added 13 commits October 14, 2026 09:57
…cs, cometduty export

Everything here is off until configured; cometcli works as before without a
monitor.

- watch --listen (or watch.listen) receives cometduty's webhook (HMAC
  verified, replays refused) or Alertmanager's (bearer token). The node an
  alert names is triaged at once; when triage finds nothing the alert
  becomes the incident (monitor:<kind>) until the monitor resolves it.
  Only kind, target, labels and severity steer the work; alert text never
  reaches the agent.
- Silences during planned work: node service stop/restart, node recreate,
  provision --reconfigure and upgrade switch silence the node's alerts
  (the chain's for a switch) via the Alertmanager v2 API at the node's
  endpoints.monitor and monitor.silence, through ssh when on the node. A
  monitor that can't be reached never blocks the work.
- endpoints.monitor: triage reads the monitor's /metrics as monitor.*
  signals; new cases monitor-unreachable and monitor-alerts-silenced.
- network export --format cometduty writes a sidecar per node and the
  chain-role instance from the profiles; --deploy starts them on the
  hosts, --link records them in the config.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ntrypoint

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…in instance

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The chain-role instance reads the chain through one node (monitor.silence
via). Stopping that node raised no-nodes there despite the node's silence;
silencing it now also mutes no-nodes/stalled for the chain at that
instance. Found live.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
network export --telegram points cometduty's own Telegram notifier at the
bot and chat watch uses, so a monitor's alerts and watch's diagnosis and
approvals land in one chat.

Planned work (restart, recreate, reconfigure, upgrade switch) is recorded
locally as well as silenced at monitors. watch checks both, plus active
silences of the node or chain at its monitors, before working an issue:
it posts it once as planned and leaves it alone, handles it afresh if it
outlasts the work, and stays quiet if it clears. Fix mode could otherwise
restart a node stopped on purpose.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docker compose up -d only recreates for a changed compose file, so a
redeploy with new settings (Telegram, a new webhook) left cometduty on its
old config. Its state lives in ./state, so the restart keeps silences and
open alerts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Messages to Telegram are rendered from cometcli's Markdown into Telegram
HTML (bold, code, italics, bullets), with a plain-text fallback, and
watch's headings are tidier: node in bold, case, severity. Reports drop
local file paths.

Alerts that queue while watch works something long are collapsed to each
condition's latest state, so an alert raised and resolved meanwhile is
not worked as a new issue (seen live: a resolved evm-down started an
agent run after a restart).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An issue was five or six messages (detected, working, report, resolved).
Now it is one card, edited as the work goes on — bold headline, a plain
reason, the raw evidence and the agent's report as collapsed quotes, and
a status line — plus a reply when it resolves (edits make no sound).
Notifiers that can't edit get the card when it opens and when it's done.
No emoji; approvals have a bold headline and plain Approve / Deny.

kb: cases get an optional plain: sentence; the 54 critical/high ones have
one.

fleet status/exec/shell: the call deadline was a fixed 90s, so --timeout
600 still cut a docker build off at 90s ('context deadline exceeded').
It now covers the per-node timeout plus time to approve.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Within the cooldown watch skipped a returning issue without a word: live,
the archive went down again 46 minutes after the last fix and cometcli
said nothing. Its card now says it is back and that watch won't act on
it automatically until the cooldown ends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
--layout standalone writes one cometduty for the whole network, run on
the --chain-on host: every validator's signing (deduplicated by operator
address), the active set, chain health, and each node whose RPC it can
reach — a loopback RPC only from its own host; the rest are named. --rpc
adds endpoints it can reach (a public RPC) as data sources that don't page.
It has no node home or logs, so disk, signer-state and log alerts stay with
the sidecar layout. Default metrics port 28696, apart from the sidecars.
--link records it under monitor.silence.

Validator profiles that saved only metadata.account had no valoper, so
neither layout watched their signing (live: v6-val3). The valoper is now
derived from the account address (same bytes).

Live on primium-6: one standalone instance on the archive host, reading
only its RPC, saw all three validators bonded and signing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cometduty's goreleaser tags images {{ .Version }} (0.3.0), so :v0.3.0
would not exist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@abhijitkrm
abhijitkrm merged commit f144dd0 into main Oct 14, 2026
2 checks passed
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