Local Dashboard
Run the read-only BlazeRules dashboard for inspecting rules, decisions, dead-letter records, and source health.
blazerules_dashboard is a read-only local UI for inspecting rules, decision logs, dead-letter logs, and source health. Full builds include it.
There is noblazerules dashboardsubcommandThe dashboard is a separate binary,
blazerules_dashboard. The mainblazerulesCLI has nodashboardsubcommand — runningblazerules dashboarderrors and directs you to the standaloneblazerules_dashboardbinary described here.
Build
cmake -S . -B cmake-build-release -G Ninja
cmake --build cmake-build-release --target blazerules_dashboard -jRun
./cmake-build-release/blazerules_dashboard \
--host 127.0.0.1 \
--port 9470 \
--rules rules.yaml \
--decision-log decisions.ndjson \
--dead-letter-log dead_letters.ndjson \
--results-jsonl results/stress_matrix.jsonlThere is currently no Python API such as blazerules.start_dashboard(...).
The supported interface is the standalone blazerules_dashboard executable.
Supported flags:
| Flag | Default | Purpose |
|---|---|---|
--host | 127.0.0.1 | Bind host. |
--port | 9470 | HTTP port. |
--poll-ms | 1000 | Poll interval for watched files and metrics. |
--tail-lines | 5000 | Lines retained from decision/dead-letter logs. |
--max-index-rows | 5000000 | Decision rows kept in the in-memory filter index (raise for larger logs). |
--decision-log | empty | Compact decision log — NDJSON or Arrow IPC (auto-detected). May be an s3://bucket/key object. |
--decision-log-dir | empty | Directory (or s3://bucket/prefix/) of per-instance decision logs; every *.arrow/*.ndjson under it is discovered and merged into one view. Use this instead of --decision-log for a multi-instance agent. |
--dead-letter-log | empty | Dead-letter NDJSON file. |
--aws-region | env | AWS region for s3:// sources (else AWS_REGION). |
--aws-endpoint-url | env | Custom S3 endpoint for s3:// sources (else AWS_ENDPOINT_URL). |
--metrics-url | empty | Prometheus exposition URL to scrape. |
--results-jsonl | empty | Stress benchmark JSONL file. |
--rules | empty | Active rules YAML for the visualizer (single ruleset). |
--rules-dir | empty | Directory (or s3://bucket/prefix/) of ruleset YAMLs; the Ruleset selector lists each *.yaml/*.yml stem and the visualizer scopes to the one matching the selected instance. Use instead of --rules for a multi-instance agent. |
--candidate-rules | empty | Candidate rules YAML for validation/diff. |
--rules-history-dir | empty | Directory of YAML versions. |
The dashboard is read-only and unauthenticatedIt ships with no authentication. Bind it to
127.0.0.1(localhost) and never expose it directly to a network. If you need remote access, put it behind your own authenticated proxy or tunnel.
Fast decision filtering
As it tails the decision log, the dashboard builds a compact in-memory columnar index (dictionary-encoded decision, risk band, and winning rule, plus timestamp and score). The Event Timeline filters — by decision, risk band, winning rule, and time range — run as a vectorized scan over that index, so filtering stays in the tens of milliseconds even across millions of rows instead of re-reading the log file per query. The index keeps the most recent --max-index-rows decisions (default 5,000,000); raise it to cover larger logs, and the /api/decisions response reports indexed_rows and truncated so you can tell when the cap is in effect.
The decision log can be NDJSON or the binary Arrow IPC stream written by blazerules_agent --output arrow; the format is auto-detected and both feed the same index, so an Arrow log filters just as fast while taking far less disk.
When the dashboard watches a directory, it also reads the agent's .stats
sidecar files next to each decision output. Those sidecars provide input rate,
input bytes/sec, evaluated rows/sec, output bytes/sec, and skipped-row counters
without scanning a large decision log on every poll. If the directory is emptied
between runs, the dashboard drops the old rows and source stats on the next poll.
Multiple rulesets (instances)
Every decision row carries the instance name and ruleset_version that produced it. When you run a multi-instance agent — several rulesets in one process, each writing its own decision log — point the dashboard at the directory instead of a single file:
./cmake-build-release/blazerules_dashboard --decision-log-dir logs/ --rules rules.yamlThe dashboard discovers every *.arrow/*.ndjson in the directory (mixed formats are fine), tags each row with its instance, and merges them into the same fast index. New instance logs that appear later are picked up automatically. Dead-letter files (names containing dlq / dead_letter) are skipped, so they never show up as an instance.
A Ruleset selector in the header scopes the whole console — Overview counts and decision distribution, Event Timeline, Rule fire rates, and the Models page — to one instance/ruleset, or All. With a multi-instance agent this is an A/B view: flip between rulesets to compare their decision mix and model-prediction distributions. The Overview also carries an Instances / Rulesets breakdown of record counts.
--decision-log-dir (and --decision-log) also accept an s3:// location. When the agent writes rolled part objects to an S3 prefix (--output-path s3://…/prefix/), point the dashboard at that prefix and it syncs new parts to a local cache each poll before indexing them — so a fully stateless deployment (agent → S3 → dashboard) needs no shared local volume. See the S3 recipe and CLI Agent for the writer side.
Per-instance rules for the visualizer
--rules PATH loads a single ruleset into the Ruleset Visualizer. To browse several rulesets from one dashboard, pass --rules-dir DIR instead — a local directory, or an s3://bucket/prefix/ that is synced to a local cache each poll. The Ruleset selector is then populated from the *.yaml/*.yml file stems in that directory, so it lists every ruleset and works even before any decisions arrive. Selecting a ruleset scopes both the visualizer and the per-instance Overview, Event Timeline, and Models panels to it.
Name each ruleset file to match its agent instance's --name — checkout.yaml for --name checkout — so a single selection drives both the decision view (from --decision-log-dir) and the rule view (from --rules-dir) for that instance.
Models page
When the agent is run with one or more ONNX models (--model name=path) and rules that use model_score, it writes each model's raw prediction into the decision log (a model.<name> column in Arrow, or a model_scores object in NDJSON). The dashboard's Models page reads those and shows, per model channel:
- a prediction-distribution histogram — probabilities in
[0,1]for a classification model, continuous values for a regression model — computed server-side over the whole filter index (/api/models); - summary stats (count, min, mean, max);
- a filterable per-record prediction table joining each record's decision with its model outputs.
The page scales to any number of models (one panel per channel) and shares the Instance filter, so you can inspect a single ruleset's model behavior in isolation.
HTTP endpoints
The dashboard serves a single-page UI at / and backs it with read-only JSON endpoints you can also query directly (for example with curl) — handy for scripting or embedding panels elsewhere. All are GET and return JSON.
| Endpoint | Returns |
|---|---|
/api/health | Liveness plus which sources (decision log, dead-letter, metrics, rules) are configured. |
/api/summary?instance= | Aggregate counts + decision/risk distribution; scoped to one instance when instance is set. |
/api/metrics | Latest values scraped from --metrics-url (empty if unset). |
/api/decisions?limit=N | Most recent decision records; accepts decision, risk_band, instance, rule, from_ms, to_ms filters and returns per-row instance and model_scores. |
/api/models?bins=N&instance= | Per-model prediction histogram (bins + count/min/mean/max) over the filter index, optionally scoped to one instance. |
/api/errors?limit=N | Most recent dead-letter/error records (from --dead-letter-log). |
/api/rules?limit=N&instance= | Per-rule fired/winning totals; winning totals scope to one instance when instance is set. |
/api/ruleset | Ruleset metadata (name, version, decision precedence). |
/api/benchmarks | Stress-benchmark rows from --results-jsonl (empty if unset). |
These endpoints are read-only and unauthenticated, so the same trusted-network guidance above applies.
Where to go next
Updated 3 days ago