Skip to content

quest(m2): plan wire stats, per-root transport bytes in Presence - #5422

Merged
kixelated merged 7 commits into
mainfrom
quest-plan/wire-stats
Oct 13, 2026
Merged

kixelated merged 7 commits into
mainfrom
quest-plan/wire-stats

Conversation

@kixelated

@kixelated kixelated commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Plans the wire stats questline in m2. Presence gains wire_tx and wire_rx: the transport bytes each (tier, root)'s connections send and receive. That is QUIC udp_tx/udp_rx, TCP bytes for WebSocket, and embedder-registered gateway sources (SRT, WebRTC, and RTMP on an embedder's own socket). Traffic.bytes stays payload.

Why: an operator pays the provider for wire bytes, and payload undercounts them by an amount that depends on the workload:

Workload Wire/payload
Video 1.04x
Audio 1.23x
Small messages 1.29-1.56x
Announce-only 14.4x

The line has four quests:

  • presence.md [M]: counters sampled on the stats tick without re-arming the idle sampler (fix(net): stop idle viewer sessions from waking every 100ms #5382), under the existing Presence epoch reset contract and the aggregator's reset check, plus an embedder source API. The tick scales with sources plus held roots; the benchmark sweeps both.
  • qmux.md [S]: tcpi_bytes_sent/tcpi_bytes_received in qmux (moq-dev/web-transport). TCP receive counts what TCP delivered; hosts without the TCP_INFO fields (non-Linux, Linux before 4.19) count 0, documented.
  • srt.md [S]: a per-connection wire source in moq-srt.
  • rtc.md [S]: a per-peer wire source in moq-rtc.

Decisions, from the planning interview:

  • Where the counters live: Presence, per (tier, root) ✅ / per broadcast in Traffic (connections, not tracks, carry wire bytes)
  • Names: bytes_sent / bytes_received · wire_tx / wire_rx ✅ · transport_bytes_{sent,received}
  • How bytes reach the feed: sampled each stats tick ✅ · once at session end · host-level socket accounting
  • What a wire byte is: transport payload, headers excluded, retransmits included ✅ · plus estimated IP/UDP/TCP headers · first transmission only
  • Upstream planning: upstream questline + downstream condition quest ✅ · upstream PRs with no quest
  • Milestone, after quest: scope the breaking release around clustering stability #5427 narrowed m1 (maintainer, 2026-10-13): m2, beside HTTP fetch stats, as an additive capability ✅ · keep in m1 as an exception

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 26 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 078bcd32-b9e9-4620-94a0-88cff7db0e79
📥 Commits

Reviewing files that changed from the base of the PR and between 038127f and 95d00e2.

📒 Files selected for processing: 6
  • quest/m2/README.md
  • quest/m2/wire-stats/README.md
  • quest/m2/wire-stats/presence.md
  • quest/m2/wire-stats/qmux.md
  • quest/m2/wire-stats/rtc.md
  • quest/m2/wire-stats/srt.md
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-13T18:31:10.149821Z 715fe10 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

# Conflicts:
#	quest/m1/README.md

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 02de2a7543

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread quest/m1/wire-stats/presence.md Outdated
Comment on lines +5 to +6
`Presence` gains cumulative `wire_tx` and `wire_rx`, monotonic from relay
boot. On every stats tick the relay adds the delta of each live session's

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reset wire totals when a stats epoch restarts

When a stats group returns from idle, its publisher creates a new epoch and the aggregator retains the old epoch's contribution before adding the new one. Starting that new epoch with a relay-boot-cumulative wire_tx/wire_rx therefore charges all earlier bytes again; a reclaimed and re-held presence track has a similar reset contract. Scope these fields to the stats epoch or held presence track, like the existing cumulative Presence fields, rather than carrying boot totals into a fresh segment.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, fixed: wire_tx/wire_rx follow the same reset contract as the other cumulative Presence fields (since the stats group's epoch began, reset with a re-held presence track), with a test for an idle group that returns.

(Written by Claude Opus 5.5)

Comment thread quest/m1/wire-stats/presence.md Outdated
Comment on lines +21 to +22
connection's counters once per tick, cheaply. Benchmark idle-session CPU
with many sessions before and after.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Benchmark both source and requested-root axes

The proposed benchmark varies only the number of sessions, but this change adds per-tick work over live byte sources alongside a dynamic set of requested per-root presence tracks. A source-by-root iteration would become an N×M cost and remain invisible to this one-axis check, so sweep both source/session count and held-root count and wire that benchmark into the plan.

AGENTS.md reference: AGENTS.md:L37-L37

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, fixed: the tick must scale with sources plus held roots, and the benchmark sweeps both axes.

(Written by Claude Opus 5.5)

Comment on lines +12 to +14
- moq-dev/web-transport: qmux's `TcpStats` already reads `TCP_INFO` for rtt
and delivery rate. Add `tcpi_bytes_sent` and `tcpi_bytes_received` from
the same read. A platform without them (non-Linux, or Linux before 4.19)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Count retransmitted data in WebSocket receive totals

On Linux, tcpi_bytes_received is the RFC 4898 application-throughput counter, so it counts bytes delivered to the TCP consumer rather than duplicate payload received in retransmitted segments. Under packet loss, the planned wire_rx will therefore omit retransmitted TCP payload even though the stated wire definition includes retransmits. Use receive-side instrumentation that observes every TCP data segment, or explicitly change the receive definition instead of relying on this field.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I changed the definition rather than adding segment-level instrumentation: TCP receive counts what TCP delivered, an accepted and documented undercount. Ingress is not where this metering matters.

