mirror of
https://github.com/jech/galene.git
synced 2024-12-22 15:25:48 +01:00
Move stats code into its own module.
Move RTP-specific code into its own file.
This commit is contained in:
parent
813d89b60d
commit
7ce61a1100
4 changed files with 171 additions and 154 deletions
74
rtpstats.go
Normal file
74
rtpstats.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"sfu/rtptime"
|
||||
"sfu/stats"
|
||||
)
|
||||
|
||||
func (c *webClient) GetStats() *stats.Client {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
cs := stats.Client{
|
||||
Id: c.id,
|
||||
}
|
||||
|
||||
for _, up := range c.up {
|
||||
conns := stats.Conn{
|
||||
Id: up.id,
|
||||
}
|
||||
tracks := up.getTracks()
|
||||
for _, t := range tracks {
|
||||
expected, lost, _, _ := t.cache.GetStats(false)
|
||||
if expected == 0 {
|
||||
expected = 1
|
||||
}
|
||||
loss := uint8(lost * 100 / expected)
|
||||
jitter := time.Duration(t.jitter.Jitter()) *
|
||||
(time.Second / time.Duration(t.jitter.HZ()))
|
||||
rate, _ := t.rate.Estimate()
|
||||
conns.Tracks = append(conns.Tracks, stats.Track{
|
||||
Bitrate: uint64(rate) * 8,
|
||||
Loss: loss,
|
||||
Jitter: jitter,
|
||||
})
|
||||
}
|
||||
cs.Up = append(cs.Up, conns)
|
||||
}
|
||||
sort.Slice(cs.Up, func(i, j int) bool {
|
||||
return cs.Up[i].Id < cs.Up[j].Id
|
||||
})
|
||||
|
||||
jiffies := rtptime.Jiffies()
|
||||
for _, down := range c.down {
|
||||
conns := stats.Conn{
|
||||
Id: down.id,
|
||||
MaxBitrate: down.GetMaxBitrate(jiffies),
|
||||
}
|
||||
for _, t := range down.tracks {
|
||||
rate, _ := t.rate.Estimate()
|
||||
rtt := rtptime.ToDuration(atomic.LoadUint64(&t.rtt),
|
||||
rtptime.JiffiesPerSec)
|
||||
loss, jitter := t.stats.Get(jiffies)
|
||||
j := time.Duration(jitter) * time.Second /
|
||||
time.Duration(t.track.Codec().ClockRate)
|
||||
conns.Tracks = append(conns.Tracks, stats.Track{
|
||||
Bitrate: uint64(rate) * 8,
|
||||
MaxBitrate: t.maxBitrate.Get(jiffies),
|
||||
Loss: uint8(uint32(loss) * 100 / 256),
|
||||
Rtt: rtt,
|
||||
Jitter: j,
|
||||
})
|
||||
}
|
||||
cs.Down = append(cs.Down, conns)
|
||||
}
|
||||
sort.Slice(cs.Down, func(i, j int) bool {
|
||||
return cs.Down[i].Id < cs.Down[j].Id
|
||||
})
|
||||
|
||||
return &cs
|
||||
}
|
131
stats.go
131
stats.go
|
@ -1,131 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"sfu/group"
|
||||
"sfu/rtptime"
|
||||
)
|
||||
|
||||
type groupStats struct {
|
||||
name string
|
||||
clients []clientStats
|
||||
}
|
||||
|
||||
type clientStats struct {
|
||||
id string
|
||||
up, down []connStats
|
||||
}
|
||||
|
||||
type connStats struct {
|
||||
id string
|
||||
maxBitrate uint64
|
||||
tracks []trackStats
|
||||
}
|
||||
|
||||
type trackStats struct {
|
||||
bitrate uint64
|
||||
maxBitrate uint64
|
||||
loss uint8
|
||||
rtt time.Duration
|
||||
jitter time.Duration
|
||||
}
|
||||
|
||||
func getGroupStats() []groupStats {
|
||||
names := group.GetNames()
|
||||
|
||||
gs := make([]groupStats, 0, len(names))
|
||||
for _, name := range names {
|
||||
g := group.Get(name)
|
||||
if g == nil {
|
||||
continue
|
||||
}
|
||||
clients := g.GetClients(nil)
|
||||
stats := groupStats{
|
||||
name: name,
|
||||
clients: make([]clientStats, 0, len(clients)),
|
||||
}
|
||||
for _, c := range clients {
|
||||
c, ok := c.(*webClient)
|
||||
if ok {
|
||||
cs := getClientStats(c)
|
||||
stats.clients = append(stats.clients, cs)
|
||||
}
|
||||
}
|
||||
sort.Slice(stats.clients, func(i, j int) bool {
|
||||
return stats.clients[i].id < stats.clients[j].id
|
||||
})
|
||||
gs = append(gs, stats)
|
||||
}
|
||||
sort.Slice(gs, func(i, j int) bool {
|
||||
return gs[i].name < gs[j].name
|
||||
})
|
||||
|
||||
return gs
|
||||
}
|
||||
|
||||
func getClientStats(c *webClient) clientStats {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
cs := clientStats{
|
||||
id: c.id,
|
||||
}
|
||||
|
||||
for _, up := range c.up {
|
||||
conns := connStats{
|
||||
id: up.id,
|
||||
}
|
||||
tracks := up.getTracks()
|
||||
for _, t := range tracks {
|
||||
expected, lost, _, _ := t.cache.GetStats(false)
|
||||
if expected == 0 {
|
||||
expected = 1
|
||||
}
|
||||
loss := uint8(lost * 100 / expected)
|
||||
jitter := time.Duration(t.jitter.Jitter()) *
|
||||
(time.Second / time.Duration(t.jitter.HZ()))
|
||||
rate, _ := t.rate.Estimate()
|
||||
conns.tracks = append(conns.tracks, trackStats{
|
||||
bitrate: uint64(rate) * 8,
|
||||
loss: loss,
|
||||
jitter: jitter,
|
||||
})
|
||||
}
|
||||
cs.up = append(cs.up, conns)
|
||||
}
|
||||
sort.Slice(cs.up, func(i, j int) bool {
|
||||
return cs.up[i].id < cs.up[j].id
|
||||
})
|
||||
|
||||
jiffies := rtptime.Jiffies()
|
||||
for _, down := range c.down {
|
||||
conns := connStats{
|
||||
id: down.id,
|
||||
maxBitrate: down.GetMaxBitrate(jiffies),
|
||||
}
|
||||
for _, t := range down.tracks {
|
||||
rate, _ := t.rate.Estimate()
|
||||
rtt := rtptime.ToDuration(atomic.LoadUint64(&t.rtt),
|
||||
rtptime.JiffiesPerSec)
|
||||
loss, jitter := t.stats.Get(jiffies)
|
||||
j := time.Duration(jitter) * time.Second /
|
||||
time.Duration(t.track.Codec().ClockRate)
|
||||
conns.tracks = append(conns.tracks, trackStats{
|
||||
bitrate: uint64(rate) * 8,
|
||||
maxBitrate: t.maxBitrate.Get(jiffies),
|
||||
loss: uint8(uint32(loss) * 100 / 256),
|
||||
rtt: rtt,
|
||||
jitter: j,
|
||||
})
|
||||
}
|
||||
cs.down = append(cs.down, conns)
|
||||
}
|
||||
sort.Slice(cs.down, func(i, j int) bool {
|
||||
return cs.down[i].id < cs.down[j].id
|
||||
})
|
||||
|
||||
return cs
|
||||
}
|
73
stats/stats.go
Normal file
73
stats/stats.go
Normal file
|
@ -0,0 +1,73 @@
|
|||
package stats
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"sfu/group"
|
||||
)
|
||||
|
||||
type GroupStats struct {
|
||||
Name string
|
||||
Clients []*Client
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
Id string
|
||||
Up, Down []Conn
|
||||
}
|
||||
|
||||
type Statable interface {
|
||||
GetStats() *Client
|
||||
}
|
||||
|
||||
type Conn struct {
|
||||
Id string
|
||||
MaxBitrate uint64
|
||||
Tracks []Track
|
||||
}
|
||||
|
||||
type Track struct {
|
||||
Bitrate uint64
|
||||
MaxBitrate uint64
|
||||
Loss uint8
|
||||
Rtt time.Duration
|
||||
Jitter time.Duration
|
||||
}
|
||||
|
||||
func GetGroups() []GroupStats {
|
||||
names := group.GetNames()
|
||||
|
||||
gs := make([]GroupStats, 0, len(names))
|
||||
for _, name := range names {
|
||||
g := group.Get(name)
|
||||
if g == nil {
|
||||
continue
|
||||
}
|
||||
clients := g.GetClients(nil)
|
||||
stats := GroupStats{
|
||||
Name: name,
|
||||
Clients: make([]*Client, 0, len(clients)),
|
||||
}
|
||||
for _, c := range clients {
|
||||
s, ok := c.(Statable)
|
||||
if ok {
|
||||
cs := s.GetStats()
|
||||
stats.Clients = append(stats.Clients, cs)
|
||||
} else {
|
||||
stats.Clients = append(stats.Clients,
|
||||
&Client{Id: c.Id()},
|
||||
)
|
||||
}
|
||||
}
|
||||
sort.Slice(stats.Clients, func(i, j int) bool {
|
||||
return stats.Clients[i].Id < stats.Clients[j].Id
|
||||
})
|
||||
gs = append(gs, stats)
|
||||
}
|
||||
sort.Slice(gs, func(i, j int) bool {
|
||||
return gs[i].Name < gs[j].Name
|
||||
})
|
||||
|
||||
return gs
|
||||
}
|
47
webserver.go
47
webserver.go
|
@ -21,6 +21,7 @@ import (
|
|||
|
||||
"sfu/disk"
|
||||
"sfu/group"
|
||||
"sfu/stats"
|
||||
)
|
||||
|
||||
var server *http.Server
|
||||
|
@ -50,7 +51,7 @@ func webserver() {
|
|||
IdleTimeout: 120 * time.Second,
|
||||
}
|
||||
server.RegisterOnShutdown(func() {
|
||||
group.Range(func (g *group.Group) bool {
|
||||
group.Range(func(g *group.Group) bool {
|
||||
go g.Shutdown("server is shutting down")
|
||||
return true
|
||||
})
|
||||
|
@ -225,7 +226,7 @@ func statsHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
stats := getGroupStats()
|
||||
ss := stats.GetGroups()
|
||||
|
||||
fmt.Fprintf(w, "<!DOCTYPE html>\n<html><head>\n")
|
||||
fmt.Fprintf(w, "<title>Stats</title>\n")
|
||||
|
@ -242,51 +243,51 @@ func statsHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return err
|
||||
}
|
||||
|
||||
printTrack := func(w io.Writer, t trackStats) {
|
||||
printTrack := func(w io.Writer, t stats.Track) {
|
||||
fmt.Fprintf(w, "<tr><td></td><td></td><td></td>")
|
||||
fmt.Fprintf(w, "<td>")
|
||||
printBitrate(w, t.bitrate, t.maxBitrate)
|
||||
printBitrate(w, t.Bitrate, t.MaxBitrate)
|
||||
fmt.Fprintf(w, "</td>")
|
||||
fmt.Fprintf(w, "<td>%d%%</td>",
|
||||
t.loss,
|
||||
t.Loss,
|
||||
)
|
||||
fmt.Fprintf(w, "<td>")
|
||||
if t.rtt > 0 {
|
||||
fmt.Fprintf(w, "%v", t.rtt)
|
||||
if t.Rtt > 0 {
|
||||
fmt.Fprintf(w, "%v", t.Rtt)
|
||||
}
|
||||
if t.jitter > 0 {
|
||||
fmt.Fprintf(w, "±%v", t.jitter)
|
||||
if t.Jitter > 0 {
|
||||
fmt.Fprintf(w, "±%v", t.Jitter)
|
||||
}
|
||||
fmt.Fprintf(w, "</td>")
|
||||
fmt.Fprintf(w, "</tr>")
|
||||
}
|
||||
|
||||
for _, gs := range stats {
|
||||
fmt.Fprintf(w, "<p>%v</p>\n", html.EscapeString(gs.name))
|
||||
for _, gs := range ss {
|
||||
fmt.Fprintf(w, "<p>%v</p>\n", html.EscapeString(gs.Name))
|
||||
fmt.Fprintf(w, "<table>")
|
||||
for _, cs := range gs.clients {
|
||||
fmt.Fprintf(w, "<tr><td>%v</td></tr>\n", cs.id)
|
||||
for _, up := range cs.up {
|
||||
for _, cs := range gs.Clients {
|
||||
fmt.Fprintf(w, "<tr><td>%v</td></tr>\n", cs.Id)
|
||||
for _, up := range cs.Up {
|
||||
fmt.Fprintf(w, "<tr><td></td><td>Up</td><td>%v</td>",
|
||||
up.id)
|
||||
if up.maxBitrate > 0 {
|
||||
up.Id)
|
||||
if up.MaxBitrate > 0 {
|
||||
fmt.Fprintf(w, "<td>%v</td>",
|
||||
up.maxBitrate)
|
||||
up.MaxBitrate)
|
||||
}
|
||||
fmt.Fprintf(w, "</tr>\n")
|
||||
for _, t := range up.tracks {
|
||||
for _, t := range up.Tracks {
|
||||
printTrack(w, t)
|
||||
}
|
||||
}
|
||||
for _, down := range cs.down {
|
||||
for _, down := range cs.Down {
|
||||
fmt.Fprintf(w, "<tr><td></td><td>Down</td><td> %v</td>",
|
||||
down.id)
|
||||
if down.maxBitrate > 0 {
|
||||
down.Id)
|
||||
if down.MaxBitrate > 0 {
|
||||
fmt.Fprintf(w, "<td>%v</td>",
|
||||
down.maxBitrate)
|
||||
down.MaxBitrate)
|
||||
}
|
||||
fmt.Fprintf(w, "</tr>\n")
|
||||
for _, t := range down.tracks {
|
||||
for _, t := range down.Tracks {
|
||||
printTrack(w, t)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue