Skip to content

Reports and Archiving

mchristegh edited this page Jul 14, 2026 · 1 revision

The report node reference covers the configuration surface; this page is the working guide — how to read reports well, and how to run a report directory as a proper post-mortem archive.

Reading a report like an investigator

A report is built to tell the recording's story, not just list it. The pieces, in the order your eye should use them:

The header states the trigger loudly. MANUAL means someone asked; ERROR and WATERMARK mean the recorder decided. For error incidents the cause block sits directly under the header — the error message and which node reported it — because that's the question you came with.

The stats line defines "normal". 47 records · span 1m 34s · median gap 2.0s — the median gap is the recording's heartbeat, and it's printed precisely so the timeline's flags are interpretable: a flag means this gap was at least 3× that number. On a steady 2-second flow, a flagged 8.0s gap is three missing beats — often the real story of an incident, especially with sources that swallow messages on failure.

The timeline's rule lines are narrative events, not records: ── MARK ── is an annotation someone laid deliberately ("about to test X"); ── MUTED ──/── UNMUTED ── bound a deliberately silenced window (the unmute rule carries how much was suppressed); ── RESTART ── marks a persistence restore boundary — everything above it predates a restart, and the first gap after it is the downtime, honestly stated.

means summary, not loss of the record. A scissored row exceeded the byte cap; its preview comes from the summary form, and payloadBytes in the raw JSON still tells you the original size.

Choosing formats and destinations

text is monospace-aligned for the debug sidebar and log files — the development-time default. Remember the sidebar's own 1000-character display cap (debugMaxLength in settings.js); the report is complete regardless. Markdown pastes cleanly into issues, chats, and docs. HTML is the post-mortem artifact: a single self-contained file (inline styles, no external resources) that opens straight from disk or a Samba share, anomaly rows tinted, months later, on any machine.

Destinations compose with formats freely; message + file is the common working setup — sidebar visibility while developing, archive accumulating regardless.

Running an evidence directory

The pattern this node was built for: tap (auto-error on) → report node (file or both, HTML, Raw JSON on) → a directory. Every error becomes a dated, readable post-mortem with its bit-for-bit evidence beside it:

2026-07-13_14-32-07_error_tap1.html   ← the readable story
2026-07-13_14-32-07_error_tap1.json   ← the untouched incident

The pairing is the point. The HTML answers "what happened?"; the JSON answers "prove it" — feed it to jq, pandas, or your own tooling, re-derive anything the report summarized. The stems always match, collisions get -2/-3 suffixes (evidence is never overwritten), and retention prunes by pair — a report never orphans its evidence or vice versa.

Practical settings for a long-running archive:

  • Retention sized to your incident rate, not disk size: 100 pairs of a typical incident is a few megabytes. The real reason retention exists is pathological cases — a misconfigured cooldown plus an error loop should hit a ceiling, not a full disk.
  • Cooldown ≥ 30–60s on any tap feeding an archive. Repeated identical incidents seconds apart add files, not information.
  • Filename template: the default sorts chronologically in any file browser. Add {incidentId} if you need guaranteed-unique stems for external tooling.
  • Retention only ever touches files matching the node's own template pattern — the directory can safely be shared with other content, though a dedicated directory is tidier.

Home Assistant hosts: use /share/flight-recorder/reports — it persists across add-on updates and is exposed by the Samba/SSH add-ons, so HTML reports open from your PC over the network. Details and the notification pairing on the Home Assistant page.

Periodic status reports

Snapshots file too: an inject on a schedule → control node (query) → the recorder's query output → a report node with file output gives you a dated status report ({trigger} renders as status) — state, counters, config, active mutes — on whatever cadence you like. With Raw JSON on, the snapshot archives beside it, giving you a machine-readable health history for free.

One report, many consumers

The report node is stateless, so fan out freely from one recorder output: one report node archiving HTML+JSON pairs, a second rendering text to the sidebar, a third feeding Markdown into a notification flow — same incident, three presentations, no interference. The original payload always survives at msg.report.source, so downstream nodes can still reach the raw incident after any rendering.

Clone this wiki locally