Add more metrics on rooms / sessions / backends.

This commit is contained in:
Joachim Bauch 2021-05-11 14:39:02 +02:00
parent 5d431e5612
commit ce1b3fc6e2
No known key found for this signature in database
GPG Key ID: 77C1D22D53E15F02
10 changed files with 316 additions and 2 deletions

View File

@ -90,6 +90,7 @@ func (b *Backend) AddSession(session Session) error {
if b.sessions == nil {
b.sessions = make(map[string]bool)
} else if uint64(len(b.sessions)) >= b.sessionLimit {
statsBackendLimitExceededTotal.WithLabelValues(b.id).Inc()
return SessionLimitExceeded
}
@ -123,6 +124,7 @@ func NewBackendConfiguration(config *goconf.ConfigFile) (*BackendConfiguration,
}
backends := make(map[string][]*Backend)
var compatBackend *Backend
numBackends := 0
if allowAll {
log.Println("WARNING: All backend hostnames are allowed, only use for development!")
compatBackend = &Backend{
@ -137,12 +139,14 @@ func NewBackendConfiguration(config *goconf.ConfigFile) (*BackendConfiguration,
if sessionLimit > 0 {
log.Printf("Allow a maximum of %d sessions", sessionLimit)
}
numBackends += 1
} else if backendIds, _ := config.GetString("backend", "backends"); backendIds != "" {
for host, configuredBackends := range getConfiguredHosts(backendIds, config) {
backends[host] = append(backends[host], configuredBackends...)
for _, be := range configuredBackends {
log.Printf("Backend %s added for %s", be.id, be.url)
}
numBackends += len(configuredBackends)
}
} else if allowedUrls, _ := config.GetString("backend", "allowed"); allowedUrls != "" {
// Old-style configuration, only hosts are configured and are using a common secret.
@ -182,9 +186,14 @@ func NewBackendConfiguration(config *goconf.ConfigFile) (*BackendConfiguration,
if sessionLimit > 0 {
log.Printf("Allow a maximum of %d sessions", sessionLimit)
}
numBackends += 1
}
}
RegisterBackendConfigurationStats()
log.Printf("Initial: %d", numBackends)
statsBackendsCurrent.Add(float64(numBackends))
return &BackendConfiguration{
backends: backends,
@ -199,6 +208,7 @@ func (b *BackendConfiguration) RemoveBackendsForHost(host string) {
for _, backend := range oldBackends {
log.Printf("Backend %s removed for %s", backend.id, backend.url)
}
statsBackendsCurrent.Sub(float64(len(oldBackends)))
}
delete(b.backends, host)
}
@ -225,6 +235,7 @@ func (b *BackendConfiguration) UpsertHost(host string, backends []*Backend) {
removed := b.backends[host][existingIndex]
log.Printf("Backend %s removed for %s", removed.id, removed.url)
b.backends[host] = append(b.backends[host][:existingIndex], b.backends[host][existingIndex+1:]...)
statsBackendsCurrent.Dec()
}
}
@ -232,6 +243,7 @@ func (b *BackendConfiguration) UpsertHost(host string, backends []*Backend) {
for _, added := range backends {
log.Printf("Backend %s added for %s", added.id, added.url)
}
statsBackendsCurrent.Add(float64(len(backends)))
}
func getConfiguredBackendIDs(backendIds string) (ids []string) {

View File

@ -0,0 +1,50 @@
/**
* Standalone signaling server for the Nextcloud Spreed app.
* Copyright (C) 2021 struktur AG
*
* @author Joachim Bauch <bauch@struktur.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package signaling
import (
"github.com/prometheus/client_golang/prometheus"
)
var (
statsBackendLimitExceededTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: "signaling",
Subsystem: "backend",
Name: "session_limit_exceeded_total",
Help: "The number of times the session limit exceeded",
}, []string{"backend"})
statsBackendsCurrent = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "signaling",
Subsystem: "backend",
Name: "current",
Help: "The current number of configured backends",
})
backendConfigurationStats = []prometheus.Collector{
statsBackendLimitExceededTotal,
statsBackendsCurrent,
}
)
func RegisterBackendConfigurationStats() {
registerAll(backendConfigurationStats...)
}

View File

@ -28,6 +28,7 @@ import (
"testing"
"github.com/dlintw/goconf"
"github.com/prometheus/client_golang/prometheus/testutil"
)
func testUrls(t *testing.T, config *BackendConfiguration, valid_urls []string, invalid_urls []string) {
@ -238,6 +239,7 @@ func TestParseBackendIds(t *testing.T) {
}
func TestBackendReloadNoChange(t *testing.T) {
current := testutil.ToFloat64(statsBackendsCurrent)
original_config := goconf.NewConfigFile()
original_config.AddOption("backend", "backends", "backend1, backend2")
original_config.AddOption("backend", "allowall", "false")
@ -249,6 +251,7 @@ func TestBackendReloadNoChange(t *testing.T) {
if err != nil {
t.Fatal(err)
}
checkStatsValue(t, statsBackendsCurrent, current+2)
new_config := goconf.NewConfigFile()
new_config.AddOption("backend", "backends", "backend1, backend2")
@ -262,13 +265,16 @@ func TestBackendReloadNoChange(t *testing.T) {
t.Fatal(err)
}
checkStatsValue(t, statsBackendsCurrent, current+4)
o_cfg.Reload(original_config)
checkStatsValue(t, statsBackendsCurrent, current+4)
if !reflect.DeepEqual(n_cfg, o_cfg) {
t.Error("BackendConfiguration should be equal after Reload")
}
}
func TestBackendReloadChangeExistingURL(t *testing.T) {
current := testutil.ToFloat64(statsBackendsCurrent)
original_config := goconf.NewConfigFile()
original_config.AddOption("backend", "backends", "backend1, backend2")
original_config.AddOption("backend", "allowall", "false")
@ -281,6 +287,7 @@ func TestBackendReloadChangeExistingURL(t *testing.T) {
t.Fatal(err)
}
checkStatsValue(t, statsBackendsCurrent, current+2)
new_config := goconf.NewConfigFile()
new_config.AddOption("backend", "backends", "backend1, backend2")
new_config.AddOption("backend", "allowall", "false")
@ -294,17 +301,20 @@ func TestBackendReloadChangeExistingURL(t *testing.T) {
t.Fatal(err)
}
checkStatsValue(t, statsBackendsCurrent, current+4)
original_config.RemoveOption("backend1", "url")
original_config.AddOption("backend1", "url", "http://domain3.invalid")
original_config.AddOption("backend1", "sessionlimit", "10")
o_cfg.Reload(original_config)
checkStatsValue(t, statsBackendsCurrent, current+4)
if !reflect.DeepEqual(n_cfg, o_cfg) {
t.Error("BackendConfiguration should be equal after Reload")
}
}
func TestBackendReloadChangeSecret(t *testing.T) {
current := testutil.ToFloat64(statsBackendsCurrent)
original_config := goconf.NewConfigFile()
original_config.AddOption("backend", "backends", "backend1, backend2")
original_config.AddOption("backend", "allowall", "false")
@ -317,6 +327,7 @@ func TestBackendReloadChangeSecret(t *testing.T) {
t.Fatal(err)
}
checkStatsValue(t, statsBackendsCurrent, current+2)
new_config := goconf.NewConfigFile()
new_config.AddOption("backend", "backends", "backend1, backend2")
new_config.AddOption("backend", "allowall", "false")
@ -329,16 +340,19 @@ func TestBackendReloadChangeSecret(t *testing.T) {
t.Fatal(err)
}
checkStatsValue(t, statsBackendsCurrent, current+4)
original_config.RemoveOption("backend1", "secret")
original_config.AddOption("backend1", "secret", string(testBackendSecret)+"-backend3")
o_cfg.Reload(original_config)
checkStatsValue(t, statsBackendsCurrent, current+4)
if !reflect.DeepEqual(n_cfg, o_cfg) {
t.Error("BackendConfiguration should be equal after Reload")
}
}
func TestBackendReloadAddBackend(t *testing.T) {
current := testutil.ToFloat64(statsBackendsCurrent)
original_config := goconf.NewConfigFile()
original_config.AddOption("backend", "backends", "backend1")
original_config.AddOption("backend", "allowall", "false")
@ -349,6 +363,7 @@ func TestBackendReloadAddBackend(t *testing.T) {
t.Fatal(err)
}
checkStatsValue(t, statsBackendsCurrent, current+1)
new_config := goconf.NewConfigFile()
new_config.AddOption("backend", "backends", "backend1, backend2")
new_config.AddOption("backend", "allowall", "false")
@ -362,6 +377,7 @@ func TestBackendReloadAddBackend(t *testing.T) {
t.Fatal(err)
}
checkStatsValue(t, statsBackendsCurrent, current+3)
original_config.RemoveOption("backend", "backends")
original_config.AddOption("backend", "backends", "backend1, backend2")
original_config.AddOption("backend2", "url", "http://domain2.invalid")
@ -369,12 +385,14 @@ func TestBackendReloadAddBackend(t *testing.T) {
original_config.AddOption("backend2", "sessionlimit", "10")
o_cfg.Reload(original_config)
checkStatsValue(t, statsBackendsCurrent, current+4)
if !reflect.DeepEqual(n_cfg, o_cfg) {
t.Error("BackendConfiguration should be equal after Reload")
}
}
func TestBackendReloadRemoveHost(t *testing.T) {
current := testutil.ToFloat64(statsBackendsCurrent)
original_config := goconf.NewConfigFile()
original_config.AddOption("backend", "backends", "backend1, backend2")
original_config.AddOption("backend", "allowall", "false")
@ -387,6 +405,7 @@ func TestBackendReloadRemoveHost(t *testing.T) {
t.Fatal(err)
}
checkStatsValue(t, statsBackendsCurrent, current+2)
new_config := goconf.NewConfigFile()
new_config.AddOption("backend", "backends", "backend1")
new_config.AddOption("backend", "allowall", "false")
@ -397,17 +416,20 @@ func TestBackendReloadRemoveHost(t *testing.T) {
t.Fatal(err)
}
checkStatsValue(t, statsBackendsCurrent, current+3)
original_config.RemoveOption("backend", "backends")
original_config.AddOption("backend", "backends", "backend1")
original_config.RemoveSection("backend2")
o_cfg.Reload(original_config)
checkStatsValue(t, statsBackendsCurrent, current+2)
if !reflect.DeepEqual(n_cfg, o_cfg) {
t.Error("BackendConfiguration should be equal after Reload")
}
}
func TestBackendReloadRemoveBackendFromSharedHost(t *testing.T) {
current := testutil.ToFloat64(statsBackendsCurrent)
original_config := goconf.NewConfigFile()
original_config.AddOption("backend", "backends", "backend1, backend2")
original_config.AddOption("backend", "allowall", "false")
@ -420,6 +442,7 @@ func TestBackendReloadRemoveBackendFromSharedHost(t *testing.T) {
t.Fatal(err)
}
checkStatsValue(t, statsBackendsCurrent, current+2)
new_config := goconf.NewConfigFile()
new_config.AddOption("backend", "backends", "backend1")
new_config.AddOption("backend", "allowall", "false")
@ -430,11 +453,13 @@ func TestBackendReloadRemoveBackendFromSharedHost(t *testing.T) {
t.Fatal(err)
}
checkStatsValue(t, statsBackendsCurrent, current+3)
original_config.RemoveOption("backend", "backends")
original_config.AddOption("backend", "backends", "backend1")
original_config.RemoveSection("backend2")
o_cfg.Reload(original_config)
checkStatsValue(t, statsBackendsCurrent, current+2)
if !reflect.DeepEqual(n_cfg, o_cfg) {
t.Error("BackendConfiguration should be equal after Reload")
}

View File

@ -58,6 +58,10 @@ var (
unknownCountry string = "unknown-country"
)
func init() {
RegisterClientStats()
}
func IsValidCountry(country string) bool {
switch country {
case "":

View File

@ -0,0 +1,43 @@
/**
* Standalone signaling server for the Nextcloud Spreed app.
* Copyright (C) 2021 struktur AG
*
* @author Joachim Bauch <bauch@struktur.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package signaling
import (
"github.com/prometheus/client_golang/prometheus"
)
var (
statsClientCountries = prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: "signaling",
Subsystem: "client",
Name: "countries_total",
Help: "The total number of connections by country",
}, []string{"country"})
clientStats = []prometheus.Collector{
statsClientCountries,
}
)
func RegisterClientStats() {
registerAll(clientStats...)
}

22
hub.go
View File

@ -95,6 +95,10 @@ const (
publicSessionName = "public-session"
)
func init() {
RegisterHubStats()
}
type Hub struct {
// 64-bit members that are accessed atomically must be 64-bit aligned.
sid uint64
@ -607,6 +611,7 @@ func (h *Hub) removeSession(session Session) (removed bool) {
delete(h.clients, data.Sid)
if _, found := h.sessions[data.Sid]; found {
delete(h.sessions, data.Sid)
statsHubSessionsCurrent.WithLabelValues(session.Backend().Id(), session.ClientType()).Dec()
removed = true
}
}
@ -742,6 +747,12 @@ func (h *Hub) processRegister(client *Client, message *ClientMessage, backend *B
}
h.mu.Unlock()
if country := client.Country(); IsValidCountry(country) {
statsClientCountries.WithLabelValues(country).Inc()
}
statsHubSessionsCurrent.WithLabelValues(backend.Id(), session.ClientType()).Inc()
statsHubSessionsTotal.WithLabelValues(backend.Id(), session.ClientType()).Inc()
h.setDecodedSessionId(privateSessionId, privateSessionName, sessionIdData)
h.setDecodedSessionId(publicSessionId, publicSessionName, sessionIdData)
h.sendHelloResponse(session, message)
@ -840,6 +851,7 @@ func (h *Hub) processHello(client *Client, message *ClientMessage) {
if resumeId != "" {
data := h.decodeSessionId(resumeId, privateSessionName)
if data == nil {
statsHubSessionResumeFailed.Inc()
client.SendMessage(message.NewErrorServerMessage(NoSuchSession))
return
}
@ -848,6 +860,7 @@ func (h *Hub) processHello(client *Client, message *ClientMessage) {
session, found := h.sessions[data.Sid]
if !found || resumeId != session.PrivateId() {
h.mu.Unlock()
statsHubSessionResumeFailed.Inc()
client.SendMessage(message.NewErrorServerMessage(NoSuchSession))
return
}
@ -857,6 +870,7 @@ func (h *Hub) processHello(client *Client, message *ClientMessage) {
// Should never happen as clients only can resume their own sessions.
h.mu.Unlock()
log.Printf("Client resumed non-client session %s (private=%s)", session.PublicId(), session.PrivateId())
statsHubSessionResumeFailed.Inc()
client.SendMessage(message.NewErrorServerMessage(NoSuchSession))
return
}
@ -879,6 +893,7 @@ func (h *Hub) processHello(client *Client, message *ClientMessage) {
log.Printf("Resume session from %s in %s (%s) %s (private=%s)", client.RemoteAddr(), client.Country(), client.UserAgent(), session.PublicId(), session.PrivateId())
statsHubSessionsResumedTotal.WithLabelValues(clientSession.Backend().Id(), clientSession.ClientType()).Inc()
h.sendHelloResponse(clientSession, message)
clientSession.NotifySessionResumed(client)
return
@ -1087,7 +1102,10 @@ func (h *Hub) getRoomForBackend(id string, backend *Backend) *Room {
func (h *Hub) removeRoom(room *Room) {
internalRoomId := getRoomIdForBackend(room.Id(), room.Backend())
h.ru.Lock()
if _, found := h.rooms[internalRoomId]; found {
delete(h.rooms, internalRoomId)
statsHubRoomsCurrent.WithLabelValues(room.Backend().Id()).Dec()
}
h.ru.Unlock()
}
@ -1100,6 +1118,7 @@ func (h *Hub) createRoom(id string, properties *json.RawMessage, backend *Backen
internalRoomId := getRoomIdForBackend(id, backend)
h.rooms[internalRoomId] = room
statsHubRoomsCurrent.WithLabelValues(backend.Id()).Inc()
return room, nil
}
@ -1550,6 +1569,8 @@ func (h *Hub) processInternalMsg(client *Client, message *ClientMessage) {
h.sessions[sessionIdData.Sid] = sess
h.virtualSessions[virtualSessionId] = sessionIdData.Sid
h.mu.Unlock()
statsHubSessionsCurrent.WithLabelValues(session.Backend().Id(), sess.ClientType()).Inc()
statsHubSessionsTotal.WithLabelValues(session.Backend().Id(), sess.ClientType()).Inc()
log.Printf("Session %s added virtual session %s with initial flags %d", session.PublicId(), sess.PublicId(), sess.Flags())
session.AddVirtualSession(sess)
sess.SetRoom(room)
@ -1608,6 +1629,7 @@ func (h *Hub) processInternalMsg(client *Client, message *ClientMessage) {
h.mu.Unlock()
if sess != nil {
log.Printf("Session %s removed virtual session %s", session.PublicId(), sess.PublicId())
statsHubSessionsCurrent.WithLabelValues(session.Backend().Id(), sess.ClientType()).Dec()
if vsess, ok := sess.(*VirtualSession); ok {
// We should always have a VirtualSession here.
vsess.CloseWithFeedback(session, message)

70
hub_stats_prometheus.go Normal file
View File

@ -0,0 +1,70 @@
/**
* Standalone signaling server for the Nextcloud Spreed app.
* Copyright (C) 2021 struktur AG
*
* @author Joachim Bauch <bauch@struktur.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package signaling
import (
"github.com/prometheus/client_golang/prometheus"
)
var (
statsHubRoomsCurrent = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: "signaling",
Subsystem: "hub",
Name: "rooms",
Help: "The current number of rooms per backend",
}, []string{"backend"})
statsHubSessionsCurrent = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: "signaling",
Subsystem: "hub",
Name: "sessions",
Help: "The current number of sessions per backend",
}, []string{"backend", "clienttype"})
statsHubSessionsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: "signaling",
Subsystem: "hub",
Name: "sessions_total",
Help: "The total number of sessions per backend",
}, []string{"backend", "clienttype"})
statsHubSessionsResumedTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: "signaling",
Subsystem: "hub",
Name: "sessions_resume_total",
Help: "The total number of resumed sessions per backend",
}, []string{"backend", "clienttype"})
statsHubSessionResumeFailed = prometheus.NewCounter(prometheus.CounterOpts{
Namespace: "signaling",
Subsystem: "hub",
Name: "sessions_resume_failed_total",
Help: "The total number of failed session resume requests",
})
hubStats = []prometheus.Collector{
statsHubRoomsCurrent,
statsHubSessionsCurrent,
statsHubSessionsTotal,
statsHubSessionResumeFailed,
}
)
func RegisterHubStats() {
registerAll(hubStats...)
}

22
room.go
View File

@ -32,6 +32,7 @@ import (
"time"
"github.com/nats-io/nats.go"
"github.com/prometheus/client_golang/prometheus"
)
const (
@ -47,6 +48,10 @@ var (
updateActiveSessionsInterval = 10 * time.Second
)
func init() {
RegisterRoomStats()
}
type Room struct {
id string
hub *Hub
@ -64,6 +69,8 @@ type Room struct {
inCallSessions map[Session]bool
roomSessionData map[string]*RoomSessionData
statsRoomSessionsCurrent *prometheus.GaugeVec
natsReceiver chan *nats.Msg
backendSubscription NatsSubscription
@ -123,6 +130,11 @@ func NewRoom(roomId string, properties *json.RawMessage, hub *Hub, n NatsClient,
inCallSessions: make(map[Session]bool),
roomSessionData: make(map[string]*RoomSessionData),
statsRoomSessionsCurrent: statsRoomSessionsCurrent.MustCurryWith(prometheus.Labels{
"backend": backend.Id(),
"room": roomId,
}),
natsReceiver: natsReceiver,
backendSubscription: backendSubscription,
@ -194,6 +206,9 @@ func (r *Room) Close() []Session {
result = append(result, s)
}
r.sessions = nil
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": HelloClientTypeClient})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": HelloClientTypeInternal})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": HelloClientTypeVirtual})
r.mu.Unlock()
return result
}
@ -264,6 +279,9 @@ func (r *Room) AddSession(session Session, sessionData *json.RawMessage) []Sessi
}
}
r.sessions[sid] = session
if !found {
r.statsRoomSessionsCurrent.With(prometheus.Labels{"clienttype": session.ClientType()}).Inc()
}
var publishUsersChanged bool
switch session.ClientType() {
case HelloClientTypeInternal:
@ -311,6 +329,7 @@ func (r *Room) RemoveSession(session Session) bool {
}
sid := session.PublicId()
r.statsRoomSessionsCurrent.With(prometheus.Labels{"clienttype": session.ClientType()}).Dec()
delete(r.sessions, sid)
delete(r.internalSessions, session)
if virtualSession, ok := session.(*VirtualSession); ok {
@ -325,6 +344,9 @@ func (r *Room) RemoveSession(session Session) bool {
}
r.hub.removeRoom(r)
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": HelloClientTypeClient})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": HelloClientTypeInternal})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": HelloClientTypeVirtual})
r.unsubscribeBackend()
r.doClose()
r.mu.Unlock()

43
room_stats_prometheus.go Normal file
View File

@ -0,0 +1,43 @@
/**
* Standalone signaling server for the Nextcloud Spreed app.
* Copyright (C) 2021 struktur AG
*
* @author Joachim Bauch <bauch@struktur.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package signaling
import (
"github.com/prometheus/client_golang/prometheus"
)
var (
statsRoomSessionsCurrent = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: "signaling",
Subsystem: "room",
Name: "sessions",
Help: "The current number of sessions in a room",
}, []string{"backend", "room", "clienttype"})
roomStats = []prometheus.Collector{
statsRoomSessionsCurrent,
}
)
func RegisterRoomStats() {
registerAll(roomStats...)
}

View File

@ -22,6 +22,9 @@
package signaling
import (
"fmt"
"runtime"
"strings"
"testing"
"github.com/prometheus/client_golang/prometheus"
@ -34,7 +37,27 @@ func checkStatsValue(t *testing.T, collector prometheus.Collector, value float64
desc := <-ch
v := testutil.ToFloat64(collector)
if v != value {
pc := make([]uintptr, 10)
n := runtime.Callers(2, pc)
if n == 0 {
t.Errorf("Expected value %f for %s, got %f", value, desc, v)
return
}
pc = pc[:n]
frames := runtime.CallersFrames(pc)
stack := ""
for {
frame, more := frames.Next()
if !strings.Contains(frame.File, "nextcloud-spreed-signaling") {
break
}
stack += fmt.Sprintf("%s:%d\n", frame.File, frame.Line)
if !more {
break
}
}
t.Errorf("Expected value %f for %s, got %f at\n%s", value, desc, v, stack)
}
}