Documentation → Monitoring

Monitoring

BoronDNS exposes health probes and a Prometheus-compatible /metrics endpoint on its management HTTP listener. All endpoints are plain HTTP/1.1, unauthenticated by default, and intended for private management networks or an orchestrator-side proxy.

Management HTTP listener

Configure the listener in your config:

[interfaces.mgmt]
bind_address = "127.0.0.1"
port = 8080

[health]
metrics_enabled = true

Health probes

PathSuccessFailureNotes
/livez200(no response or 5xx)Alive while zones are loading and during graceful shutdown
/readyz200503Ready when ≥ 1 zone is ACTIVE and the process is not draining
/healthz200503Alias for /readyz

These endpoints are never rate-limited.

/livez response

{"status":"alive","version":"0.2.0","uptime_seconds":12345}

/readyz responses

Ready:

{"status":"ready","version":"0.2.0","zones_active":5,"zones_loading":0,"zones_expired":0}

Not ready (zones still loading):

{"status":"not-ready","reason":"loading","version":"0.2.0","zones_active":0,"zones_loading":3,"zones_expired":0}

Draining (graceful shutdown in progress):

{"status":"draining","version":"0.2.0","grace_period_remaining_seconds":15}

Prometheus metrics

/metrics emits standard Prometheus text exposition (text/plain; version=0.0.4). The endpoint supports gzip compression when requested.

Scrape configuration:

scrape_configs:
  - job_name: borondns
    static_configs:
      - targets: ['localhost:8080']
    scrape_interval: 15s
    metrics_path: /metrics

Available metric families

Zone state (per-zone gauges):

MetricTypeDescription
borondns_secondary_zone_state{zone="...",state="active|loading|expired"}gauge1 if zone is in this state
borondns_secondary_zone_soa_serial{zone="..."}gaugeCurrent served SOA serial
borondns_secondary_zone_last_refresh_seconds{zone="..."}gaugeSeconds since last successful transfer
borondns_secondary_zone_next_refresh_seconds{zone="..."}gaugeSeconds until next scheduled refresh
borondns_secondary_zone_refresh_failures{zone="..."}counterTransfer failure count since startup
borondns_secondary_zone_loading_seconds{zone="..."}gaugeSeconds the zone has been in LOADING state

Query counters:

MetricTypeDescription
borondns_secondary_queries_total{zone="..."}counterAuthoritative queries answered per zone
borondns_transfer_sessions_started_totalcounterTotal AXFR/IXFR sessions started
borondns_transfer_sessions_completed_totalcounterTotal sessions completed successfully

Catalog zones (when RFC 9432 catalog zones are configured):

MetricTypeDescription
borondns_catalog_member_info{catalog_zone="...",zone="...",managed="..."}gaugeCatalog membership indicator
groups:
  - name: borondns
    rules:
      - alert: BoronDNSZoneExpired
        expr: borondns_secondary_zone_state{state="expired"} == 1
        for: 0m
        labels:
          severity: critical
        annotations:
          summary: "Zone {{ $labels.zone }} has expired"
          description: "BoronDNS cannot reach the primary and SOA expire time has passed."

      - alert: BoronDNSZoneStale
        expr: borondns_secondary_zone_last_refresh_seconds > 3600
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Zone {{ $labels.zone }} has not refreshed in over 1 hour"

      - alert: BoronDNSDown
        expr: up{job="borondns"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "BoronDNS instance {{ $labels.instance }} is unreachable"

Structured logs

Set format = "json" in [log] to emit structured log lines:

{"timestamp":"2026-06-15T10:23:01.452Z","level":"info","message":"zone transfer complete","zone":"example.com.","type":"IXFR","records_changed":3,"duration_ms":42}
{"timestamp":"2026-06-15T10:24:00.001Z","level":"warn","message":"zone refresh failed","zone":"old.example.org.","error":"connection refused","retry_in":"10s"}

Observability API

BoronDNS optionally exposes a richer JSON observability API for management-network consumers. Enable it with:

[observability]
enabled = true
path_prefix = "/observability/v1"

Key endpoints include:

PathDescription
/observability/v1/summaryOne-page runtime, zone, transfer, and security summary
/observability/v1/zonesPer-zone state, serial, refresh, and transfer details
/observability/v1/transfersCurrent and recent transfer session state
/observability/v1/securityTSIG, NOTIFY, RRL, and DNS Cookie counters
/observability/v1/runtimeProcess uptime, version, worker mode, and drain state
/observability/v1/resourcesCoarse memory, CPU, file-descriptor, and filesystem view

All observability endpoints are GET-only, rate-limited (default: 60 req/min per source), and must not be exposed on the public DNS listener address. For deployments where the management listener is reachable beyond localhost, set a bearer token:

[observability]
enabled = true
bearer_token_file = "/etc/borondns-secondary/observability.token"

Secrets (TSIG values, private keys, tokens) are never returned by any observability endpoint.