Aria's diagnostics system lets you observe the inner workings of the reactive graph, async commands, bindings, validators, and list mutations — all through a single, zero-overhead trace protocol.
Include: #include "aria/diagnostics.hpp", #include "aria/reactive/inspector.hpp"
Zero-Overhead Contract
When no trace sink is installed, the publish path costs one atomic load + one branch. No strings are built, no allocations happen. This means you can ship production builds with trace instrumentation compiled in and pay nothing until you attach a debugger.
Trace Categories
Every trace event carries a TraceCategory:
| Category | Enum Value | Covers |
| Reactive | 0 | Graph flush, push-color, pull-evaluate |
| Async | 1 | AsyncCommand / AsyncResource lifecycle |
| Binding | 2 | BindingEngine VM↔View dispatch |
| Command | 3 | Synchronous Command execution |
| Validation | 4 | Validator / FormValidator rule runs |
| List | 5 | ObservableList / derived list mutations |
Installing a Global Trace Sink
<< ev.debug_name << "\n";
});
void install_trace_sink(TraceSink sink)
Install (or replace) the global sink.
Definition diagnostics.hpp:271
std::string_view to_string(TraceCategory c) noexcept
Definition diagnostics.hpp:75
One trace event.
Definition diagnostics.hpp:200
TraceCategory category
Coarse routing label.
Definition diagnostics.hpp:202
The sink is thread-safe — install, replace, or clear from any thread at any time.
Clear the Sink
void clear_trace_sink() noexcept
Tear down the global sink.
Definition diagnostics.hpp:279
TraceEvent Structure
struct TraceEvent {
TraceCategory category;
std::string debug_name;
std::variant<
trace::Reactive,
trace::Async,
trace::Binding,
trace::Command,
trace::Validation,
trace::List
> payload;
};
Each payload variant carries category-specific data:
- trace::Reactive — flush phase, node state transitions
- trace::Async — command execution start/end/error
- trace::Binding — bind/unbind events, dispatch direction
- trace::Command — execute / rejected_can_execute / can_execute_changed
- trace::Validation — rule_pass / rule_fail / begin_pending / end_pending
- trace::List — insert/remove/reset/change events
GraphInspector
For deeper reactive graph introspection:
std::string dot = inspector.
to_dot();
std::string json = inspector.
to_json();
std::cout <<
"Phase: " << ev.
phase
<< " Node: " << ev.node_name
<<
" Changed: " << ev.
changed <<
"\n";
});
Lightweight diagnostics entry point.
Definition inspector.hpp:54
static void install_flush_tracer(FlushTracer tracer)
Install a tracer.
Definition inspector.hpp:201
static std::string to_dot(const std::vector< const Node * > &seeds, std::string_view graph_name="reactive")
Emit the reachable subgraph as a Graphviz DOT document.
Definition inspector.hpp:96
static std::string to_json(const std::vector< const Node * > &seeds)
Emit the reachable subgraph as a minimal JSON document.
Definition inspector.hpp:132
A single event emitted by the Graph during flush.
Definition inspector.hpp:171
bool changed
valid for Phase::Recomputed
Definition inspector.hpp:184
Phase phase
Definition inspector.hpp:181
DOT Output
Generate a visual representation of the reactive DAG:
std::ofstream out("graph.dot");
Nodes are labeled with their debug_name (if set via set_debug_name()). Edges show dependency direction.
ScopedTraceSink
Install a trace sink for a limited scope, restoring the previous sink on exit:
void test_reactive_flow() {
std::vector<std::string> log;
log.push_back(ev.debug_name);
});
REQUIRE(log.size() > 0);
}
Installs a sink for the lifetime of the scope, restoring whatever was previously installed (possibly ...
Definition diagnostics.hpp:348
Debug Names
Set human-readable names on reactive nodes for easier debugging:
Definition computed.hpp:86
void set_debug_name(std::string name)
Definition node.hpp:158
Definition property.hpp:103
T get() const
Auto-tracked read.
Definition property.hpp:138
These names appear in DOT graphs, JSON dumps, and trace events.
Filtering by Category
});
@ Validation
Validator / FormValidator rule runs.
Definition diagnostics.hpp:71
Quick Reference
| Function / Type | Purpose |
| install_trace_sink(fn) | Set global trace consumer |
| clear_trace_sink() | Remove consumer, restore zero-overhead |
| has_trace_sink() | Check if a consumer is active |
| ScopedTraceSink | RAII: install + auto-restore |
| GraphInspector::to_dot() | Export DAG as DOT |
| GraphInspector::to_json() | Export DAG as JSON |
| GraphInspector::install_flush_tracer(fn) | Per-flush step logging |
| Node::set_debug_name(str) | Human-readable label |
See Also