-
-
Notifications
You must be signed in to change notification settings - Fork 0
Recorder Report Node
flight-recorder-report — the post-mortem archiver. Wire it to any recorder output; it auto-detects what arrives and renders it human-readable, optionally landing files on disk. The classic setup: tap with auto-error on → report node with a directory → every error becomes a dated post-mortem file, automatically.
It is stateless — a pure formatter with file-landing — and produces up to two artifacts per incident:
- the report — the rendered document, to the message and/or a file
- the raw JSON evidence — the untouched incident, bit for bit, as a companion file sharing the same filename stem
| Arriving payload | Rendered as |
|---|---|
| Incident | Summary + timeline report; can be filed. |
| Query snapshot | Status report; can be filed (filename token {trigger} renders as status). |
Recorder event (envelope with recorderEvent) |
A one-line entry. Message only — never filed. |
| Anything else | A one-line "not a recorder payload" note; the original is preserved untouched. |
Because detection is automatic, "which output do I wire this to?" has a simple answer: any of them. Wiring the events output turns the report node into a readable activity log; incident copies arriving there render as full reports.
FLIGHT RECORDER INCIDENT · ERROR
store / incident / at / runtime ← identity and provenance
cause "..." from: worker [function] ← error triggers: failure front and center
47 records · span 1m 34s · median gap 2.0s
wraps 12 · truncated 0 · dropped while paused 0
SEQ +TIME GAP SOURCE PAYLOAD
...one line per record...
Timeline notation: +TIME is relative to the first record; GAP is the delta since the previous capture; gaps ≥ 3× the median are flagged ⚠ (the median is in the stats line, so the flag is interpretable); truncated records are marked ✂. Annotation marks (── MARK ──), mute boundaries (── MUTED ── / ── UNMUTED ──), and persistence restore boundaries (── RESTART ──) appear as full-width rules in sequence position — the report tells the recording's story, including its gaps. The runtime line (package/Node-RED/node versions, hostname) appears when the incident carries meta.
| Field | Default | Meaning |
|---|---|---|
| Format | text |
text (monospace-aligned — sidebar and logs), Markdown (files, chats, issues), HTML (a single self-contained file, inline styles, no external resources — opens straight from disk). |
| Send to | message |
message only, file only, or message + file. |
| Directory | (empty) | Where files land; created on demand. Required for any file output. |
| Filename | {date}_{time}_{trigger}_{storeId} |
Template; tokens below. |
| Raw JSON | off | Also save the untouched incident/snapshot as .json, paired by stem. Requires file output — the editor greys the box out otherwise, and the runtime independently enforces it. |
| Retention | 100 | Newest N incidents kept; 0 = unlimited. Prunes report + JSON as a pair, and only ever files matching this node's own template — foreign files are never touched. |
| Preview | 60 | Payload preview width in the timeline. |
{date} (2026-07-13), {time} (14-32-07 — filesystem-safe), {trigger} (manual / error / watermark / status), {storeId}, {incidentId} (short 8-char form), {format}. Incident filenames use the incident's own trigger timestamp; token values are sanitized so hostile ids can't escape the directory. Collisions get -2/-3 suffixes — an archiver never overwrites evidence.
msg.payload is the rendered document — or, in file-only mode, a confirmation line naming what was written. Everything else lives in msg.report:
{
"kind": "incident",
"format": "html",
"source": { ...the original payload, untouched... },
"files": [
{ "kind": "report", "path": "/share/.../..._error_tap1.html", "bytes": 8412, "ok": true },
{ "kind": "raw", "path": "/share/.../..._error_tap1.json", "bytes": 21033, "ok": true }
]
}Failures report per-file with a reason — a partial write (disk filled between the pair) is never invisible.
File output requested without a directory, or Raw JSON with a message-only destination: the node warns once at deploy, disables the affected output for the session, and keeps rendering to the message where possible. Configuration problems degrade; they never throw.
The sidebar truncates displayed strings at 1000 characters by default (debugMaxLength in settings.js). Reports are longer. The report itself is always complete — raise the limit, or use file output to read full reports. There's a reminder of this in the node's edit dialog.
Green incident ✓ · saved ×2 on success; red write failed when any file write fails (details in msg.report.files).
Flight Recorder
Node Reference
Reference
Guides
Testing