facett-trace — a structured event trace: the machine-readable sibling of a free-form action log.
An action log is a human free-form trail (tab=Bench, reload … → 3 release(s)). This is its typed counterpart: every instrumented operation
emits its INPUT parameters and its OUTPUT data as real JSON payloads, so an
external agent (or a headless test matrix) can read back exactly the data
the UI rendered — the bubble table, the bench rows, the server response —
not a summary and not a screenshot.
Adopted verbatim from nornir's src/viz/trace.rs; it was already zero-coupling
(generic over serde::Serialize). The only change is the output-path env var:
$FACETT_TRACE (default /tmp/facett_trace.jsonl), truncated on launch.
One JSON object per line (JSONL):
The contract
- span — the operation name (
knowledge.scan,ui.tab,server.reload). - phase —
in(params accepted),out(result produced),end(a unit of work finished), orevent(a point-in-time fact, e.g. a tab switch). Pair aninwith its laterout/endof the samespanby adjacency — the UI is single-threaded, so within one operation they don't interleave. - data — the real, structured payload. Emit typed structs (serialized via serde), never a pre-formatted string, so the consumer parses fields.
Cheap by design: a Mutex<File> writeln! + a global atomic seq. Call sites
only emit on edge-triggered events (a scan, a click, an RPC), never per-frame.