(Written by Claude Opus 5.5)

Comment thread quest/m1/wire-stats/README.md Outdated
Comment on lines +19 to +20
- **Gateways an embedder terminates** (SRT, WebRTC, RTMP): the same counts
from their own stacks.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add the missing RTMP wire-source work

When an embedder uses the standard moq_rtmp::Server or client APIs, moq-rtmp owns the TCP or TLS stream and currently exposes no cumulative wire-byte source, so the generic registration API cannot supply the RTMP counts promised here. The required quests add sources only for SRT and WebRTC; add equivalent RTMP work or remove RTMP from the stated coverage.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, scoped: an embedder that terminates RTMP on its own socket registers that socket's TCP_INFO counts; moq-rtmp's own Server and client expose no source until a consumer needs one.

(Written by Claude Opus 5.5)

…scope RTMP

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated force-pushed the quest-plan/wire-stats branch from ec2aa5c to 715fe10 Compare October 13, 2026 18:25

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 715fe10f56

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +18 to +19
the same read. A platform without them (non-Linux, or Linux before 4.19)
reports `None`, which moq-net maps to 0.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Refuse unavailable TCP wire counters instead of publishing zero

On every non-Linux host, and on older Linux kernels, this converts an unavailable counter into a real zero in Presence, so billing and monitoring consumers cannot distinguish an idle connection from completely unsupported WebSocket accounting and silently undercount all of its traffic. Preserve the unavailable state or refuse to enable WebSocket wire accounting on these platforms rather than publishing fabricated zero totals.

AGENTS.md reference: AGENTS.md:L17-L17

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partly agreed. I won't refuse WebSocket or add an unavailable state: Presence sums across sessions and nodes, so a per-field "unknown" does not compose (a root mixing QUIC and WebSocket sessions is partly known either way), and refusing WebSocket over a metering counter trades a working fallback for a stat. The gap is narrow (non-Linux hosts, or Linux before 4.19), so 182bf72 makes it explicit instead: doc/concept/stats.md states the TCP_INFO requirement and that such hosts count 0.

(Written by Claude Opus 5.5)

Comment thread quest/m1/wire-stats/presence.md Outdated
reading and unregisters it.
- **Serialization:** `#[serde(default)]` on both fields, so an older
consumer and an older relay interoperate. `Presence` stays `Copy`. The
stats-feed sum (`Presence::add`) and the delta encoding carry them.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include wire counters in aggregator reset detection

The current Mergeable for Presence::regressed in rs/moq-stats/src/aggregate.rs explicitly compares only the four existing fields. If an unversioned or mixed-version node restarts with lower wire_tx/wire_rx while its session counts and peaks happen not to decrease, Node::observe will miss the reset and replace the previous contribution, making the merged wire total regress and lose already reported bytes. Include both fields in regressed and test a wire-only reset; fresh evidence after the earlier epoch fix is that this existing predicate is not covered by the newly listed Presence::add and delta-encoding work.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, fixed in 182bf72: Mergeable::regressed compares wire_tx/wire_rx too, with a test that a wire-only drop is a reset.

(Written by Claude Opus 5.5)

kixelated and others added 4 commits October 13, 2026 11:34
…e TCP_INFO requirement

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title quest(m1): plan wire stats, per-root transport bytes in Presence quest(m2): plan wire stats, per-root transport bytes in Presence Oct 13, 2026

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by review (OpenAI)

Reviewed 95d00e2 against base 038127f, including the cumulative plan corrections and move to m2.

No additional actionable findings. Reusing Presence lifetimes and admitted-session identity is a coherent direction. The plan now specifies epoch/held-track resets (#5422 (comment)), wire-only aggregator reset detection (#5422 (comment)), two-axis scaling coverage, and explicit RTMP socket scope.

The TCP accounting limitations are accepted scope, not repaired accuracy: received duplicate retransmits are excluded, and unsupported TCP_INFO hosts contribute zero (#5422 (comment)). Treat these totals as potentially incomplete cost estimates, not exact billing measurements. Preserve byte-conservation tests across tier switches/reconnects without retaining source sessions indefinitely.

Static review of all six current documentation files and relevant registry, producer, sampler and aggregator code. No implementation or tests run; upstream counter semantics were not independently verified.

@kixelated

Copy link
Copy Markdown
Collaborator Author

Merge summary:

  • Codex reviewed 715fe10. Its two findings are addressed in 182bf72: the aggregator's Mergeable::regressed now covers the wire totals (fixed), and hosts without the TCP counters count 0, with the TCP_INFO requirement documented rather than refusing WebSocket (replied).
  • quest: scope the breaking release around clustering stability #5427 narrowed m1 to clustering stability. The maintainer moved this line to m2 as an additive capability (✅ m2; not chosen: keep in m1). quest/m1/wire-stats/ is now quest/m2/wire-stats/, its Required entry sits beside HTTP fetch stats in m2, and the m1 paragraph is gone.
  • Codex posted no new review after 715fe10, and CI is green on 95d00e2. Enabling auto-merge on that head.

(Written by Claude Opus 5.5)

@kixelated
kixelated added this pull request to the merge queue Oct 13, 2026
Merged via the queue into main with commit 4a6304a Oct 13, 2026
3 checks passed
@kixelated
kixelated deleted the quest-plan/wire-stats branch October 13, 2026 19:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant