vike
ReferenceBinaries

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.

On this page