Observability
Metrics reference
Six metrics, read from RTCP as the media passes through the SFU. Each one is armed by default with the threshold below and a 30s debounce, per peer and — where the scope says so — per room.
Default thresholds
Section titled “Default thresholds”| Metric | Field | Unit | Threshold | Scope | What it breaks |
|---|---|---|---|---|---|
| Packet loss | packet_loss_ratio | ratio, shown as % | > 2% | peer, room | Choppy audio, frozen frames |
| Round-trip time | rtt_ms | milliseconds | > 200ms | peer | Participants talking over each other |
| Jitter | jitter_ms | milliseconds | > 30ms | peer | Growing jitter buffer, drifting latency |
| NACK ratio | nack_ratio | ratio, shown as % | > 5% | peer | Retransmission storms, saturated uplink |
| Freeze ratio | freeze_ratio | ratio, shown as % | > 1% | peer | Video the user calls broken |
| Bitrate | bitrate_kbps | kilobits per second | < 100kbps | peer, track, room | Encoder giving up entirely |
Packet loss [#packet_loss_ratio]
Section titled “Packet loss [#packet_loss_ratio]”Fraction of RTP packets the receiver reported missing over the interval, read from RTCP receiver reports. Above 2% sustained, audio artefacts become audible before video visibly breaks.
- Unit
- ratio, shown as %
- Default threshold
- > 2%
- Scope
- peer, room
What breaks: Choppy audio, frozen frames
Response: force audio-only for that peer, or drop it to a lower simulcast layer to reduce what has to survive the link.
Round-trip time [#rtt_ms]
Section titled “Round-trip time [#rtt_ms]”Round trip between the SFU and the peer, from RTCP sender/receiver report timestamps. Conversation stops feeling natural somewhere past 200ms one-way perceived latency.
- Unit
- milliseconds
- Default threshold
- > 200ms
- Scope
- peer
What breaks: Participants talking over each other
Response: check whether the peer fell back to a TURN relay, and whether a closer region exists for that user population.
Jitter [#jitter_ms]
Section titled “Jitter [#jitter_ms]”Variance in packet arrival timing. The receiver absorbs it by growing its jitter buffer, which trades latency for smoothness — so high jitter shows up as delay creeping upward rather than as loss.
- Unit
- milliseconds
- Default threshold
- > 30ms
- Scope
- peer
What breaks: Growing jitter buffer, drifting latency
Response: usually a network path problem rather than a bandwidth problem. Compare with loss before touching bitrate.
NACK ratio [#nack_ratio]
Section titled “NACK ratio [#nack_ratio]”Share of packets that had to be requested again. A rising NACK ratio is the earliest signal that a peer uplink is saturated — it moves before loss and before freeze ratio.
- Unit
- ratio, shown as %
- Default threshold
- > 5%
- Scope
- peer
What breaks: Retransmission storms, saturated uplink
Response: reduce the target bitrate for that publisher, or turn off the highest simulcast layer for the room.
Freeze ratio [#freeze_ratio]
Section titled “Freeze ratio [#freeze_ratio]”Share of the interval during which the decoder produced no new frame. This is the metric closest to what a participant actually complains about, which is why its threshold is the tightest.
- Unit
- ratio, shown as %
- Default threshold
- > 1%
- Scope
- peer
What breaks: Video the user calls broken
Response: if freeze is high while loss is low, look at the sender — encoder starvation and CPU pressure produce exactly this shape.
Bitrate [#bitrate_kbps]
Section titled “Bitrate [#bitrate_kbps]”Forwarded bitrate per track. Reported as a floor rather than a ceiling: a video track that collapses under 100kbps has effectively stopped being video.
- Unit
- kilobits per second
- Default threshold
- < 100kbps
- Scope
- peer, track, room
What breaks: Encoder giving up entirely
Response: check congestion control decisions and whether the publisher is CPU-bound before assuming the network.
Overriding a threshold
Section titled “Overriding a threshold”Thresholds live per project and per environment since v0.4.0. Set one and it applies to every room in that environment; alerts still debounce for 30s before firing.
PATCH /v1/projects/live-classroom/thresholds
{ "packet_loss_ratio": 0.03,
"rtt_ms": 250 }