Skip to content

feat: sample str0m stats into per-second telemetry deltas (LUM-553) - #18

Merged
FrekiManagarm merged 2 commits into
mainfrom
feat/lum-553-stats-sampling
Nov 7, 2026
Merged

FrekiManagarm merged 2 commits into
mainfrom
feat/lum-553-stats-sampling

Conversation

@FrekiManagarm

@FrekiManagarm FrekiManagarm commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Closes the SFU-side instrumentation of LUM-553: per participant and per leg, jitter, loss, RTT, NACK/PLI/FIR counters and transport totals now reach telemetry.track_samples / telemetry.peer_samples as a per-second time series. This is Task 7 of docs/plans/2026-08-30-db-self-hosted-rust.md.

  • str0m stats enabled. PeerConnection::new takes the sample interval (telemetry.sample_interval, 1 s by default). str0m disables stats by default, which is why jitter/loss/RTT were never measured.
  • telemetry::sampler: pure delta arithmetic. There is no delta on the first reading, a counter going backwards clamps to zero, and jitter is converted from RTP clock units to ms (a zero clock rate gives None, never inf).
  • Transport → session: new TrackStats, PeerStats and IceState events. Egress stats are ignored on purpose because they would double count.
  • Session pump: records TrackSample, PeerSample, TrackCodec and ICE state/events.

Deviations from the plan

  • Samples are keyed by occupancy, not connection (Task 6 review, finding 3), and are only written for published tracks. The new Telemetry::published_track never mints an id, so no orphan track_id is produced.
  • The codec is recorded on the 1 Hz stats tick, not per packet. The only per-packet cost is one HashMap<Mid, _> lookup.
  • The clock rate is derived from the media kind, as to_packet already does, so no per-packet registry is needed.
  • str0m 0.23 has no ICE Failed state, so IceFailed has no emitter.

Overhead (cargo bench --bench sampling)

The instrumentation costs 20–24 ns per packet, which is 2.5–4 % of the 580–900 ns fanout and about 0.02 % of a core at 50 peers. Sampling itself costs ~60 ns per track per second and runs off the hot path.

Relation to the monorepo branch

origin/feature/lum-553 holds the same work done in the former monorepo (apps/sfu, unrelated history). It was never ported to this repo. This PR re-implements it on the current tree and ports its bench. That branch is left untouched.

Known gap

A peer switching rooms gets no TrackPublished in its new occupancy, so no track samples are written after the switch. This predates this PR and is tracked in LUM-708.

Test plan

  • cargo test: 158 passed, including 8 sampler unit tests, a published_track test, and an end-to-end test in tests/room.rs where a real ICE/DTLS/SRTP session yields ≥ 2 non-zero video deltas with jitter in ms. That test fails when stats are disabled (checked).
  • cargo clippy --all-targets -- -D warnings
  • cargo fmt --check
  • Run against Postgres (SFU_DATABASE_URL) and check rows in telemetry.track_samples

Enable str0m statistics (SFU_* sample interval, 1 s by default) and turn
its cumulative counters into per-second deltas persisted as TrackSample
and PeerSample: bytes, packets, NACK/PLI/FIR, jitter in ms, loss, RTT,
transport totals and BWE. ICE state transitions are recorded too.

- telemetry::sampler: pure delta arithmetic (no delta on first reading,
  backwards counters clamp to zero, jitter converted from RTP clock units)
- samples are keyed by occupancy and only written for published tracks,
  so no orphan track_id is ever minted
- the codec is recorded on the 1 Hz stats tick, not per packet
- end-to-end test: a real ICE/DTLS/SRTP session yields a time series
LUM-553 requires the collection not to degrade what it measures. Ported
from the monorepo bench (3e43fae), adapted to the one per-packet lookup
left: codecs.entry(mid) in the transport pump.

Measured: 20-24 ns per packet, i.e. 2.5-4% of the 580-900 ns fanout,
about 0.02% of a core at 50 peers. Sampling costs ~60 ns per track per
second, off the hot path.
@FrekiManagarm
FrekiManagarm force-pushed the feat/lum-553-stats-sampling branch from 5efce3b to 362ff36 Compare November 3, 2026 23:48
@FrekiManagarm FrekiManagarm self-assigned this Nov 7, 2026
@FrekiManagarm FrekiManagarm added the enhancement New feature or request label Nov 7, 2026
@FrekiManagarm
FrekiManagarm merged commit 46ade72 into main Nov 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant