Skip to main content

Module trace

Module trace 

Source
Expand description

Decision-trace channel for XFA observability.

This module is part of M1 (Observability Foundation). It exists so that XFA fidelity debugging can record why the engine made a particular layout decision, separate from what the resulting layout looks like (the latter is captured by crate::ir).

§Design constraints

  • Off by default. No global state. The trace channel is enabled only inside a with_sink scope. When no sink is installed, emit is a single thread-local read returning a None and compiles to a small handful of instructions.
  • No new dependencies. Plain Rust, std only. No tracing or serde involvement at this layer.
  • Frozen vocabulary. Phase and Reason are enums with stable string tags; renames are breaking and require a taxonomy bump (see migration policy in source comments).
  • Determinism-friendly. Events are accumulated in insertion order inside a RecordingSink, with no HashMap/HashSet involvement.

§Out of scope (M1 v1)

  • Wiring trace emit calls from the engine’s hot phases (bind, occur, presence, paginate, suppress) into production layout code paths. v1 ships the taxonomy, the sink trait, and demonstration emit sites under tests. Engine wiring lands in a follow-up wave that is allowed to perturb existing call sites.
  • Streaming output to disk, file rotation, or telemetry. The diff CLI in xfa-test-runner reads the in-memory RecordingSink events serialised once at the end of a run.
  • JSON/Serde derives. Output is via the small to_canonical_json helpers below.

Modules§

sites
Named emit helpers for the five M1.6 hot phases.

Structs§

NoopSink
A no-op sink. Default when no sink is installed.
RecordingSink
A simple recording sink that accumulates events in insertion order.
TraceEvent
One trace event.

Enums§

Phase
The phase in which a trace event was emitted.
Reason
The reason behind a trace event — a closed vocabulary of decision codes.

Traits§

Sink
Implemented by anything that wants to receive trace events.

Functions§

clear_global_sink
Clear the global sink slot.
emit
Emit one event to the current thread-local sink, if any, and then to the global sink, if any. Cheap when neither is installed: one thread-local read, one atomic-protected lock read, and two Option::is_some checks.
emit_simple
Convenience: emit a Phase + Reason event with no extra fields.
events_to_canonical_json
Render a slice of events to canonical JSON (alphabetical keys, fixed ordering, two-space indent).
set_global_sink
Install a Send + Sync sink in the cross-thread global slot.
with_global_sink
Install sink in the global slot for the duration of f, then restore the previous global sink. Emits from any thread (including worker threads f spawns) reach this sink. Single-thread callers should prefer the cheaper with_sink API.
with_sink
Install sink for the duration of f, then restore the previous sink.