BKPT LabsDOCS/VIEWALYZER CLI/QUERIES VIEWALYZER · HEADLESS CLI
VIEWALYZER · CLI & AUTOMATION

Queries

query <verb> --recording <id|path> prints one JSON object shaped for a consumer, from a recording on disk. Every response carries schema_version, recording_id, path, query and budget; times are microseconds since the recording start; tasks are referenced by a compact code (T1, T2) defined in the response's task_legend, channels by C1, C2 in trace_legend.

$ viewalyzer-cli query summary --recording run.vadb
{"schema_version":2,"recording_id":"328d49aa4eb6","query":"summary","budget":"med","duration_us":5111531,"span_seconds":5.11,"cpu_freq_hz":170000000.0,"os":"BareMetal","total_events":21930,"task_events":14679,"trace_events":7251,"events_per_second":4290.3,"context_switches":14679,"preemptions":0,"cpu_load_percent":0.27,"total_tasks":1,"lanes":2,"trace_channels":4,"user_events":1,"lost_events":0,"corrupt_bytes":0,"capture_utc":"2026-08-29T08:29:39Z"}

Tiers and budgets

Three verbs (timeline, events, user-traces) come in three tiers, so a consumer never pulls a payload it cannot handle:

--TIER NEEDS RETURNS
summary (default)nothingwhole-recording statistics
bucketed--t-start-us, --t-end-us, --bucket-usone value per bucket over the window
raw--t-start-us, --t-end-usthe individual rows in the window

--budget low|med|high scales the caps (rows 200 / 1000 / 5000, buckets 64 / 256 / 1024, serialized size 12 / 48 / 200 KB). A window that exceeds a cap does not truncate silently: it answers window_too_wide with a suggestion (a narrower t_end_us, a wider bucket, a --kinds or --channels filter, or a higher budget). The -all verbs (slices, slice-details, events-all, user-traces-all) are unbounded, for consumers that manage payload size themselves (--max-slices n).

$ viewalyzer-cli query user-traces --recording run.vadb --tier raw --t-start-us 1000000 --t-end-us 1010000 --channels "Sine Wave"
{"schema_version":2,"query":"user-traces","tier":"raw","t_start_us":1000000,"t_end_us":1010000,
 "trace_legend":{"C1":{"name":"Sine Wave","va_id":42,"display":"graph","ns":"user_trace"}},
 "sample_fields":["channel_code","t_us","value"],
 "samples":[["C1",1000239,88.0],["C1",1002370,83.0],["C1",1004502,77.0],["C1",1006632,71.0],["C1",1008768,63.0]]}

The verbs

VERB PAYLOAD
summaryWhole-recording scalars: duration, events by class, context switches, preemptions, CPU load, channels, integrity counters
timelinePer-lane cards: cpu_percent, slice_count, mean/p50/p95/p99/max slice, preemptions, observed period p50/p95, max_jitter_us, anomalies[]; bucketed: per-lane CPU% per bucket; raw: slices: [[task_code, t_start_us, dur_us], ...]
eventsCounts by_kind and top_objects (--kinds filters); bucketed: kind counts per bucket; raw: {t_us, kind, start_end, code|obj, value_i, value_f, text}
user-tracesPer channel {count, min, max, mean, last, rms, std_dev, rate_hz, min_at_us, max_at_us} (--channels by name or code); bucketed: [{min,max,mean,count} | null] per bucket; raw: samples: [[channel_code, t_us, value], ...]
cpuThe CPU panel: busy_pct, idle_pct, min and max load with their times over a sliding window, context_switches, preemptions, tasks[] (execution percentiles net of preemption, period and outliers, blocked time, inversions, sync and failed ops, stack), findings[] (priority_inversion, jitter_outlier, failed_ops); --t-start-us/--t-end-us scope everything
inversionsEvery mutex contention: type (inversion when the waiter outranks the holder, OS-aware), waiter and holder with priorities, contend_us, acquire_us, release_us, wait_us
timersPer kernel timer: measured fires, predicted fires, arms and stops, phase-corrected lateness (mean/p99/max_lat_us), violations against --threshold-us (500), a 12-bin histogram, callback duration; work[] k_work lanes. Raw: fire_records[] with a cause on violations
commspaths[] (producer>via>consumer: kind, count, rate, median/p99/max latency, blocked) and resources[] (sends, receives, matched, still pending, empty receives, contentions, peak pending); with --bucket-us a per-resource backlog series
series--kind cpu-load (total plus per-lane bands), event-rate, stack, heap (with failed_allocs_us and capacity), task-timing --task n --metric exec|period, interval --from task:a|trace:a|resource:a --to ... (latency pairs with median/p99/max); all [[t_us, value], ...]
verdictsThe analyser's findings with their evidence, the same list the app shows
sql--sql "SELECT ...": read-only, one statement, rows capped by budget, BLOBs as "<blob N bytes>"
fingerprint, compareGolden-run regression testing; see Regression tests in CI
$ viewalyzer-cli query cpu --recording run.vadb
{"schema_version":2,"query":"cpu","window":{"t_start_us":0,"t_end_us":5111531,"scoped":false},"busy_pct":0.27,"idle_pct":99.73,"min_load_pct":0.27,"max_load_pct":0.27,"sweep_window_us":500000,"context_switches":0,"preemptions":0,
 "tasks":[{"name":"ISR:SysTick","kind":"isr","cpu_pct":0.27,"runs":5111,"mean_us":2.74,"p50_us":2.75,"p99_us":2.77,"max_us":2.87,"period_p50_us":1000.0,"period_p95_us":1000.1,"outliers":0,"preempt_count":0,"blocked":0,"inversions":0}],"findings":[]}

