3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-13 07:29:30 +01:00

Merge pull request #583 from slingamn/stats.4

fix #526
This commit is contained in:
Daniel Oaks 2019-07-12 23:39:50 +10:00 committed by GitHub
commit dc87ae7ef1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 109 additions and 67 deletions

View File

@ -275,6 +275,7 @@ func (server *Server) RunClient(conn clientConn) {
client.rawHostname = session.rawHostname client.rawHostname = session.rawHostname
client.proxiedIP = session.proxiedIP client.proxiedIP = session.proxiedIP
server.stats.Add()
client.run(session) client.run(session)
} }
@ -359,6 +360,15 @@ func (client *Client) IPString() string {
return ip return ip
} }
// t returns the translated version of the given string, based on the languages configured by the client.
func (client *Client) t(originalString string) string {
languageManager := client.server.Config().languageManager
if !languageManager.Enabled() {
return originalString
}
return languageManager.Translate(client.Languages(), originalString)
}
// //
// command goroutine // command goroutine
// //
@ -922,21 +932,6 @@ func (client *Client) LoggedIntoAccount() bool {
return client.Account() != "" return client.Account() != ""
} }
// RplISupport outputs our ISUPPORT lines to the client. This is used on connection and in VERSION responses.
func (client *Client) RplISupport(rb *ResponseBuffer) {
translatedISupport := client.t("are supported by this server")
nick := client.Nick()
config := client.server.Config()
for _, cachedTokenLine := range config.Server.isupport.CachedReply {
length := len(cachedTokenLine) + 2
tokenline := make([]string, length)
tokenline[0] = nick
copy(tokenline[1:], cachedTokenLine)
tokenline[length-1] = translatedISupport
rb.Add(nil, client.server.name, RPL_ISUPPORT, tokenline...)
}
}
// Quit sets the given quit message for the client. // Quit sets the given quit message for the client.
// (You must ensure separately that destroy() is called, e.g., by returning `true` from // (You must ensure separately that destroy() is called, e.g., by returning `true` from
// the command handler or calling it yourself.) // the command handler or calling it yourself.)
@ -1095,16 +1090,8 @@ func (client *Client) destroy(session *Session) {
client.server.accounts.Logout(client) client.server.accounts.Logout(client)
// send quit messages to friends client.server.stats.Remove(registered, client.HasMode(modes.Invisible),
if registered { client.HasMode(modes.Operator) || client.HasMode(modes.LocalOperator))
client.server.stats.ChangeTotal(-1)
}
if client.HasMode(modes.Invisible) {
client.server.stats.ChangeInvisible(-1)
}
if client.HasMode(modes.Operator) || client.HasMode(modes.LocalOperator) {
client.server.stats.ChangeOperators(-1)
}
// this happens under failure to return from BRB // this happens under failure to return from BRB
if quitMessage == "" { if quitMessage == "" {

View File

@ -1638,14 +1638,7 @@ func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
// LUSERS [<mask> [<server>]] // LUSERS [<mask> [<server>]]
func lusersHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool { func lusersHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
//TODO(vegax87) Fix network statistics and additional parameters server.Lusers(client, rb)
totalCount, invisibleCount, operCount := server.stats.GetStats()
rb.Add(nil, server.name, RPL_LUSERCLIENT, client.nick, fmt.Sprintf(client.t("There are %[1]d users and %[2]d invisible on %[3]d server(s)"), totalCount-invisibleCount, invisibleCount, 1))
rb.Add(nil, server.name, RPL_LUSEROP, client.nick, strconv.Itoa(operCount), client.t("IRC Operators online"))
rb.Add(nil, server.name, RPL_LUSERCHANNELS, client.nick, strconv.Itoa(server.channels.Len()), client.t("channels formed"))
rb.Add(nil, server.name, RPL_LUSERME, client.nick, fmt.Sprintf(client.t("I have %[1]d clients and %[2]d servers"), totalCount, 1))
return false return false
} }
@ -2583,7 +2576,7 @@ func userhostHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *
// VERSION // VERSION
func versionHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool { func versionHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
rb.Add(nil, server.name, RPL_VERSION, client.nick, Ver, server.name) rb.Add(nil, server.name, RPL_VERSION, client.nick, Ver, server.name)
client.RplISupport(rb) server.RplISupport(client, rb)
return false return false
} }

View File

