Skip to content

Prometheus Metrics ​

EzyShield exposes Prometheus metrics at GET /metrics on the dashboard listener (127.0.0.1:9090 by default). No new network listener is created — the metrics ride the existing loopback-only dashboard, per the project's no-new-listeners rule. The counters live in the daemon and are proxied over the control unix socket, so the dashboard process needs the daemon running to serve a scrape (503 otherwise).

Zero dependencies: the text exposition format (0.0.4) is hand-rolled — a Prometheus client library would be the largest dependency in the binary for a page of writer code.

Metrics ​

MetricTypeLabelsMeaning
ezyshield_build_infogaugeversionAlways 1; carries the build version
ezyshield_collector_lines_totalcountercollectorRaw log lines received, by collector type (filetail, journald, docker, …)
ezyshield_parser_events_totalcounterparserStructured events produced, by parser (ssh, nginx, …)
ezyshield_actions_totalcounteropDecision-engine actions (ban, dry_ban, notify_only, record, …)
ezyshield_strikes_totalcounterlevelStrikes recorded, by escalation level (1–5)
ezyshield_bans_applied_totalcounterenforcerBans successfully applied, by enforcer backend
ezyshield_ai_requests_totalcounterproviderAI analyze calls per provider
ezyshield_ai_tokens_totalcounterproviderAI tokens consumed (input+output) per provider
ezyshield_active_bansgauge—Active bans in the store at scrape time (−1 = store query failed)
ezyshield_notifications_dropped_totalgauge (cumulative)—Notification deliveries suppressed by a per-channel rate limit since start; a non-zero value during an incident means alerts were lost

Label cardinality is bounded by construction: only enumerable labels exist (collector/parser types, operation names, strike levels, enforcer and provider names). IPs, usernames, and paths can never become label values — hostile or unexpected values fold into invalid, and each family caps distinct values, folding overflow into other.

Auth ​

By default /metrics requires the dashboard session auth, like every other dashboard route. Since Prometheus cannot perform a session login, scraping normally uses:

yaml
# /etc/ezyshield/config.yaml
dashboard:
  metrics_auth: false

This allows unauthenticated scrapes and is acceptable only because the listener is loopback-only — any local process can already observe most of this information. The route is throttled either way (120 requests/min).

Scrape config ​

yaml
# prometheus.yml — Prometheus running on the same host
scrape_configs:
  - job_name: ezyshield
    scrape_interval: 30s
    static_configs:
      - targets: ["127.0.0.1:9090"]

For a remote Prometheus, do not expose the dashboard — tunnel instead (ssh -L 9090:127.0.0.1:9090 host) or run a local agent that remote-writes. The dashboard refuses non-loopback binds by design.