COREDNS-METRICS(7)
๐ COREDNS-METRICS(7) โ the prometheus plugin, explained ๐
okay so bestie, real talk: this is the manpage for the prometheus plugin, and its whole personality is enabling Prometheus โจhttps://prometheus.io/โฉ metrics. That's the NAME section, we're done, slay. โจ
๐ธ DESCRIPTION ๐ธ
So with prometheus you export metrics from CoreDNS and, like, from any plugin that happens to have them. The default hangout spot for the metrics is localhost:9153, and the metrics path is fixed to /metrics โ no negotiating, it's giving "my way or the highway". ๐ฃ๏ธ
On top of the default Go metrics that the Prometheus Go client โจhttps://prometheus.io/docs/guides/go-application/โฉ exports on its own, you also get these absolute icons: ๐
coredns_build_info{version, revision, goversion}โ info about CoreDNS itself. the lore.coredns_panics_total{}โ total number of panics. screaming, crying, throwing up counter ๐ญcoredns_dns_requests_total{server, zone, view, proto, family, type}โ total query count.coredns_dns_request_duration_seconds{server, zone, view, type}โ duration to process each query.coredns_dns_request_size_bytes{server, zone, view, proto}โ size of the request in bytes. Uses the original size before any plugin rewrites โ pre-glow-up measurements only, bestie.coredns_dns_do_requests_total{server, view, zone}โ queries that have the DO bit set.coredns_dns_response_size_bytes{server, zone, view, proto}โ response size in bytes.coredns_dns_responses_total{server, zone, view, rcode, plugin}โ response per zone, rcode and plugin.coredns_dns_https_responses_total{server, status}โ responses per server and http status code.coredns_dns_quic_responses_total{server, status}โ responses per server and QUIC application code.coredns_plugin_enabled{server, zone, view, name}โ indicates whether a plugin is enabled on per server, zone and view basis.
Almost every counter carries a zone label, and that's just the zonename used for the request/response. ๐บ๏ธ
โจ the extra labels, decoded โจ
serveridentifies the server responsible for the request. It's a string formatted as the server's listening address:<scheme>://[<bind>]:<port>. So for a "normal" DNS server this isdns://:53. And if you're using thebindplugin, an IP address gets included too, e.g.dns://127.0.0.53:53. ๐ซถprotoholds the transport of the response ("udp"or"tcp").familyis the address family of the transport (1= IP (IP version 4),2= IP6 (IP version 6)).typeholds the query type. It covers the most common types (A,AAAA,MX,SOA,CNAME,PTR,TXT,NS,SRV,DS,DNSKEY,RRSIG,NSEC,NSEC3,HTTPS,IXFR,AXFRandANY) plus"other", which is the group-chat where all the remaining types get lumped together. ๐statusholds the https status code. possible values are:200โ request is processed,404โ request has been rejected on validation,400โ request to dns message conversion failed,500โ processing ended up with no response.
pluginholds the name of the plugin that made the write to the client. And if the server did the write (on error for instance), the value is empty. ghosted. ๐
If monitoring is enabled, queries that do not enter the plugin chain get exported under the fake name "dropped" โ and note there's no closing dot on it, because this is never a valid domain name. it's a fake name, it's cosplaying, we love it.
Other plugins may export additional stats whenever the prometheus plugin is enabled โ those stats are documented in each plugin's own README, so go read those, iykyk. ๐
๐จ big one, bestie: this plugin can only be used once per Server Block. one. uno. don't push it.
๐ SYNTAX ๐
prometheus [ADDRESS] {
runtime_metrics
}
For each zone that you want to see metrics for. ๐ฏ
It optionally takes a bind address to which the metrics are exported; the default listens on localhost:9153. And again โ the metrics path is fixed to /metrics.
runtime_metricsโ exports the full Goruntime/metricsโจhttps://pkg.go.dev/runtime/metricsโฉ set, notablygo_cpu_classes_*for CPU attribution (GC mark/assist/pause vs user code) andgo_sched_latencies_secondsfor goroutine scheduling delay. Adds roughly 100 scalars and 8 histograms. ๐งฎ
โ ๏ธ heads up: this is a process-wide latch โ enabling it in any server block enables it for all of them, and it stays enabled across reloads until restart. it's not a phase, it's a lifestyle. ๐
๐ฆ EXAMPLES ๐ฆ
Use an alternative listening address, like the main character you are:
. {
prometheus localhost:9253
}
Or via an environment variable (this is supported throughout the Corefile): export PORT=9253, and then:
. {
prometheus localhost:{$PORT}
}
look at that variable interpolation go. obsessed. โจ
๐ BUGS ๐ (yes we have lore, unfortunately)
When reloading, the Prometheus handler is stopped before the new server instance is started. And if that new server fails to start? then the initial server instance is still available and DNS queries still get served, but the Prometheus handler stays down. ๐ญ Prometheus will not reply to HTTP requests until a successful reload or a complete restart of CoreDNS. so basically it's sitting there like "no thoughts, head empty" until you fix it. ๐ฅ
Also: only the plugins that register as Handler are visible in coredns_plugin_enabled{server, zone, name}. As of today the plugins reload and bind will not be reported. they're lowkey invisible. ๐
and that's the whole page, bestie, you ate. ๐
this was CoreDNS โ October 2026 โ manual page COREDNS-METRICS(7). go forth and scrape responsibly. ๐๐ง๐
๐ฆ where this page comes from
- opensuse-leap 16.0: coredns-extras 1.15.0-bp160.1.1 ยท Apache-2.0 AND MPL-2.0
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms