Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tracing

Every state-modifying instruction emits a LogEntry into the execution trace. The trace provides a complete audit trail for debugging, testing, and formal verification.

Log entry structure

struct LogEntry {
    timestamp: u64,              // monotonic counter
    event_type: EventType,       // what happened
    executing_controller: Option<ControllerId>,
}

Event types

EventEmitted by
ObjectCreated { id, behavior_name }create_obj
ObjectDestroyed(id)destroy_obj
ObjectCalled { id, input, output }call
MessageReceived { id, input }receive
StateUpdated(id)set_state
ObjectMoved { id, from, to }move_object
ExecutionMoved { from, to }teleport
ObjectFetched { id, machine }fetch
ObjectTransferred { id, from, to }transfer_object
ObjectFrozen { id, controller }freeze
FunctionUpdated(name)update_pure
TransactionStarted(id)begin_tx
TransactionCommitted(id)commit_tx
TransactionAborted(id)abort_tx
ErrorOccurred(msg)error paths

Using traces in tests

use avm_core::trace::{count_events, EventType};

let result = run_ping_pong(3).unwrap();

let creates = count_events(&result.trace, |e| {
    matches!(e, EventType::ObjectCreated { .. })
});
assert_eq!(creates, 2);

Timestamps

Timestamps are monotonically increasing within a single interpret() call. They do not represent wall-clock time — they are logical event counters.