1
0
Fork 0
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:
Kane York 2015-11-16 13:25:25 -08:00
parent a3971a27bf
commit c38b9b0018
4 changed files with 43 additions and 10 deletions

View file

@ -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 {

View file

@ -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())

View file

@ -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 {

View file

@ -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)
}