$ viewalyzer-cli query series --recording run.vadb --kind cpu-load --bucket-us 500000
{"schema_version":2,"query":"series","kind":"cpu-load","window_us":500000,"points":256,"fields":["t_us","load_pct"],"total":[[0,0.0],[19967,0.28],[39934,0.27], ...]}

SQL

When no verb shapes the data the way you need, sql runs one read-only statement against the recording's tables (The .vadb file):

$ viewalyzer-cli query sql --recording run.vadb --sql "select kind, count(*) as n from va_events group by kind order by n desc limit 5"
{"schema_version":2,"query":"sql","columns":["kind","n"],"rows":[["user_event",19136],["isr",10222],["user_trace",7176],["user_toggle",75],["string",5]],"row_count":5,"truncated":false}

Hardware-trace queries

Present when the recording was captured with hardware trace (--dwt ... or the hardware-trace block on an SWO transport, or DWT_PCSR polling on the others); no_hw_trace otherwise.

VERB DATA
profile [--elf f]PC-sample hotspots: total_samples, sleep_samples, span_s, sample_rate_hz, hotspots[] of {symbol, addr, samples, pct, file, line, isr} (symbolicated with --elf), source (dwt-swo or pcsr-poll), interval_cycles, sleep_pct, outside_elf_pct
itm-console [--port N]ports[] of {port, lines: [{t_us, text}], bytes}; lines split on newline, an unterminated tail is marked partial; --port keeps one port
dwt-datawatches[] of {cmp, name, address, function, count, first: [{t_us, value, rw, pc?, symbol?, file?, line?}]} (up to 256 samples each; --elf symbolicates the PCs)
dwt-exctotal, max_depth, exceptions[] of {num, name, enter, exit, return, max_depth}, events[] of {t_us, num, func, depth} (up to 4096)
dwt-counterscounters.{cpi,exc,sleep,lsu,fold,cyc} = {wraps, cycles, rate_per_s}, span_s, cpu_load_pct (from the sleep counter, null without it), overflows, reliable
swo-load{bytes, seconds, bytes_per_s, swo_hz, share_pct, overflows} for the whole capture

irq, etm and target-caps are reserved and error naming the reason (no_hw_trace, etm_not_present, bad_arguments).

load and export

load prints a recording's summary (recording.{duration_us, os, total_events, lanes_detail[], channels_detail[], lost_events, ...}) and converts or exports:

$ viewalyzer-cli load run.va --output run.vadb                              # a byte-log or raw wire dump into a .vadb
$ viewalyzer-cli load run.vadb --export traces --format csv --out -         # events | traces | spans | tasks | channels
t_us,channel,va_id,value
6,Sine Wave,42,0
9,Tick Counter,43,0
11,Workload,46,0

replay run.vadb [--perf] re-parses a recording and prints [metric] category,name,value,unit lines (info, data, per-lane task.slices and task.cpu, per-channel trace, flow, result,status), the surface the HIL bench parses; --perf adds pipeline timings. Exit 0 when the recording carries task slices or user traces, 1 otherwise.