Prometheus Metrics¶
When api.metrics_enabled is on (the default), Bindizr serves Prometheus
text-format metrics at GET /metrics. Like /health, the endpoint is
unauthenticated — it exposes only aggregate counters and gauges, never zone data
— and it is not part of the OpenAPI spec.
| Metric | Type | Description |
|---|---|---|
bindizr_build_info{version} |
gauge | Build metadata; the value is always 1 |
bindizr_started_at_seconds |
gauge | Unix time the process started |
bindizr_database_up |
gauge | Whether this scrape's database probe succeeded (3 s timeout) |
bindizr_db_connections{state} |
gauge | Pooled database connections by state (idle/in_use); in_use reaching the max is the saturation every request then queues behind |
bindizr_db_connections_max |
gauge | Connection ceiling the pool was built with, scaled to the host's cores |
bindizr_zones_total, bindizr_records_total |
gauge | Zone / record counts, refreshed at scrape time |
bindizr_http_requests_total{method, route, status} |
counter | HTTP API requests, labeled by route pattern |
bindizr_http_request_duration_seconds{method, route} |
histogram | HTTP API request latency |
bindizr_xfr_total{type, result} |
counter | AXFR/IXFR requests served, by query type and outcome; a UDP request (TC set, or an IXFR's SOA alone) counts as truncated, since the transfer itself follows over TCP |
bindizr_soa_queries_total{result} |
counter | SOA queries answered, by outcome; secondaries poll these on their refresh timer, so a rise in refused means one stopped being an enabled secondary |
bindizr_notify_sent_total{result} |
counter | NOTIFY delivery attempts to secondaries, by outcome |
bindizr_nsupdate_requests_total{result} |
counter | RFC 2136 dynamic updates, by outcome |
bindizr_pruned_rows_total{table} |
counter | History rows pruned by table (journal/version); zero is expected until rows exceed the retention period |
bindizr_zone_serial_bumps_total |
counter | Zone serial writes across every update path |
bindizr_dnssec_zones_total |
gauge | DNSSEC-signed zones, refreshed at scrape time |
bindizr_dnssec_keys_total{state} |
gauge | DNSSEC keys by state (published/active/retired) |
bindizr_dnssec_rrsigs_expiring_total |
gauge | Signatures inside the refresh window; persisting across scrapes means re-signing is falling behind |
bindizr_dnssec_rrsigs_expired_total |
gauge | Signatures already past their expiration; any at all mean resolvers are failing part of a zone |
bindizr_dnssec_scheduler_runs_total{result} |
counter | DNSSEC scheduler passes by outcome; interval set by dns.scheduler_interval_secs |
bindizr_zone_cache_lookups_total{result} |
counter | Transfer-cache reads by outcome; a low hit ratio means transfers reach the database anyway |
bindizr_zone_cache_evictions_total |
counter | Zones dropped to make room; rising beside a low hit ratio means dns.transfer_cache.max_records is too small |
bindizr_zone_cache_records |
gauge | Records the transfer cache holds, against dns.transfer_cache.max_records |
Example Prometheus scrape configuration:
Set metrics_enabled = false in the [api] section (or
BINDIZR_API_METRICS_ENABLED=false) to disable the endpoint.
A ready-to-run Prometheus + Grafana stack with a pre-provisioned dashboard lives in examples/monitoring/.