diff --git a/pkg/telemetry/statsworker.go b/pkg/telemetry/statsworker.go index 84cbc6020..a5d816ffb 100644 --- a/pkg/telemetry/statsworker.go +++ b/pkg/telemetry/statsworker.go @@ -71,6 +71,9 @@ type StatsWorker struct { outgoingPerTrack map[livekit.TrackID]Stats incomingPerTrack map[livekit.TrackID]Stats + + // clean up stats for unpublished tracks + closedTracks map[livekit.TrackID]bool } func newStatsWorker( @@ -89,6 +92,7 @@ func newStatsWorker( outgoingPerTrack: make(map[livekit.TrackID]Stats), incomingPerTrack: make(map[livekit.TrackID]Stats), + closedTracks: make(map[livekit.TrackID]bool), } return s } @@ -113,6 +117,16 @@ func (s *StatsWorker) OnTrackStat(trackID livekit.TrackID, direction livekit.Str } } +func (s *StatsWorker) CleanUpTrackStats() { + if len(s.closedTracks) > 0 { + for trackID := range s.closedTracks { + delete(s.outgoingPerTrack, trackID) + delete(s.incomingPerTrack, trackID) + } + s.closedTracks = make(map[livekit.TrackID]bool) + } +} + func (s *StatsWorker) Update() { ts := timestamppb.Now() @@ -122,6 +136,7 @@ func (s *StatsWorker) Update() { if len(stats) > 0 { s.t.Report(s.ctx, stats) } + s.CleanUpTrackStats() } func (s *StatsWorker) collectDownstreamStats(ts *timestamppb.Timestamp, stats []*livekit.AnalyticsStat) []*livekit.AnalyticsStat { @@ -315,6 +330,10 @@ func (stats *Stats) computeDeltaStats() *livekit.AnalyticsStat { deltaStats.TotalNacks = cur.TotalNacks - prev.TotalNacks deltaStats.TotalFirs = cur.TotalFirs - prev.TotalFirs deltaStats.TotalPacketsLost = cur.TotalPacketsLost - prev.TotalPacketsLost + // https://datatracker.ietf.org/doc/html/rfc3550#page-83 + if int32(deltaStats.TotalPacketsLost) < 0 { + deltaStats.TotalPacketsLost = 0 + } deltaStats.TotalPrimaryPackets = cur.TotalPrimaryPackets - prev.TotalPrimaryPackets deltaStats.TotalRetransmitPackets = cur.TotalRetransmitPackets - prev.TotalRetransmitPackets deltaStats.TotalPaddingPackets = cur.TotalPaddingPackets - prev.TotalPaddingPackets @@ -345,3 +364,7 @@ func (stats *Stats) computeDeltaStats() *livekit.AnalyticsStat { } return deltaStats.ToAnalyticsStats(videoLayer) } + +func (s *StatsWorker) RemoveStats(trackID livekit.TrackID) { + s.closedTracks[trackID] = true +} diff --git a/pkg/telemetry/telemetryserviceinternalevents.go b/pkg/telemetry/telemetryserviceinternalevents.go index 9913c3f0b..37b230c3f 100644 --- a/pkg/telemetry/telemetryserviceinternalevents.go +++ b/pkg/telemetry/telemetryserviceinternalevents.go @@ -126,6 +126,7 @@ func (t *telemetryServiceInternal) TrackUnpublished(ctx context.Context, partici if w != nil { roomID = w.roomID roomName = w.roomName + w.RemoveStats(livekit.TrackID(track.GetSid())) } prometheus.SubPublishedTrack(track.Type.String())