diff --git a/irc/logger.go b/irc/logger.go new file mode 100644 index 00000000..90348521 --- /dev/null +++ b/irc/logger.go @@ -0,0 +1,106 @@ +// Copyright (c) 2017 Daniel Oaks +// released under the MIT license + +package irc + +import ( + "bufio" + "fmt" + "os" + "time" +) + +// LogLevel represents the level to log messages at. +type LogLevel int + +const ( + // LogDebug represents debug messages. + LogDebug LogLevel = iota + // LogInfo represents informational messages. + LogInfo + // LogWarn represents warnings. + LogWarn + // LogError represents errors. + LogError +) + +// ClientLogger is a logger dedicated to a single client. This is a convenience class that +// automagically adds the client nick to logged messages. +type ClientLogger struct { + client *Client +} + +// NewClientLogger returns a new ClientLogger. +func NewClientLogger(client *Client) ClientLogger { + logger := ClientLogger{ + client: client, + } + return logger +} + +// Log logs the given message with the given details. +func (logger *ClientLogger) Log(level LogLevel, logType, object, message string) { + object = fmt.Sprintf("%s : %s", logger.client.nick, object) + logger.client.server.logger.Log(level, logType, object, message) +} + +// Logger is the main interface used to log debug/info/error messages. +type Logger struct { + loggers []SingleLogger +} + +// NewLogger returns a new Logger. +func NewLogger(config LogConfig) (*Logger, error) { + return nil, fmt.Errorf("Not implemented") +} + +// Log logs the given message with the given details. +func (logger *Logger) Log(level LogLevel, logType, object, message string) { + for _, singleLogger := range logger.loggers { + singleLogger.Log(level, logType, object, message) + } +} + +// SingleLogger represents a single logger instance. +type SingleLogger struct { + MethodSTDERR bool + MethodFile struct { + Enabled bool + Filename string + File os.File + Writer bufio.Writer + } + Level LogLevel + Types map[string]bool + ExcludedTypes map[string]bool +} + +// Log logs the given message with the given details. +func (logger *SingleLogger) Log(level LogLevel, logType, object, message string) { + // no logging enabled + if !(logger.MethodSTDERR || logger.MethodFile.Enabled) { + return + } + + // ensure we're logging to the given level + if level < logger.Level { + return + } + + // ensure we're capturing this logType + capturing := (logger.Types["*"] || logger.Types[logType]) && !logger.ExcludedTypes["*"] && !logger.ExcludedTypes[logType] + if !capturing { + return + } + + // assemble full line + fullString := fmt.Sprintf("%s : %s : %s : %s", time.Now().UTC().Format("2006-01-02T15:04:05.999Z"), logType, object, message) + + // output + if logger.MethodSTDERR { + fmt.Fprintln(os.Stderr, fullString) + } + if logger.MethodFile.Enabled { + logger.MethodFile.Writer.WriteString(fullString + "\n") + } +} diff --git a/irc/logging.go b/irc/logging.go deleted file mode 100644 index b2ab34bd..00000000 --- a/irc/logging.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2012-2014 Jeremy Latt -// released under the MIT license - -package irc - -import ( - "io" - "log" - "os" -) - -type Logging struct { - debug *log.Logger - info *log.Logger - warn *log.Logger - error *log.Logger -} - -var ( - levels = map[string]uint8{ - "debug": 4, - "info": 3, - "warn": 2, - "error": 1, - } - devNull io.Writer -) - -func init() { - var err error - devNull, err = os.Open(os.DevNull) - if err != nil { - log.Fatal(err) - } -} - -func NewLogger(on bool) *log.Logger { - return log.New(output(on), "", log.LstdFlags) -} - -func output(on bool) io.Writer { - if on { - return os.Stdout - } - return devNull -} - -func (logging *Logging) SetLevel(level string) { - logging.debug = NewLogger(levels[level] >= levels["debug"]) - logging.info = NewLogger(levels[level] >= levels["info"]) - logging.warn = NewLogger(levels[level] >= levels["warn"]) - logging.error = NewLogger(levels[level] >= levels["error"]) -} - -func NewLogging(level string) *Logging { - logging := &Logging{} - logging.SetLevel(level) - return logging -} - -var ( - // Log is the default logger. - Log = NewLogging("warn") -) diff --git a/irc/server.go b/irc/server.go index 6f2cad19..329e11cc 100644 --- a/irc/server.go +++ b/irc/server.go @@ -80,18 +80,18 @@ type ListenerEvent struct { // Server is the main Oragono server. type Server struct { + accountAuthenticationEnabled bool accountRegistration *AccountRegistration accounts map[string]*ClientAccount - accountAuthenticationEnabled bool channels ChannelNameMap checkIdent bool clients *ClientLookupSet commands chan Command configFilename string - connectionThrottle *ConnectionThrottle - connectionThrottleMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack connectionLimits *ConnectionLimits connectionLimitsMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack + connectionThrottle *ConnectionThrottle + connectionThrottleMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack ctime time.Time currentOpers map[*Client]bool dlines *DLineManager @@ -102,6 +102,7 @@ type Server struct { listenerEventActMutex sync.Mutex listeners map[string]ListenerInterface listenerUpdateMutex sync.Mutex + logger *Logger monitoring map[string][]Client motdLines []string name string