Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
galene
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
galene
Commits
3a6ade98
Commit
3a6ade98
authored
Apr 30, 2021
by
Juliusz Chroboczek
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Export stats as JSON.
parent
9b1d814b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
47 additions
and
95 deletions
+47
-95
README
README
+2
-2
rtpconn/rtpstats.go
rtpconn/rtpstats.go
+6
-9
stats/stats.go
stats/stats.go
+31
-12
webserver/webserver.go
webserver/webserver.go
+8
-72
No files found.
README
View file @
3a6ade98
...
...
@@ -163,8 +163,8 @@ with others, there is no need to go through the landing page.
Recordings can be accessed under `/recordings/groupname`. This is only
available to the administrator of the group.
Some statistics are available under `/stats
`. This is only available to
the server administrator.
Some statistics are available under `/stats
.json`. This is only available
t
o t
he server administrator.
## Side menu
...
...
rtpconn/rtpstats.go
View file @
3a6ade98
...
...
@@ -23,18 +23,15 @@ func (c *webClient) GetStats() *stats.Client {
tracks
:=
up
.
getTracks
()
for
_
,
t
:=
range
tracks
{
s
:=
t
.
cache
.
GetStats
(
false
)
var
loss
uint8
if
s
.
Expected
>
s
.
Received
{
loss
=
uint8
((
s
.
Expected
-
s
.
Received
)
*
100
/
s
.
Expected
)
}
loss
:=
float64
(
s
.
Expected
-
s
.
Received
)
/
float64
(
s
.
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
,
Jitter
:
stats
.
Duration
(
jitter
)
,
})
}
cs
.
Up
=
append
(
cs
.
Up
,
conns
)
...
...
@@ -59,9 +56,9 @@ func (c *webClient) GetStats() *stats.Client {
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
,
Loss
:
float64
(
loss
)
/
256.0
,
Rtt
:
stats
.
Duration
(
rtt
)
,
Jitter
:
stats
.
Duration
(
j
)
,
})
}
cs
.
Down
=
append
(
cs
.
Down
,
conns
)
...
...
stats/stats.go
View file @
3a6ade98
package
stats
import
(
"encoding/json"
"sort"
"time"
...
...
@@ -8,13 +9,14 @@ import (
)
type
GroupStats
struct
{
Name
string
Clients
[]
*
Client
Name
string
`json:"name"`
Clients
[]
*
Client
`json:"clients,omitempty"`
}
type
Client
struct
{
Id
string
Up
,
Down
[]
Conn
Id
string
`json:"id"`
Up
[]
Conn
`json:"up,omitempty"`
Down
[]
Conn
`json:"down,omitempty"`
}
type
Statable
interface
{
...
...
@@ -22,17 +24,34 @@ type Statable interface {
}
type
Conn
struct
{
Id
string
MaxBitrate
uint64
Tracks
[]
Track
Id
string
`json:"id"`
MaxBitrate
uint64
`json:"maxBitrate,omitempty"`
Tracks
[]
Track
`json:"tracks"`
}
type
Duration
time
.
Duration
func
(
d
Duration
)
MarshalJSON
()
([]
byte
,
error
)
{
s
:=
float64
(
d
)
/
float64
(
time
.
Millisecond
)
return
json
.
Marshal
(
s
)
}
func
(
d
*
Duration
)
UnmarshalJSON
(
buf
[]
byte
)
error
{
var
s
float64
err
:=
json
.
Unmarshal
(
buf
,
&
s
)
if
err
!=
nil
{
return
err
}
*
d
=
Duration
(
s
*
float64
(
time
.
Millisecond
))
return
nil
}
type
Track
struct
{
Bitrate
uint64
MaxBitrate
uint64
Loss
uint8
Rtt
time
.
Duration
Jitter
time
.
Duration
Bitrate
uint64
`json:"bitrate"`
MaxBitrate
uint64
`json:"maxBitrate,omitempty"`
Loss
float64
`json:"loss"`
Rtt
Duration
`json:"rtt,omitempty"`
Jitter
Duration
`json:"jitter,omitempty"`
}
func
GetGroups
()
[]
GroupStats
{
...
...
webserver/webserver.go
View file @
3a6ade98
...
...
@@ -47,9 +47,10 @@ func Serve(address string, dataDir string) error {
http
.
HandleFunc
(
"/recordings/"
,
recordingsHandler
)
http
.
HandleFunc
(
"/ws"
,
wsHandler
)
http
.
HandleFunc
(
"/public-groups.json"
,
publicHandler
)
http
.
HandleFunc
(
"/stats"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
statsHandler
(
w
,
r
,
dataDir
)
})
http
.
HandleFunc
(
"/stats.json"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
statsHandler
(
w
,
r
,
dataDir
)
})
s
:=
&
http
.
Server
{
Addr
:
address
,
...
...
@@ -361,81 +362,16 @@ func statsHandler(w http.ResponseWriter, r *http.Request, dataDir string) {
return
}
w
.
Header
()
.
Set
(
"content-type"
,
"
text/html; charset=utf-8
"
)
w
.
Header
()
.
Set
(
"content-type"
,
"
application/json
"
)
w
.
Header
()
.
Set
(
"cache-control"
,
"no-cache"
)
if
r
.
Method
==
"HEAD"
{
return
}
ss
:=
stats
.
GetGroups
()
fmt
.
Fprintf
(
w
,
"<!DOCTYPE html>
\n
<html><head>
\n
"
)
fmt
.
Fprintf
(
w
,
"<title>Stats</title>
\n
"
)
fmt
.
Fprintf
(
w
,
"<link rel=
\"
stylesheet
\"
type=
\"
text/css
\"
href=
\"
/common.css
\"
/>"
)
fmt
.
Fprintf
(
w
,
"<head><body>
\n
"
)
printBitrate
:=
func
(
w
io
.
Writer
,
rate
,
maxRate
uint64
)
error
{
var
err
error
if
maxRate
!=
0
&&
maxRate
!=
^
uint64
(
0
)
{
_
,
err
=
fmt
.
Fprintf
(
w
,
"%v/%v"
,
rate
,
maxRate
)
}
else
{
_
,
err
=
fmt
.
Fprintf
(
w
,
"%v"
,
rate
)
}
return
err
}
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
)
fmt
.
Fprintf
(
w
,
"</td>"
)
fmt
.
Fprintf
(
w
,
"<td>%d%%</td>"
,
t
.
Loss
,
)
fmt
.
Fprintf
(
w
,
"<td>"
)
if
t
.
Rtt
>
0
{
fmt
.
Fprintf
(
w
,
"%v"
,
t
.
Rtt
)
}
if
t
.
Jitter
>
0
{
fmt
.
Fprintf
(
w
,
"±%v"
,
t
.
Jitter
)
}
fmt
.
Fprintf
(
w
,
"</td>"
)
fmt
.
Fprintf
(
w
,
"</tr>"
)
}
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
{
fmt
.
Fprintf
(
w
,
"<tr><td></td><td>Up</td><td>%v</td>"
,
up
.
Id
)
if
up
.
MaxBitrate
>
0
{
fmt
.
Fprintf
(
w
,
"<td>%v</td>"
,
up
.
MaxBitrate
)
}
fmt
.
Fprintf
(
w
,
"</tr>
\n
"
)
for
_
,
t
:=
range
up
.
Tracks
{
printTrack
(
w
,
t
)
}
}
for
_
,
down
:=
range
cs
.
Down
{
fmt
.
Fprintf
(
w
,
"<tr><td></td><td>Down</td><td> %v</td>"
,
down
.
Id
)
if
down
.
MaxBitrate
>
0
{
fmt
.
Fprintf
(
w
,
"<td>%v</td>"
,
down
.
MaxBitrate
)
}
fmt
.
Fprintf
(
w
,
"</tr>
\n
"
)
for
_
,
t
:=
range
down
.
Tracks
{
printTrack
(
w
,
t
)
}
}
}
fmt
.
Fprintf
(
w
,
"</table>
\n
"
)
}
fmt
.
Fprintf
(
w
,
"</body></html>
\n
"
)
e
:=
json
.
NewEncoder
(
w
)
e
.
Encode
(
ss
)
return
}
var
wsUpgrader
=
websocket
.
Upgrader
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment