mirror of
https://github.com/livekit/livekit.git
synced 2026-03-31 21:55:41 +00:00
Dev debug info (#50)
This commit is contained in:
2
go.mod
2
go.mod
@@ -43,4 +43,4 @@ require (
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
)
|
||||
|
||||
replace github.com/pion/ion-sfu => github.com/livekit/ion-sfu v1.20.0
|
||||
replace github.com/pion/ion-sfu => github.com/livekit/ion-sfu v1.20.2
|
||||
|
||||
4
go.sum
4
go.sum
@@ -231,8 +231,8 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/lithammer/shortuuid/v3 v3.0.6 h1:pr15YQyvhiSX/qPxncFtqk+v4xLEpOZObbsY/mKrcvA=
|
||||
github.com/lithammer/shortuuid/v3 v3.0.6/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts=
|
||||
github.com/livekit/ion-sfu v1.20.0 h1:mLNunMgRF6+Bz+5/JrVgxQKE6umuN3vkkQu8IcVquYA=
|
||||
github.com/livekit/ion-sfu v1.20.0/go.mod h1:Wx6b4qGUjvSo1kGl+/fHl0ZF48g2IJOjzUFg0yCo9qY=
|
||||
github.com/livekit/ion-sfu v1.20.2 h1:fIvKl2biQUbIdVPgWgGaMXo8e3s9E9ActCvD5lSlVJo=
|
||||
github.com/livekit/ion-sfu v1.20.2/go.mod h1:Wx6b4qGUjvSo1kGl+/fHl0ZF48g2IJOjzUFg0yCo9qY=
|
||||
github.com/livekit/protocol v0.5.6 h1:vMUjYvJH2TD/WIjrXtG6aQl5fFrIj0/ZgIctQqmmwro=
|
||||
github.com/livekit/protocol v0.5.6/go.mod h1:wo3CGfYB7XMF8GoVJAfTARrYSP/ombi+sbLl6AYdKP0=
|
||||
github.com/lucsky/cuid v1.0.2 h1:z4XlExeoderxoPj2/dxKOyPxe9RCOu7yNq9/XWxIUMQ=
|
||||
|
||||
@@ -373,3 +373,32 @@ func (t *MediaTrack) sendDownTrackBindingReports(sub types.Participant) {
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (t *MediaTrack) DebugInfo() map[string]interface{} {
|
||||
info := map[string]interface{}{
|
||||
"ID": t.ID(),
|
||||
"SSRC": t.ssrc,
|
||||
"Kind": t.kind.String(),
|
||||
"PubMuted": t.muted.Get(),
|
||||
}
|
||||
|
||||
subscribedTrackInfo := make([]map[string]interface{}, 0)
|
||||
t.lock.RLock()
|
||||
for _, track := range t.subscribedTracks {
|
||||
dt := track.dt.DebugInfo()
|
||||
dt["PubMuted"] = track.pubMuted.Get()
|
||||
dt["SubMuted"] = track.subMuted.Get()
|
||||
subscribedTrackInfo = append(subscribedTrackInfo, dt)
|
||||
}
|
||||
t.lock.RUnlock()
|
||||
info["DownTracks"] = subscribedTrackInfo
|
||||
|
||||
if t.receiver != nil {
|
||||
receiverInfo := t.receiver.DebugInfo()
|
||||
for k, v := range receiverInfo {
|
||||
info[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
@@ -964,3 +964,52 @@ func (p *ParticipantImpl) rtcpSendWorker() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ParticipantImpl) DebugInfo() map[string]interface{} {
|
||||
info := map[string]interface{}{
|
||||
"ID": p.id,
|
||||
"State": p.State().String(),
|
||||
}
|
||||
|
||||
publishedTrackInfo := make(map[string]interface{})
|
||||
subscribedTrackInfo := make(map[string]interface{})
|
||||
pendingTrackInfo := make(map[string]interface{})
|
||||
|
||||
p.lock.RLock()
|
||||
for trackID, track := range p.publishedTracks {
|
||||
if mt, ok := track.(*MediaTrack); ok {
|
||||
publishedTrackInfo[trackID] = mt.DebugInfo()
|
||||
} else {
|
||||
publishedTrackInfo[trackID] = map[string]interface{}{
|
||||
"ID": track.ID(),
|
||||
"Kind": track.Kind().String(),
|
||||
"PubMuted": track.IsMuted(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for pubID, tracks := range p.subscribedTracks {
|
||||
trackInfo := make([]map[string]interface{}, 0, len(tracks))
|
||||
for _, track := range tracks {
|
||||
dt := track.DownTrack().DebugInfo()
|
||||
dt["SubMuted"] = track.IsMuted()
|
||||
trackInfo = append(trackInfo, dt)
|
||||
}
|
||||
subscribedTrackInfo[pubID] = trackInfo
|
||||
}
|
||||
|
||||
for clientID, track := range p.pendingTracks {
|
||||
pendingTrackInfo[clientID] = map[string]interface{}{
|
||||
"Sid": track.Sid,
|
||||
"Type": track.Type.String(),
|
||||
"Simulcast": track.Simulcast,
|
||||
}
|
||||
}
|
||||
p.lock.RUnlock()
|
||||
|
||||
info["PublishedTracks"] = publishedTrackInfo
|
||||
info["SubscribedTracks"] = subscribedTrackInfo
|
||||
info["PendingTracks"] = pendingTrackInfo
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
@@ -580,3 +580,20 @@ func (r *Room) audioUpdateWorker() {
|
||||
time.Sleep(time.Duration(r.audioConfig.UpdateInterval) * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Room) DebugInfo() map[string]interface{} {
|
||||
info := map[string]interface{}{
|
||||
"Name": r.Room.Name,
|
||||
"Sid": r.Room.Sid,
|
||||
"CreatedAt": r.Room.CreationTime,
|
||||
}
|
||||
|
||||
participants := r.GetParticipants()
|
||||
participantInfo := make(map[string]interface{})
|
||||
for _, p := range participants {
|
||||
participantInfo[p.Identity()] = p.DebugInfo()
|
||||
}
|
||||
info["Participants"] = participantInfo
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
@@ -78,6 +78,8 @@ type Participant interface {
|
||||
RemoveSubscribedTrack(participantId string, st SubscribedTrack)
|
||||
SubscriberPC() *webrtc.PeerConnection
|
||||
UpdateAfterActive() bool
|
||||
|
||||
DebugInfo() map[string]interface{}
|
||||
}
|
||||
|
||||
// PublishedTrack is the main interface representing a track published to the room
|
||||
|
||||
@@ -89,6 +89,16 @@ type FakeParticipant struct {
|
||||
connectedAtReturnsOnCall map[int]struct {
|
||||
result1 time.Time
|
||||
}
|
||||
DebugInfoStub func() map[string]interface{}
|
||||
debugInfoMutex sync.RWMutex
|
||||
debugInfoArgsForCall []struct {
|
||||
}
|
||||
debugInfoReturns struct {
|
||||
result1 map[string]interface{}
|
||||
}
|
||||
debugInfoReturnsOnCall map[int]struct {
|
||||
result1 map[string]interface{}
|
||||
}
|
||||
GetAudioLevelStub func() (uint8, bool)
|
||||
getAudioLevelMutex sync.RWMutex
|
||||
getAudioLevelArgsForCall []struct {
|
||||
@@ -788,6 +798,59 @@ func (fake *FakeParticipant) ConnectedAtReturnsOnCall(i int, result1 time.Time)
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeParticipant) DebugInfo() map[string]interface{} {
|
||||
fake.debugInfoMutex.Lock()
|
||||
ret, specificReturn := fake.debugInfoReturnsOnCall[len(fake.debugInfoArgsForCall)]
|
||||
fake.debugInfoArgsForCall = append(fake.debugInfoArgsForCall, struct {
|
||||
}{})
|
||||
stub := fake.DebugInfoStub
|
||||
fakeReturns := fake.debugInfoReturns
|
||||
fake.recordInvocation("DebugInfo", []interface{}{})
|
||||
fake.debugInfoMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub()
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1
|
||||
}
|
||||
return fakeReturns.result1
|
||||
}
|
||||
|
||||
func (fake *FakeParticipant) DebugInfoCallCount() int {
|
||||
fake.debugInfoMutex.RLock()
|
||||
defer fake.debugInfoMutex.RUnlock()
|
||||
return len(fake.debugInfoArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeParticipant) DebugInfoCalls(stub func() map[string]interface{}) {
|
||||
fake.debugInfoMutex.Lock()
|
||||
defer fake.debugInfoMutex.Unlock()
|
||||
fake.DebugInfoStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeParticipant) DebugInfoReturns(result1 map[string]interface{}) {
|
||||
fake.debugInfoMutex.Lock()
|
||||
defer fake.debugInfoMutex.Unlock()
|
||||
fake.DebugInfoStub = nil
|
||||
fake.debugInfoReturns = struct {
|
||||
result1 map[string]interface{}
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeParticipant) DebugInfoReturnsOnCall(i int, result1 map[string]interface{}) {
|
||||
fake.debugInfoMutex.Lock()
|
||||
defer fake.debugInfoMutex.Unlock()
|
||||
fake.DebugInfoStub = nil
|
||||
if fake.debugInfoReturnsOnCall == nil {
|
||||
fake.debugInfoReturnsOnCall = make(map[int]struct {
|
||||
result1 map[string]interface{}
|
||||
})
|
||||
}
|
||||
fake.debugInfoReturnsOnCall[i] = struct {
|
||||
result1 map[string]interface{}
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeParticipant) GetAudioLevel() (uint8, bool) {
|
||||
fake.getAudioLevelMutex.Lock()
|
||||
ret, specificReturn := fake.getAudioLevelReturnsOnCall[len(fake.getAudioLevelArgsForCall)]
|
||||
@@ -2430,6 +2493,8 @@ func (fake *FakeParticipant) Invocations() map[string][][]interface{} {
|
||||
defer fake.closeMutex.RUnlock()
|
||||
fake.connectedAtMutex.RLock()
|
||||
defer fake.connectedAtMutex.RUnlock()
|
||||
fake.debugInfoMutex.RLock()
|
||||
defer fake.debugInfoMutex.RUnlock()
|
||||
fake.getAudioLevelMutex.RLock()
|
||||
defer fake.getAudioLevelMutex.RUnlock()
|
||||
fake.getPublishedTracksMutex.RLock()
|
||||
|
||||
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
@@ -73,6 +74,7 @@ func NewLivekitServer(conf *config.Config,
|
||||
mux.HandleFunc("/", s.healthCheck)
|
||||
if conf.Development {
|
||||
mux.HandleFunc("/debug/goroutine", s.debugGoroutines)
|
||||
mux.HandleFunc("/debug/rooms", s.debugInfo)
|
||||
}
|
||||
|
||||
s.httpServer = &http.Server{
|
||||
@@ -222,6 +224,23 @@ func (s *LivekitServer) debugGoroutines(w http.ResponseWriter, r *http.Request)
|
||||
_ = pprof.Lookup("goroutine").WriteTo(w, 2)
|
||||
}
|
||||
|
||||
func (s *LivekitServer) debugInfo(w http.ResponseWriter, r *http.Request) {
|
||||
s.roomManager.lock.RLock()
|
||||
info := make([]map[string]interface{}, 0, len(s.roomManager.rooms))
|
||||
for _, room := range s.roomManager.rooms {
|
||||
info = append(info, room.DebugInfo())
|
||||
}
|
||||
s.roomManager.lock.RUnlock()
|
||||
|
||||
b, err := json.Marshal(info)
|
||||
if err != nil {
|
||||
w.WriteHeader(400)
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
} else {
|
||||
_, _ = w.Write(b)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *LivekitServer) healthCheck(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user