@@ -158,7 +158,8 @@ tls.disable_verify = true
158158
159159Per-node stats publishing. When enabled, the relay publishes a single
160160` <prefix>/node/<node> ` broadcast (or ` <prefix>/node ` when ` node ` is unset)
161- carrying JSON snapshots of every broadcast it's currently serving.
161+ carrying JSON snapshots of the broadcasts it's currently serving and of the
162+ sessions currently connected to it.
162163
163164``` toml
164165[stats ]
@@ -178,21 +179,24 @@ interval = 1
178179node = " sjc/1"
179180```
180181
181- Each stats broadcast carries four tracks, one per ` (tier, role) ` pair:
182+ Each stats broadcast carries four per-broadcast tracks, one per
183+ ` (tier, role) ` pair, plus two session tracks (one per tier):
182184
183185| Track | What it covers |
184186| -----------------------------| ---------------------------------------------|
185187| ` publisher.json ` | external (e.g. customer) egress |
186188| ` subscriber.json ` | external ingress |
187189| ` internal/publisher.json ` | internal (e.g. mTLS cluster peer) egress |
188190| ` internal/subscriber.json ` | internal ingress |
191+ | ` sessions.json ` | external connected sessions, keyed by root |
192+ | ` internal/sessions.json ` | internal connected sessions, keyed by root |
189193
190- Each frame is a JSON object mapping broadcast path to a cumulative
191- counter snapshot. An entry surfaces on any tick where the broadcast is
192- live (any open counter still exceeds its ` *_closed ` counterpart, so a
193- subscription could begin at any moment) or its snapshot changed since the
194- previous tick. Once every counter equals its ` *_closed ` counterpart no
195- traffic can flow, so the entry is dropped:
194+ Each per-broadcast frame is a JSON object mapping broadcast path to a
195+ cumulative counter snapshot. An entry surfaces on any tick where the
196+ broadcast is live (any open counter still exceeds its ` *_closed `
197+ counterpart, so a subscription could begin at any moment) or its snapshot
198+ changed since the previous tick. Once every counter equals its ` *_closed `
199+ counterpart no traffic can flow, so the entry is dropped:
196200
197201``` json
198202{
@@ -228,6 +232,22 @@ Field semantics:
228232- ` bytes ` / ` frames ` / ` groups ` : cumulative payload counters from the
229233 session loops (both the ` moq-lite ` and IETF ` moq-transport ` paths).
230234
235+ The session tracks (` sessions.json ` , ` internal/sessions.json ` ) instead map
236+ each auth root to a ` { sessions, sessions_closed } ` snapshot. ` sessions `
237+ bumps when a session authenticated under that root connects and
238+ ` sessions_closed ` when it disconnects, so ` sessions - sessions_closed ` is
239+ the number of sessions currently connected under the root. This counts
240+ presence regardless of whether any data flows, so a client connected to
241+ e.g. ` /acme ` is billable even while idle. A root entry is emitted while live
242+ or on the tick it changed, then dropped once no session under it remains:
243+
244+ ``` json
245+ {
246+ "acme" : { "sessions" : 3 , "sessions_closed" : 1 },
247+ "globex" : { "sessions" : 1 , "sessions_closed" : 0 }
248+ }
249+ ```
250+
231251Tier, role, and node are implied by the track and broadcast paths, so
232252they aren't repeated inside the frame. Counters are cumulative and
233253strictly monotonic; a counter going * backwards* across successive
0 commit comments