feat(observe)!: unify journal and trace into single observation pipeline
The codegen now emits one `__chart_observe!` invocation per observable
atom. The macro fans out at compile time to whichever sinks are enabled:
the in-memory journal (`feature = "journal"`), `defmt` (`trace-defmt`),
`log` (`trace-log`), and/or `tracing` (`trace-tracing`). Trace and
journal share the same vocabulary by construction — they cannot
diverge. With no sink feature on, every site expands to `()` (zero
overhead). Multiple trace backends now compose; previously they were
mutually exclusive.
Trace lines use a logfmt-style format with a `[statechart:Name]` prefix
and `key=value` pairs, machine-parseable and greppable. Twenty verbs
cover every observable atom — entries/exits with begin/end pairs,
actions with kind, durings, transitions with the reason that triggered
them, event lifecycle (received/delivered/dropped/queued/failed),
timers, and termination.
BREAKING CHANGES (chart syntax unchanged; observability surface only):
- `TraceEvent::TransitionFired` now carries `reason: TransitionReason`
showing whether the transition was driven by an event, a timer, or
internal logic.
- New `TraceEvent` variants for phase pairing: `EnterBegan`, `ExitBegan`,
`TransitionComplete`, `EventReceived`.
- Trace prefix changed from `[Name]` to `[statechart:Name]`.
- The chart-level `trace;` keyword is parsed for backwards compatibility
but no longer gates emission.
- `__chart_trace!` / `__chart_journal!` macros removed (doc-hidden).
Verification: 159 integration tests pass, 0 missed mutants, miri 68
tests clean, Creusot 14/14 VCs discharged. Zero overhead confirmed via
`cargo expand` — every observation site expands to `{}` with no sinks
enabled.
This commit is contained in:
21 files changed
+2026
-488
No files matched your search
@@ -217,6 +217,16 @@ So a full transition reads top-to-bottom as: cancel durings on the way
|
||||
out → run exits on the way out → run entries on the way in → start
|
||||
durings on the way in.
|
||||
|
||||
Observers (the journal and any active trace backend) see this as
|
||||
phase **begin** and **end** markers bracketing the work: an
|
||||
`EnterBegan { state }` fires before any of that state's entry actions /
|
||||
timer arms / during starts, and an `Entered { state }` fires after
|
||||
all of them finish. The same for `ExitBegan` / `Exited`, and
|
||||
`TransitionFired` / `TransitionComplete` bracket the whole exit-then-
|
||||
enter sequence of a transition. This is purely a visibility change —
|
||||
the operational rules above are unchanged — but it lets you tell from
|
||||
a captured trace which atoms ran inside which phase.
|
||||
|
||||
---
|
||||
|
||||
## `emit()` — sending events from inside an action
|
||||
|
||||
Reference in new issue
Block a user