IT

Metriche e log

Work in progress — content may be incomplete.

Tre segnali sul daemon, tre posti dove guardare — /metrics per i numeri, il query log per chi-ha-chiesto-cosa, l’audit log per chi-ha-cambiato-cosa.

Cos’è

Warden espone visibilità day-2 attraverso tre superfici indipendenti. Nessuna è attiva di default — ognuna è opt-in tramite la config TOML, di proposito, così un’installazione appena fatta non fa altro che rispondere a DNS.

Questa pagina è la mappa: quale superficie risponde a quale domanda, come attivare ognuna, e cosa fare scrape o tail per tirare fuori un segnale utile dall’altra parte. L’endpoint Prometheus riceve il trattamento più approfondito qui perché non ha una pagina dedicata altrove; i due log hanno ciascuno il proprio approfondimento (linkato in fondo).

Le tre superfici

SuperficieFormatoRisponde aDove vive
Prometheus /metricsTesto OpenMetrics su HTTP(S)“Come sta andando il daemon adesso?” Counter, gauge, rapporti.Stesso server [api] di /healthz e /api/*.
Query logJSONL, una riga per query risolta“Cosa ha chiesto il client X, e cosa ha risposto Warden?”File con rotazione [query_log]. Vedi query log.
Audit logJSONL via tracing, target = "audit"“Chi ha cambiato quale profilo / blocklist / dispositivo, e quando?”Journald + mirror [audit_log]. Vedi audit log.

Sono indipendenti. Puoi tenere Prometheus senza il query log, o entrambi i log senza l’endpoint metriche. La maggior parte degli operatori alla fine vuole Prometheus per “la scatola è sana?” e il query log per “perché quel dominio è stato bloccato?”; l’audit log serve soprattutto quando più di una persona edita la config.

Abilitare Prometheus

L’endpoint /metrics è chiuso a tempo di registrazione delle route — quando metrics_enabled = false la route non viene proprio registrata (ricevi un 404 dal fallback, non da un handler disabilitato). Evita di esporre una superficie di enumerazione su un daemon che non era pensato per essere scrappato.

Due chiavi TOML lo controllano:

/etc/purge-warden/config.toml
toml
[api]
enabled         = true              # obbligatorio — accende il server HTTP
metrics_enabled = true              # obbligatorio — registra la route /metrics
listen          = "127.0.0.1:8053"  # default — solo loopback

Entrambi devono essere true. enabled controlla l’intero server [api] (da cui dipendono anche /healthz e /api/*). metrics_enabled è l’interruttore per-route specifico di /metrics.

Dopo aver salvato, fai sudo warden reload per caricare la nuova config. Conferma con:

curl -s http://127.0.0.1:8053/metrics | head

Un’attivazione riuscita produce un body che inizia con # HELP purge_shield_uptime_seconds …. Un 404 significa o che il daemon non si è ricaricato o che una delle due chiavi è ancora false.

Nessuna scorciatoia CLI
Non esiste un sottocomando warden metrics enable. Il blocco [api] è config a livello di daemon e si edita direttamente. Sorgente: src/config/settings.rs:1213-1219.

L’endpoint

ProprietàValoreSorgente
Path/metricssrc/api/routes.rs:71
MetodoSolo GETsrc/api/routes.rs:69-72
BindDefault 127.0.0.1:8053, condiviso con /healthz e /api/*src/config/settings.rs:136-138
Content-Typetext/plain; version=0.0.4; charset=utf-8src/api/handlers.rs:1202
AutenticazioneNessuna/metrics è montato in public_routes, fuori dal middleware del bearer tokensrc/api/routes.rs:69-72
Rate limitNessuno su questa route (il [api] rate_limit_per_minute si applica solo a /api/*)
TLSObbligatorio quando listen è bound su un indirizzo non-loopback (il validator rifiuta altrimenti)src/config/settings.rs:1234, 1241

L’endpoint è OpenMetrics text scritto a mano, non la crate prometheus. Il compromesso è zero dipendenze extra e zero label / histogram — ogni metrica è uno scalare.

Riferimento metriche

Ogni metrica esposta da Warden oggi. Nessuna label su nessuna serie.

MetricaTipoSignificato
purge_shield_uptime_secondsgaugeSecondi dall’avvio del daemon.
purge_shield_domains_loadedgaugeDomini attualmente caricati nel motore di filtro (somma su tutte le blocklist attive + admin rule).
purge_shield_cache_entriesgaugeVoci vive nella cache delle risposte (moka).
purge_shield_queries_totalcounterQuery DNS totali viste dal daemon.
purge_shield_blocked_totalcounterQuery totali negate dal filtro.
purge_shield_cache_hits_totalcounterHit di cache totali (risposta servita senza andare upstream).
purge_shield_refused_acl_totalcounterQuery totali rifiutate dall’ACL allow_from (IP client non autorizzato).
purge_shield_blocked_ratiogaugeblocked / queries, calcolato a tempo di scrape.
purge_shield_cache_hit_ratiogaugecache_hits / queries, calcolato a tempo di scrape.
purge_shield_tracked_devicesgaugeNumero di dispositivi attualmente tracciati nella tabella runtime.
purge_shield_tracked_clientsgaugeAlias legacy di tracked_devices, in dismissione una release più avanti.
Counter e rapporti richiedono il motore stats
I counter, i due rapporti e tracked_devices / tracked_clients vengono emessi solo quando il motore di stats / tracking dispositivi è inizializzato. Senza tracking, appaiono solo uptime_seconds, domains_loaded e cache_entries. Il tracking è attivo di default nelle installazioni standard; se hai una config minimal senza, aspettati un body di /metrics più corto.

Sorgente: src/api/handlers.rs:1124-1206.

Scraping

Job Prometheus minimale per un daemon sullo stesso host:

/etc/prometheus/prometheus.yml
yaml
scrape_configs:
  - job_name: purge_shield
    metrics_path: /metrics
    scheme: http
    static_configs:
      - targets: ["127.0.0.1:8053"]

Per uno scraper remoto, esponi l’endpoint su TLS:

/etc/purge-warden/config.toml
toml
[api]
enabled         = true
metrics_enabled = true
listen          = "10.0.0.20:8053"
tls_cert        = "/etc/purge-warden/tls/api.crt"
tls_key         = "/etc/purge-warden/tls/api.key"

Il validator rifiuta un listen non-loopback senza entrambi tls_cert e tls_key. Il materiale TLS copre /healthz, /metrics e /api/* con lo stesso certificato.

Un intervallo di scrape di 15 secondi è ampio — la maggior parte delle serie si muove su tempi di secondi-minuti, non sotto-secondo.

Dashboard Grafana

Nessuna dashboard viaggia con Warden oggi. Non esiste un dashboards/*.json nel repository upstream. Un set di pannelli ragionevole per partire:

  • Riga in alto (panoramica): uptime, query totali al secondo (rate), rapporto bloccate, rapporto cache hit.
  • Salute del filtro: purge_shield_domains_loaded (gauge), rate al minuto di purge_shield_blocked_total, rate al minuto di purge_shield_refused_acl_total.
  • Cache: purge_shield_cache_entries, rate di purge_shield_cache_hits_total.
  • Topologia: purge_shield_tracked_devices.

Frammenti PromQL utili:

# Query al secondo nell'ultimo minuto
rate(purge_shield_queries_total[1m])

# Tasso di blocchi al minuto
rate(purge_shield_blocked_total[1m]) * 60

# Rapporto bloccate in tempo reale (usa il gauge precalcolato)
purge_shield_blocked_ratio

Una dashboard JSON contribuita dalla community sarebbe benvenuta — apri una issue se vuoi pubblicarne una.

Sicurezza dell’endpoint metriche

Un endpoint /metrics su un resolver DNS rivela quanto è carico, quanti client serve, quanto blocca e cosa cachea. Tratta il body come telemetria operativa sensibile.

  • Default listen = "127.0.0.1:8053". Solo loopback può fare scrape. Un Prometheus sullo stesso host funziona; tutto il resto richiede una modifica deliberata della config.
  • Nessun bearer token su /metrics. Il middleware bearer-token avvolge solo /api/*/metrics sta in public_routes accanto a /healthz. Se fai bind dell’API su un indirizzo non-loopback, ogni scraper dentro il confine di fiducia TLS può leggere il body.
  • Il validator impone TLS fuori dal loopback. Fare bind di [api] listen su 0.0.0.0:8053 o un IP LAN senza tls_cert / tls_key viene rifiutato. Il compromesso è “TLS sì, auth no” — accettabile per un Prometheus dietro il tuo perimetro, non accettabile per un bind su internet pubblico.
  • Se ti serve auth. Oggi: reverse-proxy /metrics dietro nginx / caddy / Traefik con basic auth o mTLS. Lega l’[api] di Warden al solo loopback e lascia che il proxy ascolti verso l’esterno. Roadmap: gating opzionale via bearer token su /metrics allineato con /api/*.

Sorgente: src/api/routes.rs:32-82, src/api/server.rs:21.

Log

Questa pagina copre le metriche in profondità; le due superfici di log hanno ciascuna la propria pagina.

  • Query log — una riga JSONL per query DNS risolta con client_ip, client_name, dominio chiesto, RCODE, nome del profilo risolto e (dove applicabile) quale regola ha attivato. Ruotato e tappato via [query_log]. L’indirizzo MAC non è mai registrato. Vedi query log per schema, rotazione, e warden log tail.
  • Audit log — eventi tracing::info!(target = "audit", action = "...") emessi su ogni chiamata CLI / API che modifica la config. Esempi: profile.blocklists.add, profile.blocklists.remove, rule.add, rule.undo. Mirroring su file via [audit_log]. Ispeziona con warden audit tail [-n N]. Vedi audit log.

Entrambi i log sono off di default (enabled = false) — opt-in come /metrics.

Risoluzione problemi

curl /metrics restituisce 404.

Causa più comune: metrics_enabled = false (la route non è davvero registrata). Controlla:

grep -A 5 '^\[api\]' /etc/purge-warden/config.toml
# Devono essere presenti sia enabled = true SIA metrics_enabled = true.

journalctl -u purge-warden -n 30 --no-pager | grep -i 'api\|listen\|metrics'
# Conferma che il server abbia fatto bind e quali route sono live.

Se entrambi i flag sono true ma il body manca lo stesso, può darsi che il daemon non si sia ricaricato dopo l’edit — sudo warden reload, poi controlla il timestamp nel journal.

Il body ha solo tre righe (uptime_seconds, domains_loaded, cache_entries).

Il motore di stats non è inizializzato nella config di questo daemon. Counter e rapporti richiedono il tracking a runtime. Controlla la sezione di tracking dispositivi nella config; per la maggior parte delle installazioni è attivo automaticamente.

Prometheus riporta up == 0 anche se curl dall’host funziona.

Lo scraper è su un host diverso dal daemon e il bind è 127.0.0.1. O sposta lo scraper su localhost o ribinda il daemon su un indirizzo raggiungibile con TLS (vedi scraping sopra).

warden reload va bene ma il body di /metrics mostra ancora i vecchi gauge.

Alcuni gauge (uptime_seconds, domains_loaded) si aggiornano al prossimo scrape; i counter non si resettano sul reload, di proposito — i counter totali continuano a girare fra i reload così le dashboard basate su derivate restano coerenti. Se ti serve un reset, riavvia il daemon: sudo systemctl restart purge-warden.

Il Content-Type di /metrics è text/plain; version=0.0.4 — è giusto?

Sì. È la versione del testo OpenMetrics che parla Warden. Sia Prometheus sia Grafana moderno lo ingeriscono senza configurazione.

Per diagnosi più ampia, vedi risoluzione problemi.

Vedi anche