Skip to main content
DNZ serves its counters at /metrics in the Prometheus text format. Prometheus scrapes them, Grafana graphs them, and the alert rules that come with DNZ tell you when something is off. You run Prometheus and Grafana wherever you like; they only need to reach DNZ. What is in there:
  • queries by source (local, cache, upstream, blocked…), response code, type and transport, and a latency histogram,
  • the cache: hits, misses, stale answers, prefetches, evictions,
  • every upstream’s health, round-trip time and failures,
  • blocked queries, RPZ hits, the per-client rate limit and response rate limiting,
  • DNSSEC validation results and the recursive resolver,
  • zone transfers, NOTIFY, secondary zones and dynamic updates,
  • certificate expiry, dnz-proxy nodes, Traefik, GeoDNS health checks and the Caddy/Traefik syncs.
Metrics are off by default.

Turn them on

Open Settings → General → Prometheus metrics, switch it on and pick where it is served: Make a token creates a bearer token Prometheus sends with every scrape. It is shown once: copy it. A scrape without it, or with the wrong one, gets 401. The card then shows a scrape config for Prometheus, filled in with DNZ’s address as your browser reaches it (change it to the address Prometheus uses), and a curl line to check it from the Prometheus host. The same from the terminal:
Or in the config file, which applies until the settings are saved in the dashboard or the CLI:
Without a token, anyone who reaches the own listen address can read the metrics (names of zones, upstreams, proxies and certificates are in the labels). Listen where only Prometheus can reach, or make a token.

Scrape it

Add a job to prometheus.yml on the Prometheus server. With a token, keep it in a file only Prometheus can read:
Several DNZ servers go into the same job, one target each. In a cluster, scrape every node: each serves its own counters (dnz_build_info carries its node id, dnz_cluster_leader and dnz_cluster_generation its place in the cluster), and metrics settings saved on one node reach the others within 15 seconds. Check it from the Prometheus host:

Prometheus and Grafana with Docker Compose

DNZ’s repository has a compose file in deploy/monitoring/ that runs Prometheus (with DNZ’s alert rules) and Grafana (with the dashboard and the data source already set up) for a DNZ that runs elsewhere:
DNZ_TARGET is host:port as Prometheus reaches DNZ: the own listen address, or the dashboard’s address with DNZ_SCHEME=https behind TLS. Grafana is on port 3000 (user admin), Prometheus on 9090.

Grafana dashboard

Import deploy/grafana/dnz-dashboard.json (Dashboards → New → Import) and pick your Prometheus data source. The data source and the DNZ servers to show are variables at the top. It has rows for the overview (queries per second, cache hit ratio, SERVFAIL ratio, p95 latency, upstreams up, soonest certificate expiry), queries, cache and upstreams, filtering and rate limits, DNSSEC and recursion, zones and transfers, certificates and proxies, and the process.

Alert rules

deploy/prometheus/dnz-alerts.yml has rules for: Add the file to rule_files in prometheus.yml. The rules expect the job to be called dnz.

Metrics reference

Every metric, with its labels, is listed in docs/metrics.md. A few to start with: Labels never carry query names or client addresses, so the number of series stays small; query types outside the common ones are counted as other.