Skip to content

Recorder Node

mchristegh edited this page Jul 14, 2026 · 1 revision

flight-recorder — an inline recorder you drop onto a wire. Every message that arrives is captured onto the tape and forwarded untouched.

Guarantees

Passthrough is sacred. Output 1 carries the original message object — same reference, unmodified, always. No capture problem (oversized payload, circular structure, encoding failure, disk error) may ever block or alter it. Pausing the recorder stops the tape, never the flow.

The input carries traffic only. This node accepts no commands in-band — a wire carrying arbitrary traffic must never be ambiguous about what's a command. All commands arrive through a control node targeting this recorder.

Ports

Port Carries
Input Traffic. Passes through untouched.
Output 1 — passthrough The original message. Nothing else, ever.
Output 2 — incidents Incident objects: manual dumps and watermark hits.
Output 3 — query Status snapshots in response to query commands.
Output 4 — events Everything, tagged with msg.recorderEvent: incident copies, marks, wraps, pause/resume, persistence results, truncation warnings, command acknowledgements.

All non-passthrough outputs use the standard envelope: { topic, recorderEvent, recorderState, storeId, payload } — see Data Formats.

Configuration

Field Default Meaning
Capacity 100 Messages kept in the recording. At capacity, the oldest record is evicted per new capture (a "wrap"); sequence numbers are never reused.
Capture full full stores the encoded message; summary stores only payload type, size, a short preview, topic, and the message's property names — much lighter for chatty wires.
Max bytes 16384 Per-record cap. A full-mode record whose encoding exceeds this falls back to summary form, flagged truncated: true — a record is either complete or explicitly a summary, never silently partial.
Redact (empty) Message property paths (one per line, or comma-separated) masked as [REDACTED] before anything is stored or previewed — a secret can never leak into a truncated preview. Example: payload.password.
Cooldown 0 Minimum milliseconds between automatic incidents (watermark here; errors on the tap). 0 disables. Manual dumps always fire regardless. Suppressed auto-dumps emit an incidentSuppressed event — nothing invisible.
Persist off The recording survives restarts and redeploys. See below.
Watermark disabled Auto-dump when a passing message matches: a property path, an operator, and a value.

Watermark operators

==, !=, >, >=, <, <= (numeric comparison when both sides parse as numbers; ==/!= fall back to string comparison), contains (substring on the stringified value), exists / not exists (property presence). The matching message is captured first, so it's always the last record in the incident; the incident's context carries the condition and the matched record's matchedSeq.

Message handling details

  • Circular structures, Buffers, functions, Errors, Dates, and HTTP req/res objects are all encoded safely — req/res become shallow placeholders and are never deep-encoded. See Data Formats for the encodings.
  • Each record carries a deltaMs since the previous accepted capture, computed at capture time — the recording is self-describing even after a restart.
  • _msgid is preserved in records, useful for correlating against debug output.

Persistence

When enabled, the recording is written to <userDir>/flight-recorder/<nodeId>.json — debounced for captures (every 20 captures or 5 seconds, whichever first), immediately for state-changing commands (clear, pause, resume, mark). Writes are atomic (temp file + rename): a crash mid-write can never corrupt an existing recording.

On restart, restored records carry restored: true, sequence numbers continue where they left off, the paused/recording state comes back, and the downtime shows honestly as a delta gap on the first new capture. Reports render the boundary as a ── RESTART ── rule. A corrupt or unrecognized persist file logs a warning and starts fresh — it never blocks the node.

Redeploying preserves the file; deleting the node removes it. Persistence failures surface as recorderError events and a red status, and recording continues regardless — the recorder never dies of a disk problem.

Status

Status Meaning
🟢 47/100 Recording; records / capacity.
🟡 paused (12 dropped) Tape paused; messages arriving are counted, not stored (traffic still flows).
🔴 persist error Last persistence write failed; recording continues in memory. Clears on the next successful write.

A note on sources

Inline records all show this recorder as their source — the node captures at its own input and cannot know which node sent the message (Node-RED doesn't pass sender identity on wires). If source attribution matters to your diagnosis, use a tap, whose hooks identify the true emitter of every message.

Clone this wiki locally