Prometheus exposition

GET /metrics                                      metrics_scraper scope

Standard Prometheus text exposition, served on the same HTTPS listener as the
rest of the API — not a sidecar and not a separate port. The handler performs no
polling; it renders values the sampler has already set on its own tick, so a
scrape costs nothing beyond serialisation.

It is authenticated. The scrape credential is an ordinary API key from the
same store, subject to the same middleware, the same audit trail, and the same
revocation control. That was chosen specifically so that revoking a scrape
credential works exactly like revoking any other, rather than requiring a second
authentication surface. The credential is constrained to the metrics_scraper
role with a path scope of /metrics, carries no expiry, and is exempt from rate
limiting.

Successful scrapes deliberately do not emit a key-usage audit event — at a
fifteen-second interval that would be nearly six thousand events per box per day
and would drown real signal. Failed scrapes do emit, and increment a failure
counter, so a revoked or rotated credential surfaces on the security health
indicator within one scrape interval.

The published families:

Metric Type Labels
bng_qos_bytes_total Counter direction={up,down}, band={green,yellow,red}
bng_qos_packets_total Counter direction, band
bng_throughput_bps Gauge direction, band
bng_throughput_pps Gauge direction
bng_sessions_active Gauge state={connected,captive,offering}
bng_reply_path_stalled Gauge
bng_reply_path_rx_pps, bng_reply_path_tx_pps Gauge
bng_radius_reachable Gauge server={auth,acct}
bng_uplink_bytes_total, bng_uplink_packets_total Counter port, direction={rx,tx}
bng_uplink_drops_total Counter port, direction, reason={miss,error}
bng_access_bytes_total, bng_access_drops_total Counter port, direction[, reason]
bng_metric_baseline_reset_total Counter family

Alongside these, the platform publishes an authentication and security family:
active sessions, users by role, disabled and MFA-enrolled user counts, API keys
by kind, expired and near-expiry key counts, locked accounts, certificate days
remaining, webhook queue depth, and audit-shipping spool and liveness gauges —
plus counters for login success and failure by reason, session expiry by cause,
ACME renewal outcomes, webhook deliveries, and audit-shipping throughput.

Two conventions in that family are worth knowing. auth_cert_days_remaining
returns a sentinel of -9999 when no certificate is installed, so a dashboard
can distinguish "missing" from "expires today". And auth_api_keys_total emits a
synthetic zero-valued series on a fresh box so the metric family always exists
and recording rules do not break against an absent series.

These collectors re-read on-disk state fresh on every scrape — there is no
staleness window and no cache.