Skip to content

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.

MetricFieldUnitThresholdScopeWhat it breaks
Packet losspacket_loss_ratioratio, shown as %> 2%peer, roomChoppy audio, frozen frames
Round-trip timertt_msmilliseconds> 200mspeerParticipants talking over each other
Jitterjitter_msmilliseconds> 30mspeerGrowing jitter buffer, drifting latency
NACK rationack_ratioratio, shown as %> 5%peerRetransmission storms, saturated uplink
Freeze ratiofreeze_ratioratio, shown as %> 1%peerVideo the user calls broken
Bitratebitrate_kbpskilobits per second< 100kbpspeer, track, roomEncoder giving up entirely
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
"packet_loss_ratio": 0.079,"packets_lost": 412,"packets_expected": 5215

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.

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
"rtt_ms": 284,"rtt_p95_ms": 331,"ice_candidate_type": "relay"

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_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
"jitter_ms": 42,"jitter_buffer_delay_ms": 180

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

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
"nack_ratio": 0.114,"nack_count": 1284,"retransmit_bytes": 482113

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

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
"freeze_ratio": 0.041,"freeze_count": 6,"total_freeze_duration_ms": 2460

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_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
"bitrate_kbps": 84,"target_bitrate_kbps": 1200,"codec": "vp8", "layer": "f"

What breaks: Encoder giving up entirely

Response: check congestion control decisions and whether the publisher is CPU-bound before assuming the network.

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 }