Expand description
Traffic counter collection for moq-net sessions.
This module only collects: build a Registry, hand each session a
tier-scoped Handle via Registry::tier, and read the counters back
with Registry::snapshot (host-level rollup, e.g. a /metrics scrape) or
Registry::report (per-broadcast detail). Publishing the counters as MoQ
broadcasts lives in the moq-stats crate, which drains a Registry on an
interval and writes the JSON stats tracks.
Traffic is bucketed by an arbitrary Tier label chosen by business logic
(billing class, region, …) and, within a tier, by broadcast path and
Role (publisher = egress, subscriber = ingress). Connected sessions are
tracked separately per (tier, auth root), counting presence regardless of
whether any data flows.
§Where counting happens
Counting lives in the model layer, not the wire loops. A session tags its
origin pair with a Session context (crate::Client::with_stats /
crate::Server::with_stats, which call origin::{Consumer, Producer}
with_stats); every derived handle (broadcast, announce, track, group, frame)
then attributes its reads (egress = publisher) and writes (ingress =
subscriber) through that context. So any protocol that drives the model gets
the full counter set for free, and an untagged handle pays nothing.
Per-counter semantics:
announced/announced_closed: cumulative broadcast announce/unannounce events on this(tier, role). Driven by the tagged announce stream on the egress side, and bycreate_broadcastroute transitions on the ingress side.announced_bytes: cumulative broadcast-name length summed over each model-visible announce and unannounce of this broadcast (the name, not the encoded message size, so hop/framing overhead isn’t charged, and the count is the same across protocol versions). Kept separate from thebytespayload counter.broadcasts/broadcasts_closed: per-(broadcast, context) egress subscription sentinel. The first active subscription a context opens for a broadcast bumpsbroadcasts; the last it closes bumpsbroadcasts_closed. Summed across contexts,broadcasts - broadcasts_closedis the number of distinct sessions currently subscribed (viewers on the egress side).subscriptions/subscriptions_closed: cumulative track-level subscriptions opened/dropped (egresstrack::Subscriber, ingresstrack::Producer).fetches: cumulative one-shot group fetches requested by a calling context, counted once per coalesced fetch at request time. A fetch that resolves toNotFoundstill counts. Separate fromsubscriptionsand the viewer refcount; fetched payload still flows intobytes/frames/groups.bytes/frames/groups: cumulative payload counters bumped as groups/frames are read (egress) or written (ingress) in the model.datagrams: cumulative single-frame groups carried over unreliable QUIC datagrams. A datagram is metered as the group it stands in for, so it also bumpsgroups,frames, andbytes; this counter breaks out how many of those took the datagram path.sessions/sessions_closed(Presence): cumulative count of sessions connected/disconnected under an auth root on this tier. Driven byHandle::session(theSessioncontext).
Counters are strictly monotonic (only fetch_add); a counter going
backwards across reads means the underlying entry was garbage collected
(see Registry::report) and re-created. Downstream consumers should
treat decreases as a fresh segment, summing across resets when computing
lifetime totals.
§Disabled stats
Registry::disabled builds a no-op registry: all counter bumps are
silently dropped and nothing is ever tracked. Registry::default /
Handle::default return one, so call sites can hold a Handle
unconditionally instead of threading an Option.
§Garbage collection
Registry::report returns the current per-broadcast detail and prunes
entries no longer referenced by any guard, so a publisher draining the
registry on an interval keeps it bounded. A registry that is never
drained accumulates one entry per broadcast path ever seen; call
Registry::report periodically if you enable a registry without
attaching a publisher. Registry::snapshot never prunes.
§Snapshot atomicity
Each counter readout loads *_closed atomics (with Acquire)
before their open counterparts (with Relaxed). The matching close
bumps in the RAII guards’ Drop impls use Release. With this
pairing the readout always satisfies open >= closed even on
weakly-ordered architectures (ARM, POWER): the Acquire load of
close synchronizes-with the Release bump that produced the
observed value, making every write that happened-before that close
(including the matching open bump on whichever thread opened the
guard) visible to the reading thread. Open / payload counters can
then stay Relaxed because the visibility comes for free through
the close pairing. The cost is a slight upward bias on the open
counts when a bump lands between the two loads, which never produces
a logically impossible (closed > open) readout for downstream.
§Cycles
A Registry built with excluded prefixes (Config::exclude) returns
empty handles (whose bumps no-op) for any path under one of them. The
moq-stats publisher excludes its own top-level prefix this way, breaking
the feedback loop where serving a stats broadcast would itself generate
more stats traffic.
Structs§
- Config
- Settings for a
Registry. Construct withConfig::newand chain thewith_*setters, then hand it toRegistry::new. - Handle
- Tier-scoped wrapper around
Registry. Whatcrate::Client::with_statsandcrate::Server::with_statsaccept. Cheap to clone. - Presence
- Connected-session presence for one slice (an auth root on a tier, or any
sum of such slices): cumulative connects and disconnects.
sessions - sessions_closedis the current live session count. - Registry
- Counter collection registry. Cheap to clone (
Arcinside for the shared state). One instance per relay; sessions get tier-scoped handles viaRegistry::tier. Themoq-statscrate drains it withRegistry::reportto publish the counters as MoQ broadcasts. - Report
- The per-broadcast detail returned by
Registry::report: one traffic entry per(broadcast, tier)and one session entry per(tier, root). Entries are unordered. - Session
- Per-connection stats context, created via
Handle::session. - Session
Entry - One
(tier, root)row of aReport. - Snapshot
- A point-in-time, host-level rollup of a registry’s counters, returned
by
Registry::snapshot. - Tier
- Traffic-class label that selects which counter set a session’s bumps record
in, so a single
Registrycan split customer-facing, cluster-peer, regional, etc. traffic. Each tracked broadcast keeps a per-tier counter set on both its publisher and subscriber sides. - Traffic
- A cumulative traffic counter readout for one slice (a broadcast on a
(tier, role), or any sum of such slices). - Traffic
Entry - One
(broadcast, tier)row of aReport.