From 3af90e454f36255f84111f86213a82335656f2a8 Mon Sep 17 00:00:00 2001 From: Derek Collison Date: Sat, 9 Jan 2016 09:57:04 -0800 Subject: [PATCH] Track total connections, http request stats --- TODO.md | 7 +++-- server/monitor.go | 53 +++++++++++++++++++++++---------- server/monitor_test.go | 3 ++ server/roothtml.go | 2 +- server/server.go | 67 +++++++++++++++++++++++++++--------------- 5 files changed, 89 insertions(+), 43 deletions(-) diff --git a/TODO.md b/TODO.md index ab77bccf..f33482cd 100644 --- a/TODO.md +++ b/TODO.md @@ -14,11 +14,12 @@ - [ ] Modify cluster support for single message across routes between pub/sub and d-queue - [ ] Memory limits/warnings? - [ ] Limit number of subscriptions a client can have, total memory usage etc. -- [ ] Gossip Protocol for discovery for clustering - [ ] Info updates contain other implicit route servers - [ ] Multi-tenant accounts with isolation of subject space -- [ ] Add to varz, time for slow consumers, peek or total connections, memory, etc. -- [ ] Add starttime and uptime to connz list. +- [ ] Track last activity time per connection? +- [X] Add total connections to varz so we won't miss spikes, etc. +- [X] Add starttime and uptime to connz list. +- [X] Gossip Protocol for discovery for clustering - [ ] Add in HTTP requests to varz? - [X] Add favico and help link for monitoring? - [X] Better user/pass support using bcrypt etc. diff --git a/server/monitor.go b/server/monitor.go index 581da19f..90cd7859 100644 --- a/server/monitor.go +++ b/server/monitor.go @@ -71,6 +71,7 @@ func (s *Server) HandleConnz(w http.ResponseWriter, r *http.Request) { // Walk the list s.mu.Lock() + s.httpReqStats[ConnzPath]++ tlsRequired := s.info.TLSRequired c.NumConns = len(s.clients) @@ -213,6 +214,8 @@ func (s *Server) HandleRoutez(w http.ResponseWriter, r *http.Request) { // Walk the list s.mu.Lock() + + s.httpReqStats[RoutezPath]++ rs.NumRoutes = len(s.routes) for _, r := range s.routes { @@ -252,6 +255,10 @@ func (s *Server) HandleRoutez(w http.ResponseWriter, r *http.Request) { // HandleStats process HTTP requests for subjects stats. func (s *Server) HandleSubsz(w http.ResponseWriter, r *http.Request) { + s.mu.Lock() + s.httpReqStats[SubszPath]++ + s.mu.Unlock() + st := &Subsz{s.sl.Stats()} b, err := json.MarshalIndent(st, "", " ") @@ -267,22 +274,25 @@ func (s *Server) HandleSubsz(w http.ResponseWriter, r *http.Request) { type Varz struct { *Info *Options - Port int `json:"port"` - MaxPayload int `json:"max_payload"` - Start time.Time `json:"start"` - Now time.Time `json:"now"` - Uptime string `json:"uptime"` - Mem int64 `json:"mem"` - Cores int `json:"cores"` - CPU float64 `json:"cpu"` - Connections int `json:"connections"` - Routes int `json:"routes"` - Remotes int `json:"remotes"` - InMsgs int64 `json:"in_msgs"` - OutMsgs int64 `json:"out_msgs"` - InBytes int64 `json:"in_bytes"` - OutBytes int64 `json:"out_bytes"` - SlowConsumers int64 `json:"slow_consumers"` + Port int `json:"port"` + MaxPayload int `json:"max_payload"` + Start time.Time `json:"start"` + Now time.Time `json:"now"` + Uptime string `json:"uptime"` + Mem int64 `json:"mem"` + Cores int `json:"cores"` + CPU float64 `json:"cpu"` + Connections int `json:"connections"` + TotalConnections uint64 `json:"total_connections"` + Routes int `json:"routes"` + Remotes int `json:"remotes"` + InMsgs int64 `json:"in_msgs"` + OutMsgs int64 `json:"out_msgs"` + InBytes int64 `json:"in_bytes"` + OutBytes int64 `json:"out_bytes"` + SlowConsumers int64 `json:"slow_consumers"` + + HTTPReqStats map[string]uint64 `json:"http_req_stats"` } type usage struct { @@ -316,6 +326,14 @@ func myUptime(d time.Duration) string { // HandleRoot will show basic info and links to others handlers. func (s *Server) HandleRoot(w http.ResponseWriter, r *http.Request) { + // This feels dumb to me, but is required: https://code.google.com/p/go/issues/detail?id=4799 + if r.URL.Path != "/" { + http.NotFound(w, r) + return + } + s.mu.Lock() + s.httpReqStats[RootPath]++ + s.mu.Unlock() fmt.Fprintf(w, rootHTML) } @@ -330,6 +348,7 @@ func (s *Server) HandleVarz(w http.ResponseWriter, r *http.Request) { s.mu.Lock() v.Connections = len(s.clients) + v.TotalConnections = s.totalClients v.Routes = len(s.routes) v.Remotes = len(s.remotes) v.InMsgs = s.inMsgs @@ -337,6 +356,8 @@ func (s *Server) HandleVarz(w http.ResponseWriter, r *http.Request) { v.OutMsgs = s.outMsgs v.OutBytes = s.outBytes v.SlowConsumers = s.slowConsumers + s.httpReqStats[VarzPath]++ + v.HTTPReqStats = s.httpReqStats s.mu.Unlock() b, err := json.MarshalIndent(v, "", " ") diff --git a/server/monitor_test.go b/server/monitor_test.go index be3737c0..aa444ec4 100644 --- a/server/monitor_test.go +++ b/server/monitor_test.go @@ -145,6 +145,9 @@ func TestVarz(t *testing.T) { if v.Connections != 1 { t.Fatalf("Expected Connections of 1, got %v\n", v.Connections) } + if v.TotalConnections >= 1 { + t.Fatalf("Expected Total Connections of at least 1, got %v\n", v.TotalConnections) + } if v.InMsgs != 1 { t.Fatalf("Expected InMsgs of 1, got %v\n", v.InMsgs) } diff --git a/server/roothtml.go b/server/roothtml.go index fcc5b975..2185229b 100644 --- a/server/roothtml.go +++ b/server/roothtml.go @@ -6,7 +6,7 @@ package server var rootHTML = "" + ` - +