Node-RED¶
The node-red-contrib-lumatrack package records one run event per flow execution.
Drop it at the end of a flow, wire a Catch node to a second copy, and the value
report builds itself.
Install¶
From the editor: Menu, Manage palette, Install, then search for
node-red-contrib-lumatrack. Or from your Node-RED user directory:
cd ~/.node-red
npm install node-red-contrib-lumatrack
Restart Node-RED afterwards. Any Node-RED flow can also report through plain HTTP with an http request node.
The connection¶
Add a lumatrack run node, open it, and create a LumaTrack configuration next to Server:
| Field | Value |
|---|---|
| Base URL | Your LumaTrack host, e.g. https://lumatrack.example.com |
| API key | From Settings, API keys in LumaTrack (shown once at creation) |
An ingest-only key is enough to record runs and is the one to use: if it leaks, an attacker can post junk runs, and they cannot read or restate your ledger.
The key is stored as a Node-RED credential, which keeps it in credentials.json
rather than in the flow. Exporting a flow to share it therefore does not carry the
key.
Fields¶
| Field | Notes |
|---|---|
| Automation | The slug this flow reports as; create it in the app or over the API |
| Status | success, failure, skipped or cancelled |
| Reason | Root cause for a failure, e.g. auth/credential. Powers the failure-reason Pareto |
| Units | Records the flow processed; drives per-unit valuation. Blank leaves the server default of 1 |
| Duration | Wall-clock seconds. Blank omits it; 0 is a real zero-second run |
| External ID | Blank uses the message id, which makes a resent message idempotent |
| Executed at | ISO 8601, for evidence that genuinely happened earlier. Frozen months are refused |
| Metadata | JSON object kept with the run |
| Source | Stored on the run, node-red by default |
Any field left blank is read from msg.payload under the same name, using
duration_seconds, external_id, failure_reason and executed_at for those four.
A field filled in on the node wins, so one node can take its slug from the editor and
its units from the message.
The output message carries the ingest reply on msg.payload, with run.id,
run.held and deduplicated.
Wire the failure path too¶
One node on the success path is half the integration. Failed flows cost money and save nothing, and reporting them is what makes the reliability chart and the net numbers credible.
Node-RED's Catch node is the mechanism. Scope one to the nodes that can fail and
wire it to a second lumatrack run node with Status set to failure:
[ inject ] → [ do the work ] → [ lumatrack run: success ]
[ catch: do the work ] → [ lumatrack run: failure ]
A Catch node passes the original message through with msg.error attached. Put a
function node between the two and set msg.payload.failure_reason from
msg.error.message when you want the Pareto broken down further than one bucket.
The lumatrack run node raises its own failures with done(err), so a Catch node
scoped to it sees a LumaTrack outage as well. Nothing fails silently.
Loops and volume¶
A flow that processed 240 records should report one run with Units set to 240, rather than a node inside a Split that reports 240 runs. The ledger prices per-unit work as fixed setup plus marginal minutes per record, which is the number that survives a CFO's review, and 240 separate runs would each consume an event against your plan's monthly cap.
Put the node after a Join, and set Units from the joined array's length with a function node.
If each item genuinely is its own run, with its own outcome, report per item. Each message has its own id, so the External ID default already keeps them distinct.
Skipped and cancelled¶
A flow that ran and deliberately did no work is skipped, e.g. a switch node sent
everything down an empty branch. One interrupted part way is cancelled. Neither
earns value and neither is ever reported as a failure. Whether they carry the
automation's per-run cost is set per automation in LumaTrack.
Held runs¶
Past your plan's monthly event allowance, LumaTrack stores the run and holds it,
excluded from every value number until the plan is raised. The node warns and shows
held over plan cap beneath itself when that happens.
If a reply carries a non-empty ignored_fields list, a field in the payload was
misspelled and the node warns about it. Treat that as a bug rather than a silent
success.