diff --git a/doc/soju.1.scd b/doc/soju.1.scd index 6838bbc..5f20b4d 100644 --- a/doc/soju.1.scd +++ b/doc/soju.1.scd @@ -320,6 +320,9 @@ abbreviated form, for instance *network* can be abbreviated as *net* or just *user delete* Delete a soju user. Only admins can delete accounts. +*server status* + Show some bouncer statistics. Only admins can query this information. + # AUTHORS Maintained by Simon Ser , who is assisted by other diff --git a/server.go b/server.go index b1f7d35..f516c2d 100644 --- a/server.go +++ b/server.go @@ -55,8 +55,9 @@ type Server struct { AcceptProxyIPs config.IPSet Identd *Identd // can be nil - db Database - stopWG sync.WaitGroup + db Database + stopWG sync.WaitGroup + connCount int64 // atomic lock sync.Mutex listeners map[net.Listener]struct{} @@ -165,6 +166,7 @@ func (s *Server) addUserLocked(user *User) *user { var lastDownstreamID uint64 = 0 func (s *Server) handle(ic ircConn) { + atomic.AddInt64(&s.connCount, 1) id := atomic.AddUint64(&lastDownstreamID, 1) dc := newDownstreamConn(s, ic, id) if err := dc.runUntilRegistered(); err != nil { @@ -177,6 +179,7 @@ func (s *Server) handle(ic ircConn) { dc.user.events <- eventDownstreamDisconnected{dc} } dc.Close() + atomic.AddInt64(&s.connCount, -1) } func (s *Server) Serve(ln net.Listener) error { @@ -249,3 +252,17 @@ func parseForwarded(h http.Header) map[string]string { _, params, _ := mime.ParseMediaType("hack; " + forwarded) return params } + +type ServerStats struct { + Users int + Downstreams int64 +} + +func (s *Server) Stats() *ServerStats { + var stats ServerStats + s.lock.Lock() + stats.Users = len(s.users) + s.lock.Unlock() + stats.Downstreams = atomic.LoadInt64(&s.connCount) + return &stats +} diff --git a/service.go b/service.go index b95f551..72ac5a9 100644 --- a/service.go +++ b/service.go @@ -292,6 +292,16 @@ func init() { }, }, }, + "server": { + children: serviceCommandSet{ + "status": { + desc: "show server statistics", + handle: handleServiceServerStatus, + admin: true, + }, + }, + admin: true, + }, } } @@ -1007,3 +1017,9 @@ func handleServiceChannelUpdate(dc *downstreamConn, params []string) error { sendServicePRIVMSG(dc, fmt.Sprintf("updated channel %q", name)) return nil } + +func handleServiceServerStatus(dc *downstreamConn, params []string) error { + stats := dc.user.srv.Stats() + sendServicePRIVMSG(dc, fmt.Sprintf("%v users, %v downstreams", stats.Users, stats.Downstreams)) + return nil +}