Expand description
Bounded node-level accounting for the PIX Exit.
Everything here is compiled unconditionally, including without the telemetry feature. Only the
instruments the numbers are eventually written to live behind the feature, in
crate::telemetry::pix. The split is deliberate: the delta arithmetic below is the part that
can be wrong in a way an operator would never notice — a gauge that fails to come back down, a
cycle counted twice — and a default cargo nextest run --lib must exercise it.
§Why aggregates rather than more labels
The two per-Session PIX gauges (hopr_session_pix_gate_mode, hopr_session_pix_recovery_progress)
answer questions about one Session. An operator’s questions are about the node: how much
predeposit service is exposed right now, whether egress is blocked on deposits or on share lag,
whether admission is refusing peers because the node is full or because their parameters are
wrong. Answering those by adding labels would make the view worse rather than better — every
session_id-labelled instrument stops reporting new Sessions after ~2000 of them (#8305), and
nothing retires the series.
So the aggregates carry no identifier at all. Every label value in this module comes from a closed enum, which is what makes that a property of the type system rather than a promise.
§The census, and why it is not inc/dec
SessionPixSupervisor recomputes
PixSessionSnapshot from its own live state on every turn, and
PixSessionTelemetry::publish applies the difference against what it last published. No
transition increments a live-set gauge directly.
That is what makes “gauges return to zero on every terminal path” structural instead of a matter of auditing call sites. A cycle that is retired, times out, is rolled back at admission, or disappears because its Session was dropped mid-turn is simply absent from the next census, and the delta that follows is the decrement. There is no path that can forget one, because there is no path that performs one.
Cumulative counters are the opposite case — they must not be recomputed, because their whole
value is that they survive the state they describe. Those are latched at the transition that
changes the source of truth (PixTurnEvents) and drained by the same publish.
Structs§
- PixCycle
Summary - What one cycle cost and recovered, observed once when it leaves the accounting front.
- PixGate
Block Episode - One episode of PIX egress being blocked, measured from first refusal until it ends.
- PixSession
Snapshot - One PIX Session’s contribution to the node-level live-set gauges.
- PixSession
Telemetry - One PIX Session’s share of the node-level aggregates, and the bookkeeping that keeps it exact.
- PixTurn
Events - Cycle lifecycle transitions latched by the supervisor since the last publish.
- Published 🔒
- What this handle has already accounted for.
Enums§
- Event
Scope 🔒 - How much of a latched batch a publish may emit.
- PixAdmission
Rejection - Why an incoming PIX Session was refused before it was established.
- PixCycle
Event - A cycle lifecycle transition worth a cumulative count.
- PixCycle
Outcome - How a cycle’s accounting ended.
- PixCycle
Phase - Supervisor phase of a retained SSA cycle.
- PixGate
Block - Why PIX egress stopped, as
hopr_pix_gate_blocks_totallabels it. - PixGate
Mode - Front-gate mode of a live PIX Session.
- PixShare
Kind - Which kind of accepted share a delta was.
- PixStall
Cause - Why a Session’s fill is not keeping up, as
hopr_pix_sessions_stalledlabels it.
Functions§
- apply_
delta 🔒 - Moves the live-set gauges from
fromtoto, either of which may be “no Session at all”. - emit_
cycle_ 🔒phase_ duration - emit_
cycle_ 🔒summary - emit_
cycles_ 🔒active - emit_
cycles_ 🔒total - emit_
deposits_ 🔒confirmed - emit_
deposits_ 🔒recovered - emit_
egress_ 🔒packets - emit_
gate_ 🔒block - emit_
gate_ 🔒block_ duration - emit_
predeposit_ 🔒exposure - emit_
sessions_ 🔒active - emit_
sessions_ 🔒stalled pub(crate)unlike its siblings, because this gauge has a second producer: the manager’sPixFillControlraisesPixStallCause::SurbStarved, which the supervisor cannot see. Routing it here rather than straight at the instrument keeps the metric to one emission point and onecfg, and lets both causes be asserted through theprobebelow.- emit_
shares_ 🔒total - record_
egress 🔒 - Counts packets admitted since the last flush, by what paid for them.
- record_
events 🔒 - record_
gate_ closed - Counts one refusal by a poisoned gate.
- sessions_
in 🔒 - 1 if
snapshotis a live Session inmode, else 0.