Expose total subscribers and topics in the /v1/stats api

This commit is contained in:
Kevin Lutzer 2023-09-17 11:48:40 -04:00
parent 528a67722b
commit d0898c8650
3 changed files with 28 additions and 10 deletions

View file

@ -631,14 +631,29 @@ func (s *Server) handleDocs(w http.ResponseWriter, r *http.Request, _ *visitor)
// handleStats returns the publicly available server stats
func (s *Server) handleStats(w http.ResponseWriter, _ *http.Request, _ *visitor) error {
s.mu.RLock()
var totalTopics, totalSubscriptions int64
for _, t := range s.topics {
if t.Stale() {
continue
}
totalTopics += 1
subscribers, _ := t.Stats()
totalSubscriptions += int64(subscribers)
}
messages, n, rate := s.messages, len(s.messagesHistory), float64(0)
if n > 1 {
rate = float64(s.messagesHistory[n-1]-s.messagesHistory[0]) / (float64(n-1) * s.config.ManagerInterval.Seconds())
}
s.mu.RUnlock()
response := &apiStatsResponse{
Messages: messages,
MessagesRate: rate,
TotalTopics: totalTopics,
TotalSubscriptions: totalSubscriptions,
}
return s.writeJSON(w, response)
}

View file

@ -6,8 +6,6 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"golang.org/x/crypto/bcrypt"
"heckel.io/ntfy/user"
"io"
"math/rand"
"net/http"
@ -22,6 +20,9 @@ import (
"testing"
"time"
"golang.org/x/crypto/bcrypt"
"heckel.io/ntfy/user"
"github.com/SherClockHolmes/webpush-go"
"github.com/stretchr/testify/require"
"heckel.io/ntfy/log"
@ -2501,7 +2502,7 @@ func TestServer_MessageHistoryAndStatsEndpoint(t *testing.T) {
response := request(t, s, "GET", "/v1/stats", "", nil)
require.Equal(t, 200, response.Code)
require.Equal(t, `{"messages":5,"messages_rate":0}`+"\n", response.Body.String())
require.Equal(t, `{"messages":5,"messages_rate":0,"total_topics":1,"total_subscriptions":0}`+"\n", response.Body.String())
// Run manager and see message history update
s.execManager()
@ -2509,7 +2510,7 @@ func TestServer_MessageHistoryAndStatsEndpoint(t *testing.T) {
response = request(t, s, "GET", "/v1/stats", "", nil)
require.Equal(t, 200, response.Code)
require.Equal(t, `{"messages":5,"messages_rate":2.5}`+"\n", response.Body.String()) // 5 messages in 2 seconds = 2.5 messages per second
require.Equal(t, `{"messages":5,"messages_rate":2.5,"total_topics":1,"total_subscriptions":0}`+"\n", response.Body.String()) // 5 messages in 2 seconds = 2.5 messages per second
// Publish some more messages
for i := 0; i < 10; i++ {
@ -2521,7 +2522,7 @@ func TestServer_MessageHistoryAndStatsEndpoint(t *testing.T) {
response = request(t, s, "GET", "/v1/stats", "", nil)
require.Equal(t, 200, response.Code)
require.Equal(t, `{"messages":15,"messages_rate":2.5}`+"\n", response.Body.String()) // Rate did not update yet
require.Equal(t, `{"messages":15,"messages_rate":2.5,"total_topics":1,"total_subscriptions":0}`+"\n", response.Body.String()) // Rate did not update yet
// Run manager and see message history update
s.execManager()
@ -2529,7 +2530,7 @@ func TestServer_MessageHistoryAndStatsEndpoint(t *testing.T) {
response = request(t, s, "GET", "/v1/stats", "", nil)
require.Equal(t, 200, response.Code)
require.Equal(t, `{"messages":15,"messages_rate":3.75}`+"\n", response.Body.String()) // 15 messages in 4 seconds = 3.75 messages per second
require.Equal(t, `{"messages":15,"messages_rate":3.75,"total_topics":1,"total_subscriptions":0}`+"\n", response.Body.String()) // 15 messages in 4 seconds = 3.75 messages per second
}
func TestServer_MessageHistoryMaxSize(t *testing.T) {

View file

@ -246,6 +246,8 @@ type apiHealthResponse struct {
type apiStatsResponse struct {
Messages int64 `json:"messages"`
MessagesRate float64 `json:"messages_rate"` // Average number of messages per second
TotalTopics int64 `json:"total_topics"`
TotalSubscriptions int64 `json:"total_subscriptions"`
}
type apiUserAddRequest struct {