Recipe: Decision And DLQ Logs
Configure decision output, bad-record handling, and dashboard log inspection.
Decision logs are compact records for downstream routing. Dead-letter logs keep bad input out of the hot path while preserving samples for debugging.
Python Engine Logs
import blazerules
cfg = blazerules.EngineConfig()
cfg.output_detail = blazerules.OutputDetail.DECISIONS
cfg.decision_log_path = "decisions.ndjson"
cfg.ingest_error_mode = blazerules.IngestErrorMode.SKIP_TO_DEAD_LETTER
cfg.dead_letter_path = "dead_letters.ndjson"
engine = blazerules.RuleEngine(cfg)
engine.load_rules("rules.yaml")
result = engine.evaluate_ndjson(payload)CLI equivalent: write compact decisions with the agent
blazerules_agent \
--rules rules.yaml \
--input stdin \
--output ndjson \
--output-path decisions.ndjsonThe agent writes compact decisions. Engine-level dead-letter policy is configured through EngineConfig in Python/C++.
Agent Output
blazerules_agent \
--rules rules.yaml \
--input stdin \
--output ndjson \
--output-path decisions.ndjsonPython equivalent: evaluate a batch and write decisions yourself
import json
import time
import blazerules
engine = blazerules.RuleEngine()
engine.load_rules("rules.yaml")
result = engine.evaluate_ndjson(payload)
with open("decisions.ndjson", "a", encoding="utf-8") as out:
ts_ms = int(time.time() * 1000)
for row, decision in enumerate(result.decisions):
out.write(json.dumps({
"ts_ms": ts_ms,
"batch_row": row,
"decision": decision,
"score": result.scores[row],
"risk_band": result.risk_bands[row],
"winning_rule_id": result.winning_rule_ids[row],
}) + "\n")The agent writes one decision per evaluated row:
{"ts_ms":1782150000000,"service":"checkout","source":"stdin","batch_row":12,"decision":"BLOCK","score":91.0,"risk_band":"HIGH","winning_rule_id":"blocked_device"}Dead-Letter Mode
Use dead-letter mode when bad records should be inspectable instead of silently counted:
cfg.ingest_error_mode = blazerules.IngestErrorMode.SKIP_TO_DEAD_LETTER
cfg.dead_letter_path = "dead_letters.ndjson"CLI equivalent: inspect dead-letter output with the dashboard
blazerules_dashboard \
--decision-log decisions.ndjson \
--dead-letter-log dead_letters.ndjson \
--host 127.0.0.1 \
--port 9470The result still reports counters:
print(result.messages_processed)
print(result.messages_skipped)
print(result.error_counts)
print(result.error_samples)Dashboard
blazerules_dashboard \
--decision-log decisions.ndjson \
--dead-letter-log dead_letters.ndjson \
--rules rules.yaml \
--host 127.0.0.1 \
--port 9470Python equivalent: start the dashboard process
import subprocess
subprocess.Popen([
"blazerules_dashboard",
"--decision-log", "decisions.ndjson",
"--dead-letter-log", "dead_letters.ndjson",
"--rules", "rules.yaml",
"--host", "127.0.0.1",
"--port", "9470",
])Open http://127.0.0.1:9470.