Usage stats
The platform keeps time series for every hub, grabber and server — machine
resources, network traffic, torrent activity, and playback concurrency — and
serves them to the admin portal's graphs. One RPC carries the read surface,
under xmb.api.v1:
| RPC | Scope | What it does |
|---|---|---|
StatsService.GetStatSeries | xmb:admin | Columnar time series for one hub, grabber, or the server itself |
How series are collected
Nothing new is polled; the numbers ride channels that already exist:
- Hubs and grabbers report machine state (
HubResources: CPU, load, memory, per-volume disk, and cumulative network counters) on their once-a-minute announce. Hubs also reportactive_transcodes; grabbers report their storage ledger and aGrabberTorrentStatsmessage relayed from the torrent client. Each announce carries aboot_id— the same id log shipping stamps on its batches — which is the boundary counters reset on. - Playback concurrency is the platform's own tally from live playback sessions, sampled once a minute per server and stamped per hub.
- Tunnel traffic comes from the gateways: each shard reports its
WireGuard per-peer transfer counters (on
RoutingService.ReportPeerStatus, paced to roughly one byte-carrying report a minute). This is the one traffic number that is not self-reported — it is counted by the platform's own end of the tunnel.
Raw minute samples are kept for 7 days, folded into 5-minute (90 days), hourly (~13 months) and daily (kept indefinitely) rollups.
GetStatSeries
The request names a server_slug, an entity (STATS_ENTITY_KIND_HUB,
STATS_ENTITY_KIND_GRABBER with the node's uuid, or
STATS_ENTITY_KIND_SERVER), a list of metric names, and a [start, end)
range. step_seconds is advisory: the platform serves the finest stored
tier that still covers the range's start (60, 300, 3600 or 86400 seconds)
and reports the one it chose.
The response is columnar: one shared timestamps axis, continuous over the
range, and one StatsSeries per requested metric with parallel values and
defined arrays. A defined[i] of false is a gap — an agent too old
to report the metric, a node that was down, a minute nothing was watched —
and must render as a gap, never as zero. Unknown metric names come back as
all-gap series rather than errors, so a UI ahead of its API degrades to an
empty panel.
Counters are always exposed as per-second rates (net_rx_bps), with counter
resets spliced server-side; a caller never sees a cumulative value.
Metric names
Hub and grabber entities:
cpu_used_percent, load1, load5, load15, mem_total_bytes,
mem_available_bytes, media_total_bytes, media_free_bytes,
data_total_bytes, data_free_bytes, net_rx_bps, net_tx_bps,
tunnel_rx_bps, tunnel_tx_bps
Hub only: active_transcodes, live_sessions, live_sessions_hls
Grabber only: storage_budget_bytes, storage_committed_bytes,
storage_obligation_hold_bytes, storage_releasable_bytes,
torrents_downloading, torrents_seeding, dl_rate_bps, up_rate_bps
Server entity:
concurrent_sessions, concurrent_watchers, concurrent_hls,
concurrent_direct, plays_started, watch_minutes, unique_watchers,
ends_stopped, ends_idle, ends_superseded, ends_failed (and
concurrent_sessions_peak / concurrent_watchers_peak at rollup
resolutions)
Event-shaped server metrics (plays_started and everything after it) and
the tunnel rates exist only from the 5-minute tier up — requesting one
floors the served resolution at 300 seconds.
Shared hubs
A hub's machine series belongs to its home server only. A tenant a hub is shared with can stream from it, but its CPU, disks and traffic are the owner's diagnostics and are not visible through this RPC.