vike-stat
A read-only reader for the live core's opt-in mmap counter mirror, so a headless or remote trader can be inspected without attaching to it.
vike_stat maps one file read-only and prints the live core's key health counters. It never
attaches to the trader process, never opens a socket and never asks the core for anything — the
whole interface is a memory-mapped file the core mirrors into. That is the point: a headless
trader on a remote box has no window to look at, and vike_stat is how you look at it anyway.
This page is written from crates/vike-core/src/bin/vike_stat.rs's module header and
crates/vike-core/src/counters.rs.
The mirror is opt-in, and off by default
The trader writes the file only when vike_core::CoreConfig's counters_path is set. None is
the default, and its module doc states the consequence exactly: nothing is opened and the publish
path is byte-identical to a build without the feature. Off costs nothing.
On costs almost nothing either, and the reason is where the copy happens.
crates/vike-core/src/counters.rs opens with the pinned constraint: the per-message fold — the
p99 < 10µs gate — is not touched. No runtime atomic moves into the mmap and no per-message
write is added. The file is a periodic mirror, copied at the same coalesced cadence the runtime
already publishes a CoreSnapshot at (the module doc gives ~16 ms while busy, or on idle). The
only new cost is at that existing rare publish.
If the path is set and cannot be opened, the core fails loudly at startup rather than dropping the
mirror silently — assemble_core (crates/vike-core/src/runtime/mod.rs) opens it with an
expect, on the argument that a trader which believes it is mirroring but is not would mislead
this tool. The desktop app therefore probes the path itself first, so a read-only directory
degrades to no mirror, with a warning instead of a panic at launch.
Finding the file
vike_stat takes the path as its one positional argument, or from $VIKE_COUNTERS_FILE. The
desktop app resolves the writer's path the same way — crates/vike-desktop/src/main.rs's
counters_file_path reads $VIKE_COUNTERS_FILE first and falls back to <exe_dir>/counters.vmc
— and its doc says why that matters: setting the one variable points the writer and the reader at
the same file with no arguments on either side.
usage: vike_stat <counters-file> [--watch] [--interval <secs>]
--watch re-read every 1s until interrupted
--interval <secs> re-read on a custom period (implies --watch)-h/--help prints that text to stdout and exits 0; the same text alongside an error message
goes to stderr. The split is deliberate and is recorded on vike_stat's usage function: printing
it unconditionally to stderr made vike_stat --help | less an empty page. A one-shot run whose
read fails exits non-zero so a script can tell "no file / bad file" apart from a healthy read;
under --watch, a transient error (the trader not up yet) is printed and the next tick retries.
What a torn read means
The writer wraps every mirror in a seqlock: the header's seq goes odd before the payload is
written and even after. The reader reads seq, the payload, then seq again, and accepts the
values only when both reads are equal and even. A clean read can therefore never return a
mid-update mix of counters.
When the retries are exhausted the report comes back with clean = false and vike_stat prints
TORN-READ instead of clean on its header line. CountersReport's own field doc is the
authority for reading that: the values may be a mid-update mix, but every counter is monotonic,
so each individual value is still a valid point-in-time reading of that counter, off by at most one
update.
The layout is fixed, versioned and cache-line padded — a header slot plus one 128-byte slot per
counter — so an external reader has a stable schema and every field a stable aligned offset.
vike_core::counters::read errors on a missing file, a file smaller than one slot, or a bad magic;
a version mismatch is surfaced in the report rather than being an error, so a newer file still
prints the counters this reader knows.
The counters
vike_core::counters::COUNTER_NAMES is the stable wire order — append-only, never reordered or
removed, with the format version bumped on each append (v2 appended dropped_nonfinite). Two slots
are reserved tombstones: exec_db_queue_depth and exec_db_errors are marked RETIRED since the
SQLite exec database was removed and are always 0.
One counter has no benign reading
COUNTER_NAMES singles out dropped_nonfinite. The others — conflation drops, rejected commands,
stranded terminals, a terminal dropped on a live order, a lifecycle event for an unknown client
order id — all have innocent explanations: a reconnect replay, a shared-account order, an
out-of-order frame. A money-lane event carrying a non-finite f64 has none; no venue sends
"NaN". Nonzero means a venue fault or a compromised feed, and the comment on that row says to
page on it.
The counters are also carried in-process by CoreSnapshot for the GUI. This file is the
out-of-process twin of that, for the case where there is no GUI to read.
For the environment variable itself see environment variables; for the fold whose budget the mirror is designed around, the latency gate.
replay-journal
Deterministic offline replay of a command journal through the real core, fenced on a final state hash.
collector_supervisor
The always-on supervisor that keeps a declared set of history-store series fresh and heals their historical holes, instead of an operator re-running one-shot collectors by hand.