@ -164,6 +164,11 @@ func (lm *Manager) Count() int {
return len(lm.Languages) return len(lm.Languages)
} }
// Enabled returns whether translation is enabled.
func (lm *Manager) Enabled() bool {
return len(lm.translations) != 0
}
// Translators returns the languages we have and the translators. // Translators returns the languages we have and the translators.
func (lm *Manager) Translators() []string { func (lm *Manager) Translators() []string {
var tlist sort.StringSlice var tlist sort.StringSlice

View File

@ -50,6 +50,8 @@ const (
RPL_TRACELOG = "261" RPL_TRACELOG = "261"
RPL_TRACEEND = "262" RPL_TRACEEND = "262"
RPL_TRYAGAIN = "263" RPL_TRYAGAIN = "263"
RPL_LOCALUSERS = "265"
RPL_GLOBALUSERS = "266"
RPL_WHOISCERTFP = "276" RPL_WHOISCERTFP = "276"
RPL_AWAY = "301" RPL_AWAY = "301"
RPL_USERHOST = "302" RPL_USERHOST = "302"

View File

@ -386,7 +386,7 @@ func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) {
c.SetRegistered() c.SetRegistered()
// count new user in statistics // count new user in statistics
server.stats.ChangeTotal(1) server.stats.Register()
server.monitorManager.AlertAbout(c, true) server.monitorManager.AlertAbout(c, true)
server.playRegistrationBurst(session) server.playRegistrationBurst(session)
@ -410,7 +410,8 @@ func (server *Server) playRegistrationBurst(session *Session) {
session.Send(nil, server.name, RPL_MYINFO, d.nick, server.name, Ver, supportedUserModesString, supportedChannelModesString) session.Send(nil, server.name, RPL_MYINFO, d.nick, server.name, Ver, supportedUserModesString, supportedChannelModesString)
rb := NewResponseBuffer(session) rb := NewResponseBuffer(session)
c.RplISupport(rb) server.RplISupport(c, rb)
server.Lusers(c, rb)
server.MOTD(c, rb) server.MOTD(c, rb)
rb.Send(true) rb.Send(true)
@ -426,11 +427,34 @@ func (server *Server) playRegistrationBurst(session *Session) {
session.client.nickTimer.Touch(nil) session.client.nickTimer.Touch(nil)
} }
// t returns the translated version of the given string, based on the languages configured by the client. // RplISupport outputs our ISUPPORT lines to the client. This is used on connection and in VERSION responses.
func (client *Client) t(originalString string) string { func (server *Server) RplISupport(client *Client, rb *ResponseBuffer) {
// TODO(slingamn) investigate a fast path for this, using an atomic load to see if translation is disabled translatedISupport := client.t("are supported by this server")
languages := client.Languages() nick := client.Nick()
return client.server.Languages().Translate(languages, originalString) config := server.Config()
for _, cachedTokenLine := range config.Server.isupport.CachedReply {
length := len(cachedTokenLine) + 2
tokenline := make([]string, length)
tokenline[0] = nick
copy(tokenline[1:], cachedTokenLine)
tokenline[length-1] = translatedISupport
rb.Add(nil, server.name, RPL_ISUPPORT, tokenline...)
}
}
func (server *Server) Lusers(client *Client, rb *ResponseBuffer) {
nick := client.Nick()
stats := server.stats.GetValues()
rb.Add(nil, server.name, RPL_LUSERCLIENT, nick, fmt.Sprintf(client.t("There are %[1]d users and %[2]d invisible on %[3]d server(s)"), stats.Total-stats.Invisible, stats.Invisible, 1))
rb.Add(nil, server.name, RPL_LUSEROP, nick, strconv.Itoa(stats.Operators), client.t("IRC Operators online"))
rb.Add(nil, server.name, RPL_LUSERUNKNOWN, nick, strconv.Itoa(stats.Unknown), client.t("unregistered connections"))
rb.Add(nil, server.name, RPL_LUSERCHANNELS, nick, strconv.Itoa(server.channels.Len()), client.t("channels formed"))
rb.Add(nil, server.name, RPL_LUSERME, nick, fmt.Sprintf(client.t("I have %[1]d clients and %[2]d servers"), stats.Total, 1))
total := strconv.Itoa(stats.Total)
max := strconv.Itoa(stats.Max)
rb.Add(nil, server.name, RPL_LOCALUSERS, nick, total, max, fmt.Sprintf(client.t("Current local users %[1]s, max %[2]s"), total, max))
rb.Add(nil, server.name, RPL_GLOBALUSERS, nick, total, max, fmt.Sprintf(client.t("Current global users %[1]s, max %[2]s"), total, max))
} }
// MOTD serves the Message of the Day. // MOTD serves the Message of the Day.

View File

@ -4,43 +4,74 @@ import (
"sync" "sync"
) )
// Stats contains the numbers of total, invisible and operators on the server type StatsValues struct {
type Stats struct { Unknown int // unregistered clients
sync.RWMutex Total int // registered clients, including invisible
Max int // high-water mark of registered clients
Total int
Invisible int Invisible int
Operators int Operators int
} }
// ChangeTotal increments the total user count on server // Stats tracks statistics for a running server
func (s *Stats) ChangeTotal(i int) { type Stats struct {
s.Lock() StatsValues
defer s.Unlock()
s.Total += i mutex sync.Mutex
} }
// ChangeInvisible increments the invisible count // Adds an unregistered client
func (s *Stats) ChangeInvisible(i int) { func (s *Stats) Add() {
s.Lock() s.mutex.Lock()
defer s.Unlock() s.Unknown += 1
s.mutex.Unlock()
s.Invisible += i
} }
// ChangeOperators increases the operator count // Transition a client from unregistered to registered
func (s *Stats) ChangeOperators(i int) { func (s *Stats) Register() {
s.Lock() s.mutex.Lock()
defer s.Unlock() s.Unknown -= 1
s.Total += 1
if s.Max < s.Total {
s.Max = s.Total
}
s.mutex.Unlock()
}
s.Operators += i // Modify the Invisible count
func (s *Stats) ChangeInvisible(increment int) {
s.mutex.Lock()
s.Invisible += increment
s.mutex.Unlock()
}
// Modify the Operator count
func (s *Stats) ChangeOperators(increment int) {
s.mutex.Lock()
s.Operators += increment
s.mutex.Unlock()
}
// Remove a user from the server
func (s *Stats) Remove(registered, invisible, operator bool) {
s.mutex.Lock()
if registered {
s.Total -= 1
} else {
s.Unknown -= 1
}
if invisible {
s.Invisible -= 1
}
if operator {
s.Operators -= 1
}
s.mutex.Unlock()
} }
// GetStats retrives total, invisible and oper count // GetStats retrives total, invisible and oper count
func (s *Stats) GetStats() (int, int, int) { func (s *Stats) GetValues() (result StatsValues) {
s.Lock() s.mutex.Lock()
defer s.Unlock() result = s.StatsValues
s.mutex.Unlock()
return s.Total, s.Invisible, s.Operators return
} }