Monitoring
Observability is split between the metrics facade and tracing.
Metrics
xstate-observability (feature observability) records the xstatemachine_* metric set of the
Python library’s PrometheusPlugin through the
metrics facade. The crate does not pick the exporter — install one
(e.g. metrics-exporter-prometheus) and call describe_metrics().
#![allow(unused)]
fn main() {
use std::sync::Arc;
use xstate_statemachine::prelude::*;
use xstate_statemachine::observability::{MetricsObserver, describe_metrics};
describe_metrics(); // after installing an exporter
let machine = Machine::from_json(
r#"{"id":"door","initial":"closed","states":{
"closed":{"on":{"OPEN":"open"}},"open":{"on":{"CLOSE":"closed"}}}}"#,
)?;
let observer = Arc::new(MetricsObserver::new());
let mut interpreter = SyncInterpreter::new(machine, MachineLogic::dynamic());
interpreter.observe(observer.clone());
interpreter.start()?;
interpreter.send("OPEN")?;
Ok::<(), Box<dyn std::error::Error>>(())
}
The recorded names include xstatemachine_transitions, xstatemachine_events_received,
xstatemachine_transition_duration_seconds, xstatemachine_active_interpreters,
xstatemachine_chain_trips, xstatemachine_actions, xstatemachine_unhandled_events,
xstatemachine_events_dropped, xstatemachine_errors and xstatemachine_microsteps (the
metrics facade appends _total to counters). Labels obey strict telemetry hygiene: undeclared
event types are recorded as unknown, every label dimension is capped (other on overflow), and
payloads, context and instance keys are never recorded. Transition durations are measured through
MetricsObserver::timed, because the observer hooks fire after the fact.
Tracing
Library crates use tracing only (no println!/log), with targets like xstate,
xstate::persistence, xstate::inspect, xstate::eda and xstate::observability. No payload,
context or secret is logged by default; the engine’s redact helpers and the inspector
allow-lists keep user data out of logs and streams. TracingObserver (in xstate-core) bridges
interpreter hooks to tracing.
See the crate docs under /api/xstate_observability/ for the full metric catalogue.