Runtime dashboard now features a TUI option and an interface for LLM tool use. Removed some bloat from stats collecting and replaced with a hook funciton to dump runtime stats into.
5.2 KiB
Runtime Dashboard — Agent Diagnostic Interface
Investigate Protocol
There is a line-oriented diagnostic protocol for programmatic runtime investigation. It reads text commands from stdin and writes JSON responses to stdout (one object per line). Human-readable output goes to stderr.
Launching
cargo run -p runtime-dashboard --example investigate_demo
Or programmatically against any running runtime:
use runtime_dashboard::investigate::run_investigate;
run_investigate(runtime_arc)?; // blocks on stdin
Response Envelope
Every response is a single JSON object on one line:
{"ok": true, "command": "overview", "data": { ... }}
{"ok": false, "command": "bogus", "error": "unknown command `bogus` — try `help`"}
Commands
overview
Overall runtime summary.
→ overview
← {"ok":true,"command":"overview","data":{
"workers": 4,
"actors": 120,
"total_messages_processed": 584210,
"total_mailbox_depth": 37,
"total_panics": 0,
"total_type_mismatches": 0,
"sends": {"local": 312000, "cross_worker": 271000, "inbox": 1210}
}}
workers
All workers with per-worker counters.
→ workers
← {"ok":true,"command":"workers","data":[
{"id":0,"actors":30,"mailbox_depth":12,"messages_processed":146000,
"local_sends":78000,"cross_sends":67000,"inbox_sends":300,
"type_mismatches":0,"panics":0},
...
]}
worker <id>
Single worker detail including tick-phase timing and its actors.
→ worker 2
← {"ok":true,"command":"worker","data":{
"id": 2, "actors": 30, "mailbox_depth": 8,
"messages_processed": 148000,
"local_sends": 80000, "cross_sends": 67500, "inbox_sends": 500,
"type_mismatches": 0, "panics": 0,
"tick_phases": {
"ticks": 412,
"active_pct": 78.4,
"avg_tick_us": 23.7,
"phases_us": [120, 980, 7200, 90, 1100, 280],
"phases_pct": [1.2, 10.0, 73.6, 0.9, 11.2, 2.9]
},
"actor_details": [
{"address": "a1b2c3d4…", "mailbox_depth": 3, "last_msg_type": "MyMsg"},
...
]
}}
The six tick phases (indices 0–5): 0. spawn_drain — draining spawn channel
- transfer_drain — draining cross-worker transfer channel
- tick_all — processing actor mailboxes (main work)
- spawn_drain_2 — draining spawns created during tick
- pending_local — delivering messages buffered within the worker
- stats_publish — updating shared stat counters
actors [--sort mailbox|worker|address] [--limit N] [--worker W]
Actor listing with sorting, limit, and worker filter.
→ actors --sort mailbox --limit 5
→ actors --worker 0 --sort address
→ actors --limit 20
actor <hex_prefix>
Find actors whose address starts with the given hex prefix.
→ actor a1b2
← {"ok":true,"command":"actor","data":{
"prefix": "a1b2",
"matches": 1,
"actors": [{"address": "a1b2c3d4…", "address_full": "a1b2c3d4...(64 hex chars)", "worker_id": 2, "mailbox_depth": 3, "last_msg_type": "MyMsg"}]
}}
hot [N]
Top N actors by mailbox depth (default 10). Use this to find backpressure.
→ hot 5
phases [worker_id]
Tick-phase timing breakdown. Without an argument returns all workers.
→ phases
→ phases 2
diff <seconds>
Takes two snapshots separated by N seconds (max 30) and reports deltas. This is the primary throughput measurement tool.
→ diff 2
← {"ok":true,"command":"diff","data":{
"elapsed_s": 2.001,
"actors_before": 120, "actors_after": 132,
"delta_messages": 8432,
"msg_per_sec": 4213.9,
"delta_local_sends": 4500,
"delta_cross_sends": 3900,
"mailbox_before": 37, "mailbox_after": 42,
"per_worker": [
{"worker_id": 0, "delta_messages": 2100, "msg_per_sec": 1049.5,
"actors_before": 30, "actors_after": 33,
"mailbox_before": 12, "mailbox_after": 14},
...
]
}}
help
Returns all commands with usage strings.
quit
Exits the session.
Investigation Playbook
When diagnosing a runtime, a useful sequence:
overview— get the lay of the landdiff 2— measure live throughput and detect growthhot 10— find actors with deepest mailboxes (backpressure)workers— compare per-worker load distributionworker <id>— drill into the busiest worker, check phase breakdownphases— check if workers are spending time in unexpected phasesactors --worker <id> --sort mailbox— find hot actors on that workeractor <prefix>— get full address and type for a specific actor
Key Metrics to Watch
| Symptom | Check | Meaning |
|---|---|---|
| High mailbox_depth | hot 10 |
Actor can't keep up — backpressure |
| Uneven msg_per_sec across workers | diff 2 per_worker |
Load imbalance |
| High cross_sends vs local_sends | overview sends |
Actors that talk are on different workers |
| active_pct near 100% | phases <id> |
Worker is saturated |
| High phase 1+4 % vs phase 2 | phases <id> |
Delivery overhead dominates processing |
| Growing actors_after vs actors_before | diff 5 |
Unbounded actor spawning |
| type_mismatches > 0 | overview |
Messages routed to wrong actor type |
| panics > 0 | overview |
Actor handlers are panicking |