1
0
Fork 0
shezmu/stats/server.go

94 lines
2.0 KiB
Go
Raw Normal View History

2015-10-27 01:16:02 +00:00
package stats
import (
"encoding/json"
2015-10-27 22:23:39 +00:00
"fmt"
2015-10-27 01:16:02 +00:00
"net/http"
2015-10-27 22:23:39 +00:00
"time"
2015-10-27 01:16:02 +00:00
)
type Server struct {
base
2015-10-27 22:23:39 +00:00
2015-10-28 23:21:34 +00:00
history map[string][]*serverStatsSnapshot
2015-10-27 01:16:02 +00:00
}
2016-01-10 18:03:00 +00:00
type serverStatsSnapshot struct {
timestamp int64
processed int64
errors int64
min float64
p25 float64
mean float64
median float64
p75 float64
max float64
}
2015-10-27 22:23:39 +00:00
const (
2016-01-10 18:03:00 +00:00
// 60 of 10 second snapshots is 10 minutes worth of stats
serverSnapshotIntervl = 10 * time.Second
serverHistorySize = 61 // +1 extra
2015-10-27 22:23:39 +00:00
)
2015-10-27 01:16:02 +00:00
func NewServer() *Server {
s := &Server{}
s.init()
2015-10-28 23:21:34 +00:00
s.history = make(map[string][]*serverStatsSnapshot)
2015-10-27 22:23:39 +00:00
go s.takeSnapshots()
2015-10-27 01:16:02 +00:00
return s
}
2015-10-27 22:23:39 +00:00
func (s *Server) History(rw http.ResponseWriter, _ *http.Request) {
encoded, err := json.Marshal(s.history)
2015-10-27 01:16:02 +00:00
if err != nil {
2015-10-27 22:23:39 +00:00
http.Error(rw, fmt.Sprintf("%v", err), http.StatusInternalServerError)
return
2015-10-27 01:16:02 +00:00
}
rw.Header().Add("Access-Control-Allow-Origin", "*")
2015-10-27 01:16:02 +00:00
rw.Write(encoded)
}
2015-10-27 22:23:39 +00:00
func (s *Server) takeSnapshots() {
for range time.NewTicker(serverSnapshotIntervl).C {
s.Lock()
for name, stat := range s.stats {
if len(s.history[name]) >= serverHistorySize {
s.history[name] = s.history[name][1:]
}
2015-10-28 23:21:34 +00:00
s.history[name] = append(s.history[name], makeServerStatsSnapshot(stat))
2015-10-27 22:23:39 +00:00
}
2015-10-28 19:42:17 +00:00
s.Reset()
2015-10-27 22:23:39 +00:00
s.Unlock()
}
}
2015-10-28 23:21:34 +00:00
//
// Stats
//
func makeServerStatsSnapshot(s *baseStats) *serverStatsSnapshot {
ps := s.time.Percentiles([]float64{0.25, 0.5, 0.75})
2016-01-10 18:03:00 +00:00
2015-10-28 23:21:34 +00:00
return &serverStatsSnapshot{
timestamp: time.Now().UTC().Unix(),
processed: s.time.Count(),
errors: s.errors.Count(),
min: round(float64(s.time.Min())/1000000, 6),
p25: round(ps[0]/1000000, 6),
mean: round(s.time.Mean()/1000000, 6),
median: round(ps[1]/1000000, 6),
p75: round(ps[2]/1000000, 6),
max: round(float64(s.time.Max())/1000000, 6),
}
}
// Implements json.Marshaler
func (s *serverStatsSnapshot) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf("[%d,%d,%d,%.6f,%.6f,%.6f,%.6f,%.6f,%.6f]",
s.timestamp, s.processed, s.errors, s.min, s.p25,
s.mean, s.median, s.p75, s.max)), nil
}