From 6947d87f9f1d03d340dc8f663138e1de104a7eed Mon Sep 17 00:00:00 2001
From: Zorglube <630192+zorglube@users.noreply.github.com>
Date: Sun, 14 Mar 2021 03:13:20 +0100
Subject: [PATCH] Stream Viewers minimal statistics.
---
chatclient.go | 11 +++++----
chatcommands.go | 4 +++-
handlers.go | 24 +++++++++++++++++--
stats.go | 63 +++++++++++++++++++++++++++++++++++++++++++------
4 files changed, 88 insertions(+), 14 deletions(-)
diff --git a/chatclient.go b/chatclient.go
index b843859..cfc6ac3 100644
--- a/chatclient.go
+++ b/chatclient.go
@@ -91,17 +91,20 @@ func (cl *Client) NewMsg(data common.ClientData) {
// because the /me command outputs to the messages
msg = addSpoilerTags(msg)
+ msgLen := len(msg)
+
// Don't send zero-length messages
- if len(msg) == 0 {
+ if msgLen == 0 {
return
}
if strings.HasPrefix(msg, "/") {
// is a command
- msg = msg[1:len(msg)]
+ msg = msg[1:msgLen]
fullcmd := strings.Split(msg, " ")
cmd := strings.ToLower(fullcmd[0])
- args := fullcmd[1:len(fullcmd)]
+ fullcmdLen := len(fullcmd)
+ args := fullcmd[1:fullcmdLen]
response, err := commands.RunCommand(cmd, args, cl)
if response != "" || err != nil {
@@ -136,7 +139,7 @@ func (cl *Client) NewMsg(data common.ClientData) {
}
// Trim long messages
- if len(msg) > 400 {
+ if msgLen > 400 {
msg = msg[0:400]
}
diff --git a/chatcommands.go b/chatcommands.go
index d7de741..0be866f 100644
--- a/chatcommands.go
+++ b/chatcommands.go
@@ -277,11 +277,13 @@ var commands = &CommandControl{
cl.belongsTo.clientsMtx.Unlock()
// Just print max users and time alive here
- return fmt.Sprintf("Current users in chat: %d
Max users in chat: %d
Server uptime: %s
Stream uptime: %s",
+ return fmt.Sprintf("Current users in chat: %d
Max users in chat: %d
Server uptime: %s
Stream uptime: %s
Viewers: %d
Max Viewers: %d",
users,
stats.getMaxUsers(),
time.Since(stats.start),
stats.getStreamLength(),
+ stats.getViewerCount(),
+ stats.getMaxViewerCount(),
), nil
},
},
diff --git a/handlers.go b/handlers.go
index 8b3ae68..91af63e 100644
--- a/handlers.go
+++ b/handlers.go
@@ -409,8 +409,10 @@ func handlePlay(conn *rtmp.Conn) {
}
func handleLive(w http.ResponseWriter, r *http.Request) {
+ uri := strings.Trim(r.URL.Path, "/")
+
l.RLock()
- ch := channels[strings.Trim(r.URL.Path, "/")]
+ ch := channels[uri]
l.RUnlock()
if ch != nil {
@@ -424,9 +426,14 @@ func handleLive(w http.ResponseWriter, r *http.Request) {
muxer := flv.NewMuxerWriteFlusher(writeFlusher{httpflusher: flusher, Writer: w})
cursor := ch.que.Latest()
+ ip := extractIp(r)
+ stats.addViewer(ip)
avutil.CopyFile(muxer, cursor)
+ stats.removeViewer(ip)
} else {
-
+ // Maybe HTTP_204 is better than HTTP_404
+ w.WriteHeader(http.StatusNoContent)
+ stats.resetViewers()
}
}
@@ -439,3 +446,16 @@ func handleDefault(w http.ResponseWriter, r *http.Request) {
handleIndexTemplate(w, r)
}
}
+
+func extractIp(r *http.Request) string {
+ ip := r.Host
+ f := r.Header.Get("Forwarded")
+ xff := r.Header.Get("X-Forwarded-For")
+ if !(xff == "") {
+ ip = xff
+ }
+ if !(f == "") {
+ ip = f
+ }
+ return ip
+}
diff --git a/stats.go b/stats.go
index 4fc8b26..755becb 100644
--- a/stats.go
+++ b/stats.go
@@ -8,18 +8,45 @@ import (
)
type streamStats struct {
- messageIn int
- messageOut int
- maxUsers int
- start time.Time
- mutex sync.Mutex
-
+ messageIn int
+ messageOut int
+ maxUsers int
+ start time.Time
+ mutex sync.Mutex
streamStart time.Time
streamLive bool // True if live
+ viewers map[string]string
+ maxViewers int
+}
+
+func (s *streamStats) addViewer(ip string) {
+ s.mutex.Lock()
+ s.viewers[ip] = ip
+ s.updateMaxViewers(len(s.viewers))
+ s.mutex.Unlock()
+
+ common.LogDebugf("Viewer connect from: %s\n", ip)
+}
+func (s *streamStats) removeViewer(ip string) {
+ s.mutex.Lock()
+ delete(s.viewers, ip)
+ s.mutex.Unlock()
+
+ common.LogDebugf("Viewer left from: %s\n", ip)
+}
+
+func (s *streamStats) updateMaxViewers(size int) {
+ if s.maxViewers < size {
+ s.maxViewers = size
+ }
+}
+
+func (s *streamStats) resetViewers() {
+ s.viewers = make(map[string]string)
}
func newStreamStats() streamStats {
- return streamStats{start: time.Now(), streamLive: false}
+ return streamStats{start: time.Now(), streamLive: false, viewers: make(map[string]string)}
}
func (s *streamStats) msgInInc() {
@@ -57,6 +84,7 @@ func (s *streamStats) Print() {
common.LogInfof("Messages Out: %d\n", s.messageOut)
common.LogInfof("Max users in chat: %d\n", s.maxUsers)
common.LogInfof("Total Time: %s\n", time.Since(s.start))
+ common.LogInfof("Max Stream Viewer: %d\n", s.maxViewers)
}
func (s *streamStats) startStream() {
@@ -83,3 +111,24 @@ func (s *streamStats) getStreamLength() time.Duration {
}
return time.Since(s.streamStart)
}
+
+func (s *streamStats) getViewerCount() int {
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+
+ return len(s.viewers)
+}
+
+func (s *streamStats) getMaxViewerCount() int {
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+
+ return s.maxViewers
+}
+
+func (s *streamStats) getViewers() map[string]string {
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+
+ return s.viewers
+}