diff --git a/consul/server.go b/consul/server.go index 90865fb53..9cdfa0b53 100644 --- a/consul/server.go +++ b/consul/server.go @@ -257,6 +257,9 @@ func NewServer(config *Config) (*Server, error) { // Start listening for RPC requests go s.listen() + + // Start the metrics handlers + go s.sessionStats() return s, nil } diff --git a/consul/session_endpoint.go b/consul/session_endpoint.go index 3d6bfc1c9..3d97b8bfe 100644 --- a/consul/session_endpoint.go +++ b/consul/session_endpoint.go @@ -166,6 +166,7 @@ func (s *Session) Renew(args *structs.SessionSpecificRequest, if done, err := s.srv.forward("Session.Renew", args, args, reply); done { return err } + defer metrics.MeasureSince([]string{"consul", "session", "renew"}, time.Now()) // Get the session, from local state state := s.srv.fsm.State() diff --git a/consul/session_ttl.go b/consul/session_ttl.go index 1d9bad93c..e93357841 100644 --- a/consul/session_ttl.go +++ b/consul/session_ttl.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/armon/go-metrics" "github.com/hashicorp/consul/consul/structs" ) @@ -95,6 +96,7 @@ func (s *Server) resetSessionTimerLocked(id string, ttl time.Duration) { // invalidateSession is invoked when a session TTL is reached and we // need to invalidate the session. func (s *Server) invalidateSession(id string) { + defer metrics.MeasureSince([]string{"consul", "session_ttl", "invalidate"}, time.Now()) // Clear the session timer s.sessionTimersLock.Lock() delete(s.sessionTimers, id) @@ -142,3 +144,20 @@ func (s *Server) clearAllSessionTimers() error { s.sessionTimers = nil return nil } + +// sessionStats is a long running routine used to capture +// the number of active sessions being tracked +func (s *Server) sessionStats() { + for { + select { + case <-time.After(5 * time.Second): + s.sessionTimersLock.Lock() + num := len(s.sessionTimers) + s.sessionTimersLock.Unlock() + metrics.SetGauge([]string{"consul", "session_ttl", "active"}, float32(num)) + + case <-s.shutdownCh: + return + } + } +}