mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-11 00:20:54 +00:00
Expose server statistics at /stats
This commit is contained in:
parent
a3971a27bf
commit
c38b9b0018
4 changed files with 43 additions and 10 deletions
|
@ -64,7 +64,7 @@ func getCacheKey(remoteCommand, data string) string {
|
||||||
// The backend can POST here to publish a message to clients with no caching.
|
// The backend can POST here to publish a message to clients with no caching.
|
||||||
// The POST arguments are `cmd`, `args`, `channel`, and `scope`.
|
// The POST arguments are `cmd`, `args`, `channel`, and `scope`.
|
||||||
// The `scope` argument is required because no attempt is made to infer the scope from the command, unlike /cached_pub.
|
// The `scope` argument is required because no attempt is made to infer the scope from the command, unlike /cached_pub.
|
||||||
func HBackendPublishRequest(w http.ResponseWriter, r *http.Request) {
|
func HTTPBackendUncachedPublish(w http.ResponseWriter, r *http.Request) {
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
formData, err := UnsealRequest(r.Form)
|
formData, err := UnsealRequest(r.Form)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -60,9 +60,11 @@ func SetupServerAndHandle(config *ConfigFile, serveMux *http.ServeMux) {
|
||||||
BannerHTML = bannerBytes
|
BannerHTML = bannerBytes
|
||||||
|
|
||||||
serveMux.HandleFunc("/", HTTPHandleRootURL)
|
serveMux.HandleFunc("/", HTTPHandleRootURL)
|
||||||
|
serveMux.HandleFunc("/stats", HTTPShowStatistics)
|
||||||
|
|
||||||
serveMux.HandleFunc("/drop_backlog", HTTPBackendDropBacklog)
|
serveMux.HandleFunc("/drop_backlog", HTTPBackendDropBacklog)
|
||||||
serveMux.HandleFunc("/uncached_pub", HBackendPublishRequest)
|
serveMux.HandleFunc("/uncached_pub", HTTPBackendUncachedPublish)
|
||||||
serveMux.HandleFunc("/cached_pub", HBackendUpdateAndPublish)
|
serveMux.HandleFunc("/cached_pub", HTTPBackendCachedPublish)
|
||||||
|
|
||||||
announceForm, err := SealRequest(url.Values{
|
announceForm, err := SealRequest(url.Values{
|
||||||
"startup": []string{"1"},
|
"startup": []string{"1"},
|
||||||
|
@ -118,25 +120,34 @@ func HTTPHandleRootURL(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// ErrProtocolGeneric is sent in a ErrorCommand Reply.
|
// ErrProtocolGeneric is sent in a ErrorCommand Reply.
|
||||||
var ErrProtocolGeneric error = errors.New("FFZ Socket protocol error.")
|
var ErrProtocolGeneric error = errors.New("FFZ Socket protocol error.")
|
||||||
|
|
||||||
// ErrProtocolNegativeMsgID is sent in a ErrorCommand Reply when a negative MessageID is received.
|
// ErrProtocolNegativeMsgID is sent in a ErrorCommand Reply when a negative MessageID is received.
|
||||||
var ErrProtocolNegativeMsgID error = errors.New("FFZ Socket protocol error: negative or zero message ID.")
|
var ErrProtocolNegativeMsgID error = errors.New("FFZ Socket protocol error: negative or zero message ID.")
|
||||||
|
|
||||||
// ErrExpectedSingleString is sent in a ErrorCommand Reply when the Arguments are of the wrong type.
|
// ErrExpectedSingleString is sent in a ErrorCommand Reply when the Arguments are of the wrong type.
|
||||||
var ErrExpectedSingleString = errors.New("Error: Expected single string as arguments.")
|
var ErrExpectedSingleString = errors.New("Error: Expected single string as arguments.")
|
||||||
|
|
||||||
// ErrExpectedSingleInt is sent in a ErrorCommand Reply when the Arguments are of the wrong type.
|
// ErrExpectedSingleInt is sent in a ErrorCommand Reply when the Arguments are of the wrong type.
|
||||||
var ErrExpectedSingleInt = errors.New("Error: Expected single integer as arguments.")
|
var ErrExpectedSingleInt = errors.New("Error: Expected single integer as arguments.")
|
||||||
|
|
||||||
// ErrExpectedTwoStrings is sent in a ErrorCommand Reply when the Arguments are of the wrong type.
|
// ErrExpectedTwoStrings is sent in a ErrorCommand Reply when the Arguments are of the wrong type.
|
||||||
var ErrExpectedTwoStrings = errors.New("Error: Expected array of string, string as arguments.")
|
var ErrExpectedTwoStrings = errors.New("Error: Expected array of string, string as arguments.")
|
||||||
|
|
||||||
// ErrExpectedStringAndBool is sent in a ErrorCommand Reply when the Arguments are of the wrong type.
|
// ErrExpectedStringAndBool is sent in a ErrorCommand Reply when the Arguments are of the wrong type.
|
||||||
var ErrExpectedStringAndBool = errors.New("Error: Expected array of string, bool as arguments.")
|
var ErrExpectedStringAndBool = errors.New("Error: Expected array of string, bool as arguments.")
|
||||||
|
|
||||||
// ErrExpectedStringAndInt is sent in a ErrorCommand Reply when the Arguments are of the wrong type.
|
// ErrExpectedStringAndInt is sent in a ErrorCommand Reply when the Arguments are of the wrong type.
|
||||||
var ErrExpectedStringAndInt = errors.New("Error: Expected array of string, int as arguments.")
|
var ErrExpectedStringAndInt = errors.New("Error: Expected array of string, int as arguments.")
|
||||||
|
|
||||||
// ErrExpectedStringAndIntGotFloat is sent in a ErrorCommand Reply when the Arguments are of the wrong type.
|
// ErrExpectedStringAndIntGotFloat is sent in a ErrorCommand Reply when the Arguments are of the wrong type.
|
||||||
var ErrExpectedStringAndIntGotFloat = errors.New("Error: Second argument was a float, expected an integer.")
|
var ErrExpectedStringAndIntGotFloat = errors.New("Error: Second argument was a float, expected an integer.")
|
||||||
|
|
||||||
// CloseGotBinaryMessage is the termination reason when the client sends a binary websocket frame.
|
// CloseGotBinaryMessage is the termination reason when the client sends a binary websocket frame.
|
||||||
var CloseGotBinaryMessage = websocket.CloseError{Code: websocket.CloseUnsupportedData, Text: "got binary packet"}
|
var CloseGotBinaryMessage = websocket.CloseError{Code: websocket.CloseUnsupportedData, Text: "got binary packet"}
|
||||||
|
|
||||||
// CloseTimedOut is the termination reason when the client fails to send or respond to ping frames.
|
// CloseTimedOut is the termination reason when the client fails to send or respond to ping frames.
|
||||||
var CloseTimedOut = websocket.CloseError{Code: websocket.CloseNoStatusReceived, Text: "no ping replies for 5 minutes"}
|
var CloseTimedOut = websocket.CloseError{Code: websocket.CloseNoStatusReceived, Text: "no ping replies for 5 minutes"}
|
||||||
|
|
||||||
// CloseFirstMessageNotHello is the termination reason
|
// CloseFirstMessageNotHello is the termination reason
|
||||||
var CloseFirstMessageNotHello = websocket.CloseError{
|
var CloseFirstMessageNotHello = websocket.CloseError{
|
||||||
Text: "Error - the first message sent must be a 'hello'",
|
Text: "Error - the first message sent must be a 'hello'",
|
||||||
|
@ -305,7 +316,7 @@ func getDeadline() time.Time {
|
||||||
}
|
}
|
||||||
|
|
||||||
func CloseConnection(conn *websocket.Conn, closeMsg *websocket.CloseError) {
|
func CloseConnection(conn *websocket.Conn, closeMsg *websocket.CloseError) {
|
||||||
Statistics.DisconnectCodes[closeMsg.Code]++
|
Statistics.DisconnectCodes[strconv.Itoa(closeMsg.Code)]++
|
||||||
Statistics.DisconnectReasons[closeMsg.Text]++
|
Statistics.DisconnectReasons[closeMsg.Text]++
|
||||||
|
|
||||||
conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(closeMsg.Code, closeMsg.Text), getDeadline())
|
conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(closeMsg.Code, closeMsg.Text), getDeadline())
|
||||||
|
|
|
@ -351,7 +351,7 @@ func HTTPBackendDropBacklog(w http.ResponseWriter, r *http.Request) {
|
||||||
// Publish a message to clients, and update the in-server cache for the message.
|
// Publish a message to clients, and update the in-server cache for the message.
|
||||||
// notes:
|
// notes:
|
||||||
// `scope` is implicit in the command
|
// `scope` is implicit in the command
|
||||||
func HBackendUpdateAndPublish(w http.ResponseWriter, r *http.Request) {
|
func HTTPBackendCachedPublish(w http.ResponseWriter, r *http.Request) {
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
formData, err := UnsealRequest(r.Form)
|
formData, err := UnsealRequest(r.Form)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,26 +1,48 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
type StatsData struct {
|
type StatsData struct {
|
||||||
ClientConnectsTotal int64
|
ClientConnectsTotal int64
|
||||||
ClientDisconnectsTotal int64
|
ClientDisconnectsTotal int64
|
||||||
FirstNotHelloDisconnects int64
|
FirstNotHelloDisconnects int64
|
||||||
|
|
||||||
DisconnectCodes map[int]int64
|
DisconnectCodes map[string]int64
|
||||||
DisconnectReasons map[string]int64
|
DisconnectReasons map[string]int64
|
||||||
|
|
||||||
CommandsIssuedTotal int64
|
CommandsIssuedTotal int64
|
||||||
CommandsIssuedMap map[Command]int64
|
CommandsIssuedMap map[Command]int64
|
||||||
|
|
||||||
MessagesSent int64
|
MessagesSent int64
|
||||||
|
|
||||||
|
Version int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StatsDataVersion = 1
|
||||||
|
|
||||||
func newStatsData() *StatsData {
|
func newStatsData() *StatsData {
|
||||||
return &StatsData{
|
return &StatsData{
|
||||||
CommandsIssuedMap: make(map[Command]int64),
|
CommandsIssuedMap: make(map[Command]int64),
|
||||||
DisconnectCodes: make(map[int]int64),
|
DisconnectCodes: make(map[string]int64),
|
||||||
DisconnectReasons: make(map[string]int64),
|
DisconnectReasons: make(map[string]int64),
|
||||||
|
Version: StatsDataVersion,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Statistics is several variables that get incremented during normal operation of the server.
|
// Statistics is several variables that get incremented during normal operation of the server.
|
||||||
|
// Its structure should be versioned as it is exposed via JSON.
|
||||||
var Statistics = newStatsData()
|
var Statistics = newStatsData()
|
||||||
|
|
||||||
|
func HTTPShowStatistics(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
jsonBytes, _ := json.Marshal(Statistics)
|
||||||
|
outBuf := bytes.NewBuffer(nil)
|
||||||
|
json.Indent(outBuf, jsonBytes, "", "\t")
|
||||||
|
|
||||||
|
outBuf.WriteTo(w)
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue