Repository navigation
feat(monitoring): dashboard and alert rules for iroh-dns-server - #201
Merged
Merged
Conversation
- monitoring/iroh-dns-server/exported-metrics.txt: the /metrics of the pinned iroh-dns-server 1.3.0 (x86_64 release asset, sha256-checked), captured from a fresh process. make lint-helm checks every dns_server_* name against it, as it does relayserver_* (this also pins the role's readiness-gate metric). - dashboard-iroh-dns-server.json (uid decdn-iroh-dns-server): up (instant), publishes and DNS requests per day, zones cached, mean HTTP duration; pkarr publishes (update vs no-op), the record store, cached zones; DNS requests by transport (tcp = total - udp - https), lookups by answer; HTTP requests and mean duration; the server's log. - Rule group iroh-dns-server with promtool tests: IrohDnsServerDown (the *Down shape with the absence arm), IrohDnsServerLookupErrors (a rise against the server's own last day with a 0.1/s floor: a scanner's NOTIMP counts as an error, an out-of-zone query is NXDOMAIN, both checked on the real binary), IrohDnsServerNoPublishes (no pkarr put in 30m after some in the last day). - render-test.sh, docs (monitoring/README, the role README and its bump checklist, ansible/ and compose/ READMEs, lifecycle silence notes, AGENTS.md, the grafana-dashboards skill). Closes #118 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Dashboard and alert descriptions misrepresent packet acceptance, lookup-cache occupancy, and store retention, potentially misleading operators about address churn, published-node counts, and cached-answer expiry.
3 open issues
What changed in this PR
Adds monitoring for self-hosted iroh DNS servers, using the existing Alloy metrics and logs on Ansible and Compose deployments.
Changes:
- Adds a dashboard covering publishes, DNS lookups, HTTP traffic, cache activity, and logs.
- Adds three alert rules with unit tests and an exported-metrics snapshot.
- Extends validation and documents monitoring setup, maintenance, and alert silencing.
| File | Description |
|---|---|
monitoring/README.md |
Documents DNS monitoring assets and external probes. |
monitoring/iroh-dns-server/prometheus-alerts.yml |
Adds downtime, lookup-error, and stopped-publish alerts. |
monitoring/iroh-dns-server/prometheus-alerts_test.yml |
Tests alert timing and representative failure scenarios. |
monitoring/iroh-dns-server/exported-metrics.txt |
Records the pinned server’s exported metrics. |
monitoring/iroh-dns-server/dashboard-iroh-dns-server.json |
Adds the DNS server dashboard. |
docs/lifecycle.md |
Documents silencing alerts during migration and decommission. |
compose/README.md |
Links monitoring assets and describes Alloy integration. |
charts/decdn-node/tests/render-test.sh |
Extends rule, metric-name, dashboard, and package-isolation checks. |
ansible/roles/iroh_dns_server/vars/main.yml |
Adds a comment linking the readiness metric to the snapshot. |
ansible/roles/iroh_dns_server/README.md |
Links monitoring assets and adds metric recapture guidance. |
ansible/README.md |
Links the new dashboard and alerts. |
AGENTS.md |
Updates the monitoring map and release-maintenance guidance. |
.github/workflows/ci.yml |
Clarifies monitoring coverage in a comment. |
.claude/skills/grafana-dashboards/SKILL.md |
Documents DNS dashboard metrics and maintenance. |
Review effort: Balanced
… boundaries Review of #201 against upstream v1.3.0 (and the real binary): - every node republish is a pkarr *update* (re-signed with a fresh timestamp); no-op is only a put older than the stored packet. The publishes and record-store panels said the opposite. - a failing record store answers REFUSED (node_zone_handler's err_refused), not SERVFAIL; the rule comment, annotation (now naming the store's real WARN/ERROR lines), the lookups panel and the README say so. An AXFR is NOERROR with no answer (checked on the binary), so it counts as not found. - dns_server_cache_zones is the lookup cache: a key enters on a lookup and leaves on its next publish. It is not a node count. - the mean HTTP duration includes /healthz and truncates to whole ms. - a series under ~8 hours old fires on any steady error rate over the floor; say so in the rule and its annotation. Tests: pin the 3x multiplier (2.5x silent, 4x fires), the 0.1/s floor (0.083 vs 0.117), the 15m for to the minute, the 1d memory and resolution of LookupErrors; each summed publish counter on its own in both arms, resolution when puts resume, the reset inside a window, and the 94m fire time. Also: the root README's monitoring row, NoPublishes silencing on Compose, both dig checks named alike, AGENTS.md no longer implies test-scripts checks exported-metrics.txt, and render-test cleans up its new negative. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the cache outlives them Store eviction runs on the packet's signed timestamp (each republish re-signs, so about its last accepted put) and does not clear the lookup cache, so a cached key can keep resolving past the 7 days (Copilot review on #201). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Closes #118.
Adds
monitoring/iroh-dns-server/, mirroringmonitoring/iroh-relay/. Alloy already scrapes the server asjob="iroh-dns-server"on the Ansible path and Compose'sdnsprofile, and labels its journalunit="iroh-dns-server.service".What's in it
exported-metrics.txt: the/metricsof the pinnediroh-dns-server1.3.0, captured from a fresh process. It was the x86_64 release asset, checked against the role's sha256. The header has the re-capture command.make lint-helmnow checksdns_server_*names against it, as it doesrelayserver_*. This also pins the role's gate metric,dns_server_dns_requests_total.uid: decdn-iroh-dns-server):iroh-dns-server, with promtool unit tests:IrohDnsServerDown: the*Downshape with the absence arm (monitoring: the *Down alerts never fire when the whole host dies (Ansible/Compose path) #109). The tests are the relay's block, relabelled.IrohDnsServerLookupErrors: the 30m error rate is above 0.1/s and more than 3× the server's own 1d rate, for 15m.IrohDnsServerNoPublishes: no pkarr put (update + no-op) in 30m after some in the last day, for 5m. Nodes republish every 5 minutes.render-test.sh: promtool check and tests, the uid check, the name check, and the chart-leak substring and its negative.monitoring/README.mdgets a new section and the*Downlist. In the role README, "no dashboard yet" is gone and the bump checklist gets a re-capture step. "No dashboard or alert rules yet" is gone fromansible/README.mdandcompose/README.md.docs/lifecycle.md: silence the alerts before a migration or decommission. Repointing the nodes firesNoPublishes.AGENTS.mdand the grafana-dashboards skill.Why the lookup-error rule is a rise, not a share
I ran the real 1.3.0 binary to see what moves
dns_server_dns_lookup_error_total. It counts every answer other than NOERROR or NXDOMAIN:., so it counts as not found.So a public udp/53 has a steady floor of errors, and a quiet server could sit above any fixed share for good. Comparing against the server's own day absorbs that floor. The 0.1/s floor keeps a server with no baseline from firing on a handful of probes. The rule comment documents one limit: a server less than a day old has an understated baseline, and a unit test pins that.
Certificate expiry is not exported. The docs point to an external
https://<hostname>/healthzprobe and an externaldig, as the relay's do.Verification
make lint-helm: promtool check (3 rules), the unit tests, the uid check, and "iroh-dns-server dashboard and rules name only exported series" all pass. The new chart-leak negative also passes.dns_server_bogus_totalin the dashboard → the name check fails.make lint,make test-scripts: pass.🤖 Generated with Claude Code