Metriche e log
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
| Superficie | Formato | Risponde a | Dove vive |
|---|---|---|---|
Prometheus /metrics | Testo OpenMetrics su HTTP(S) | “Come sta andando il daemon adesso?” Counter, gauge, rapporti. | Stesso server [api] di /healthz e /api/*. |
| Query log | JSONL, 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 log | JSONL 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:
[api]
enabled = true # obbligatorio — accende il server HTTP
metrics_enabled = true # obbligatorio — registra la route /metrics
listen = "127.0.0.1:8053" # default — solo loopbackEntrambi 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.
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à | Valore | Sorgente |
|---|---|---|
| Path | /metrics | src/api/routes.rs:71 |
| Metodo | Solo GET | src/api/routes.rs:69-72 |
| Bind | Default 127.0.0.1:8053, condiviso con /healthz e /api/* | src/config/settings.rs:136-138 |
| Content-Type | text/plain; version=0.0.4; charset=utf-8 | src/api/handlers.rs:1202 |
| Autenticazione | Nessuna — /metrics è montato in public_routes, fuori dal middleware del bearer token | src/api/routes.rs:69-72 |
| Rate limit | Nessuno su questa route (il [api] rate_limit_per_minute si applica solo a /api/*) | — |
| TLS | Obbligatorio 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.
| Metrica | Tipo | Significato |
|---|---|---|
purge_shield_uptime_seconds | gauge | Secondi dall’avvio del daemon. |
purge_shield_domains_loaded | gauge | Domini attualmente caricati nel motore di filtro (somma su tutte le blocklist attive + admin rule). |
purge_shield_cache_entries | gauge | Voci vive nella cache delle risposte (moka). |
purge_shield_queries_total | counter | Query DNS totali viste dal daemon. |
purge_shield_blocked_total | counter | Query totali negate dal filtro. |
purge_shield_cache_hits_total | counter | Hit di cache totali (risposta servita senza andare upstream). |
purge_shield_refused_acl_total | counter | Query totali rifiutate dall’ACL allow_from (IP client non autorizzato). |
purge_shield_blocked_ratio | gauge | blocked / queries, calcolato a tempo di scrape. |
purge_shield_cache_hit_ratio | gauge | cache_hits / queries, calcolato a tempo di scrape. |
purge_shield_tracked_devices | gauge | Numero di dispositivi attualmente tracciati nella tabella runtime. |
purge_shield_tracked_clients | gauge | Alias legacy di tracked_devices, in dismissione una release più avanti. |
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:
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:
[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 dipurge_shield_blocked_total, rate al minuto dipurge_shield_refused_acl_total. - Cache:
purge_shield_cache_entries, rate dipurge_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/*—/metricssta inpublic_routesaccanto 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] listensu0.0.0.0:8053o un IP LAN senzatls_cert/tls_keyviene 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
/metricsdietro 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/metricsallineato 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, ewarden 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 conwarden 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
- Query log — JSONL per-query.
- Audit log — traccia di audit dei cambi di config.
- Dashboard TUI — vista interattiva degli stessi counter, utile via SSH.
- Impostazioni globali — dove vive
[api]accanto a[server]e affini. - Schema TOML — ogni campo, ogni vincolo.