logger: Move to separate package, make *much* nicer

This commit is contained in:
Daniel Oaks 2017-03-10 22:02:08 +10:00
parent ef9acf53f8
commit 439331cfb8
6 changed files with 160 additions and 86 deletions

View File

@ -264,7 +264,7 @@ func (channel *Channel) Join(client *Client, key string) {
return return
} }
client.server.logger.Log(LogDebug, "join", fmt.Sprintf("%s joined channel %s", client.nick, channel.name)) client.server.logger.Debug("join", fmt.Sprintf("%s joined channel %s", client.nick, channel.name))
for member := range channel.members { for member := range channel.members {
if member.capabilities[ExtendedJoin] { if member.capabilities[ExtendedJoin] {
@ -306,7 +306,7 @@ func (channel *Channel) Part(client *Client, message string) {
} }
channel.Quit(client) channel.Quit(client)
client.server.logger.Log(LogDebug, "part", fmt.Sprintf("%s left channel %s", client.nick, channel.name)) client.server.logger.Debug("part", fmt.Sprintf("%s left channel %s", client.nick, channel.name))
} }
func (channel *Channel) GetTopic(client *Client) { func (channel *Channel) GetTopic(client *Client) {

View File

@ -170,7 +170,7 @@ func (client *Client) run() {
maxlenTags, maxlenRest := client.maxlens() maxlenTags, maxlenRest := client.maxlens()
client.server.logger.Log(LogDebug, "userinput ", client.nick, "<- ", line) client.server.logger.Debug("userinput ", client.nick, "<- ", line)
msg, err = ircmsg.ParseLineMaxLen(line, maxlenTags, maxlenRest) msg, err = ircmsg.ParseLineMaxLen(line, maxlenTags, maxlenRest)
if err == ircmsg.ErrorLineIsEmpty { if err == ircmsg.ErrorLineIsEmpty {
@ -404,7 +404,7 @@ func (client *Client) AllNickmasks() []string {
// SetNickname sets the very first nickname for the client. // SetNickname sets the very first nickname for the client.
func (client *Client) SetNickname(nickname string) error { func (client *Client) SetNickname(nickname string) error {
if client.HasNick() { if client.HasNick() {
client.server.logger.Log(LogError, "nick", fmt.Sprintf("%s nickname already set, something is wrong with server consistency", client.nickMaskString)) client.server.logger.Error("nick", fmt.Sprintf("%s nickname already set, something is wrong with server consistency", client.nickMaskString))
return ErrNickAlreadySet return ErrNickAlreadySet
} }
@ -421,7 +421,7 @@ func (client *Client) ChangeNickname(nickname string) error {
origNickMask := client.nickMaskString origNickMask := client.nickMaskString
err := client.server.clients.Replace(client.nick, nickname, client) err := client.server.clients.Replace(client.nick, nickname, client)
if err == nil { if err == nil {
client.server.logger.Log(LogDebug, "nick", fmt.Sprintf("%s changed nickname to %s", client.nick, nickname)) client.server.logger.Debug("nick", fmt.Sprintf("%s changed nickname to %s", client.nick, nickname))
client.server.whoWas.Append(client) client.server.whoWas.Append(client)
client.nick = nickname client.nick = nickname
client.updateNickMask() client.updateNickMask()
@ -446,7 +446,7 @@ func (client *Client) destroy() {
return return
} }
client.server.logger.Log(LogDebug, "quit", fmt.Sprintf("%s is no longer on the server", client.nick)) client.server.logger.Debug("quit", fmt.Sprintf("%s is no longer on the server", client.nick))
// send quit/error message to client if they haven't been sent already // send quit/error message to client if they haven't been sent already
client.Quit("Connection closed") client.Quit("Connection closed")
@ -595,7 +595,7 @@ func (client *Client) Send(tags *map[string]ircmsg.TagValue, prefix string, comm
line = line[:len(line)-3] + "\r\n" line = line[:len(line)-3] + "\r\n"
} }
client.server.logger.Log(LogDebug, "useroutput", client.nick, " ->", strings.TrimRight(line, "\r\n")) client.server.logger.Debug("useroutput", client.nick, " ->", strings.TrimRight(line, "\r\n"))
client.socket.Write(line) client.socket.Write(line)
return nil return nil

View File

@ -15,6 +15,7 @@ import (
"time" "time"
"github.com/DanielOaks/oragono/irc/custime" "github.com/DanielOaks/oragono/irc/custime"
"github.com/DanielOaks/oragono/irc/logger"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
@ -119,13 +120,14 @@ type ConnectionThrottleConfig struct {
type LoggingConfig struct { type LoggingConfig struct {
Method string Method string
Methods map[string]bool MethodStderr bool
MethodFile bool
Filename string Filename string
TypeString string `yaml:"type"` TypeString string `yaml:"type"`
Types map[string]bool `yaml:"real-types"` Types []string `yaml:"real-types"`
ExcludedTypes map[string]bool `yaml:"real-excluded-types"` ExcludedTypes []string `yaml:"real-excluded-types"`
LevelString string `yaml:"level"` LevelString string `yaml:"level"`
Level LogLevel `yaml:"level-real"` Level logger.Level `yaml:"level-real"`
} }
type LineLenConfig struct { type LineLenConfig struct {
@ -389,26 +391,26 @@ func LoadConfig(filename string) (config *Config, err error) {
var newLogConfigs []LoggingConfig var newLogConfigs []LoggingConfig
for _, logConfig := range config.Logging { for _, logConfig := range config.Logging {
// methods // methods
logConfig.Methods = make(map[string]bool) methods := make(map[string]bool)
for _, method := range strings.Split(logConfig.Method, " ") { for _, method := range strings.Split(logConfig.Method, " ") {
if len(method) > 0 { if len(method) > 0 {
logConfig.Methods[strings.ToLower(method)] = true methods[strings.ToLower(method)] = true
} }
} }
if logConfig.Methods["file"] && logConfig.Filename == "" { if methods["file"] && logConfig.Filename == "" {
return nil, errors.New("Logging configuration specifies 'file' method but 'filename' is empty") return nil, errors.New("Logging configuration specifies 'file' method but 'filename' is empty")
} }
logConfig.MethodFile = methods["file"]
logConfig.MethodStderr = methods["stderr"]
// levels // levels
level, exists := logLevelNames[strings.ToLower(logConfig.LevelString)] level, exists := logger.LogLevelNames[strings.ToLower(logConfig.LevelString)]
if !exists { if !exists {
return nil, fmt.Errorf("Could not translate log leve [%s]", logConfig.LevelString) return nil, fmt.Errorf("Could not translate log leve [%s]", logConfig.LevelString)
} }
logConfig.Level = level logConfig.Level = level
// types // types
logConfig.Types = make(map[string]bool)
logConfig.ExcludedTypes = make(map[string]bool)
for _, typeStr := range strings.Split(logConfig.TypeString, " ") { for _, typeStr := range strings.Split(logConfig.TypeString, " ") {
if len(typeStr) == 0 { if len(typeStr) == 0 {
continue continue
@ -418,9 +420,9 @@ func LoadConfig(filename string) (config *Config, err error) {
} }
if typeStr[0] == '-' { if typeStr[0] == '-' {
typeStr = typeStr[1:] typeStr = typeStr[1:]
logConfig.ExcludedTypes[typeStr] = true logConfig.ExcludedTypes = append(logConfig.ExcludedTypes, typeStr)
} else { } else {
logConfig.Types[typeStr] = true logConfig.Types = append(logConfig.Types, typeStr)
} }
} }
if len(logConfig.Types) < 1 { if len(logConfig.Types) < 1 {

View File

@ -1,7 +1,7 @@
// Copyright (c) 2017 Daniel Oaks <daniel@danieloaks.net> // Copyright (c) 2017 Daniel Oaks <daniel@danieloaks.net>
// released under the MIT license // released under the MIT license
package irc package logger
import ( import (
"bufio" "bufio"
@ -17,62 +17,84 @@ import (
"github.com/mgutz/ansi" "github.com/mgutz/ansi"
) )
// LogLevel represents the level to log messages at. // Level represents the level to log messages at.
type LogLevel int type Level int
const ( const (
// LogDebug represents debug messages. // LogDebug represents debug messages.
LogDebug LogLevel = iota LogDebug Level = iota
// LogInfo represents informational messages. // LogInfo represents informational messages.
LogInfo LogInfo
// LogWarn represents warnings. // LogWarning represents warnings.
LogWarn LogWarning
// LogError represents errors. // LogError represents errors.
LogError LogError
) )
var ( var (
logLevelNames = map[string]LogLevel{ LogLevelNames = map[string]Level{
"debug": LogDebug, "debug": LogDebug,
"info": LogInfo, "info": LogInfo,
"warn": LogWarn, "warn": LogWarning,
"warning": LogWarn, "warning": LogWarning,
"warnings": LogWarn, "warnings": LogWarning,
"error": LogError, "error": LogError,
"errors": LogError, "errors": LogError,
} }
logLevelDisplayNames = map[LogLevel]string{ LogLevelDisplayNames = map[Level]string{
LogDebug: "debug", LogDebug: "debug",
LogInfo: "info", LogInfo: "info",
LogWarn: "warning", LogWarning: "warning",
LogError: "error", LogError: "error",
} }
) )
// Logger is the main interface used to log debug/info/error messages. // Manager is the main interface used to log debug/info/error messages.
type Logger struct { type Manager struct {
loggers []SingleLogger loggers []singleLogger
stderrWriteLock sync.Mutex stderrWriteLock sync.Mutex
DumpingRawInOut bool DumpingRawInOut bool
} }
// NewLogger returns a new Logger. // Config represents the configuration of a single logger.
func NewLogger(config []LoggingConfig) (*Logger, error) { type Config struct {
var logger Logger // logging methods
MethodStderr bool
MethodFile bool
Filename string
// logging level
Level Level
// logging types
Types []string
ExcludedTypes []string
}
// NewManager returns a new log manager.
func NewManager(config ...Config) (*Manager, error) {
var logger Manager
for _, logConfig := range config { for _, logConfig := range config {
sLogger := SingleLogger{ typeMap := make(map[string]bool)
MethodSTDERR: logConfig.Methods["stderr"], for _, name := range logConfig.Types {
typeMap[name] = true
}
excludedTypeMap := make(map[string]bool)
for _, name := range logConfig.ExcludedTypes {
excludedTypeMap[name] = true
}
sLogger := singleLogger{
MethodSTDERR: logConfig.MethodStderr,
MethodFile: fileMethod{ MethodFile: fileMethod{
Enabled: logConfig.Methods["file"], Enabled: logConfig.MethodFile,
Filename: logConfig.Filename, Filename: logConfig.Filename,
}, },
Level: logConfig.Level, Level: logConfig.Level,
Types: logConfig.Types, Types: typeMap,
ExcludedTypes: logConfig.ExcludedTypes, ExcludedTypes: excludedTypeMap,
stderrWriteLock: &logger.stderrWriteLock, stderrWriteLock: &logger.stderrWriteLock,
} }
if logConfig.Types["userinput"] || logConfig.Types["useroutput"] || (logConfig.Types["*"] && !(logConfig.ExcludedTypes["userinput"] && logConfig.ExcludedTypes["useroutput"])) { if typeMap["userinput"] || typeMap["useroutput"] || (typeMap["*"] && !(excludedTypeMap["userinput"] && excludedTypeMap["useroutput"])) {
logger.DumpingRawInOut = true logger.DumpingRawInOut = true
} }
if sLogger.MethodFile.Enabled { if sLogger.MethodFile.Enabled {
@ -91,12 +113,47 @@ func NewLogger(config []LoggingConfig) (*Logger, error) {
} }
// Log logs the given message with the given details. // Log logs the given message with the given details.
func (logger *Logger) Log(level LogLevel, logType string, messageParts ...string) { func (logger *Manager) Log(level Level, logType string, messageParts ...string) {
for _, singleLogger := range logger.loggers { for _, singleLogger := range logger.loggers {
singleLogger.Log(level, logType, messageParts...) singleLogger.Log(level, logType, messageParts...)
} }
} }
// Debug logs the given message as a debug message.
func (logger *Manager) Debug(logType string, messageParts ...string) {
for _, singleLogger := range logger.loggers {
singleLogger.Log(LogDebug, logType, messageParts...)
}
}
// Info logs the given message as an info message.
func (logger *Manager) Info(logType string, messageParts ...string) {
for _, singleLogger := range logger.loggers {
singleLogger.Log(LogInfo, logType, messageParts...)
}
}
// Warning logs the given message as a warning message.
func (logger *Manager) Warning(logType string, messageParts ...string) {
for _, singleLogger := range logger.loggers {
singleLogger.Log(LogWarning, logType, messageParts...)
}
}
// Error logs the given message as an error message.
func (logger *Manager) Error(logType string, messageParts ...string) {
for _, singleLogger := range logger.loggers {
singleLogger.Log(LogError, logType, messageParts...)
}
}
// Fatal logs the given message as an error message, then exits.
func (logger *Manager) Fatal(logType string, messageParts ...string) {
logger.Error(logType, messageParts...)
logger.Error("FATAL", "Fatal error encountered, application exiting")
os.Exit(1)
}
type fileMethod struct { type fileMethod struct {
Enabled bool Enabled bool
Filename string Filename string
@ -104,18 +161,18 @@ type fileMethod struct {
Writer *bufio.Writer Writer *bufio.Writer
} }
// SingleLogger represents a single logger instance. // singleLogger represents a single logger instance.
type SingleLogger struct { type singleLogger struct {
stderrWriteLock *sync.Mutex stderrWriteLock *sync.Mutex
MethodSTDERR bool MethodSTDERR bool
MethodFile fileMethod MethodFile fileMethod
Level LogLevel Level Level
Types map[string]bool Types map[string]bool
ExcludedTypes map[string]bool ExcludedTypes map[string]bool
} }
// Log logs the given message with the given details. // Log logs the given message with the given details.
func (logger *SingleLogger) Log(level LogLevel, logType string, messageParts ...string) { func (logger *singleLogger) Log(level Level, logType string, messageParts ...string) {
// no logging enabled // no logging enabled
if !(logger.MethodSTDERR || logger.MethodFile.Enabled) { if !(logger.MethodSTDERR || logger.MethodFile.Enabled) {
return return
@ -142,10 +199,10 @@ func (logger *SingleLogger) Log(level LogLevel, logType string, messageParts ...
debug := ansi.ColorFunc("78") debug := ansi.ColorFunc("78")
section := ansi.ColorFunc("229") section := ansi.ColorFunc("229")
levelDisplay := logLevelDisplayNames[level] levelDisplay := LogLevelDisplayNames[level]
if level == LogError { if level == LogError {
levelDisplay = alert(levelDisplay) levelDisplay = alert(levelDisplay)
} else if level == LogWarn { } else if level == LogWarning {
levelDisplay = warn(levelDisplay) levelDisplay = warn(levelDisplay)
} else if level == LogInfo { } else if level == LogInfo {
levelDisplay = info(levelDisplay) levelDisplay = info(levelDisplay)
@ -155,7 +212,7 @@ func (logger *SingleLogger) Log(level LogLevel, logType string, messageParts ...
sep := grey(":") sep := grey(":")
fullStringFormatted := fmt.Sprintf("%s %s %s %s %s %s ", timeGrey(time.Now().UTC().Format("2006-01-02T15:04:05Z")), sep, levelDisplay, sep, section(logType), sep) fullStringFormatted := fmt.Sprintf("%s %s %s %s %s %s ", timeGrey(time.Now().UTC().Format("2006-01-02T15:04:05Z")), sep, levelDisplay, sep, section(logType), sep)
fullStringRaw := fmt.Sprintf("%s : %s : %s : ", time.Now().UTC().Format("2006-01-02T15:04:05Z"), logLevelDisplayNames[level], section(logType)) fullStringRaw := fmt.Sprintf("%s : %s : %s : ", time.Now().UTC().Format("2006-01-02T15:04:05Z"), LogLevelDisplayNames[level], section(logType))
for i, p := range messageParts { for i, p := range messageParts {
fullStringFormatted += p fullStringFormatted += p
fullStringRaw += p fullStringRaw += p

View File

@ -24,6 +24,7 @@ import (
"time" "time"
"github.com/DanielOaks/girc-go/ircmsg" "github.com/DanielOaks/girc-go/ircmsg"
"github.com/DanielOaks/oragono/irc/logger"
"github.com/tidwall/buntdb" "github.com/tidwall/buntdb"
) )
@ -102,7 +103,7 @@ type Server struct {
listenerEventActMutex sync.Mutex listenerEventActMutex sync.Mutex
listeners map[string]ListenerInterface listeners map[string]ListenerInterface
listenerUpdateMutex sync.Mutex listenerUpdateMutex sync.Mutex
logger *Logger logger *logger.Manager
monitoring map[string][]Client monitoring map[string][]Client
motdLines []string motdLines []string
name string name string
@ -137,7 +138,7 @@ type clientConn struct {
} }
// NewServer returns a new Oragono server. // NewServer returns a new Oragono server.
func NewServer(configFilename string, config *Config, logger *Logger) (*Server, error) { func NewServer(configFilename string, config *Config, logger *logger.Manager) (*Server, error) {
casefoldedName, err := Casefold(config.Server.Name) casefoldedName, err := Casefold(config.Server.Name)
if err != nil { if err != nil {
return nil, fmt.Errorf("Server name isn't valid [%s]: %s", config.Server.Name, err.Error()) return nil, fmt.Errorf("Server name isn't valid [%s]: %s", config.Server.Name, err.Error())
@ -226,7 +227,7 @@ func NewServer(configFilename string, config *Config, logger *Logger) (*Server,
} }
// open data store // open data store
server.logger.Log(LogDebug, "startup", "Opening datastore") server.logger.Debug("startup", "Opening datastore")
db, err := buntdb.Open(config.Datastore.Path) db, err := buntdb.Open(config.Datastore.Path)
if err != nil { if err != nil {
return nil, fmt.Errorf("Failed to open datastore: %s", err.Error()) return nil, fmt.Errorf("Failed to open datastore: %s", err.Error())
@ -237,7 +238,7 @@ func NewServer(configFilename string, config *Config, logger *Logger) (*Server,
err = server.store.View(func(tx *buntdb.Tx) error { err = server.store.View(func(tx *buntdb.Tx) error {
version, _ := tx.Get(keySchemaVersion) version, _ := tx.Get(keySchemaVersion)
if version != latestDbSchema { if version != latestDbSchema {
logger.Log(LogError, "startup", "server", fmt.Sprintf("Database must be updated. Expected schema v%s, got v%s.", latestDbSchema, version)) logger.Error("startup", "server", fmt.Sprintf("Database must be updated. Expected schema v%s, got v%s.", latestDbSchema, version))
return errDbOutOfDate return errDbOutOfDate
} }
return nil return nil
@ -249,12 +250,12 @@ func NewServer(configFilename string, config *Config, logger *Logger) (*Server,
} }
// load *lines // load *lines
server.logger.Log(LogDebug, "startup", "Loading D/Klines") server.logger.Debug("startup", "Loading D/Klines")
server.loadDLines() server.loadDLines()
server.loadKLines() server.loadKLines()
// load password manager // load password manager
server.logger.Log(LogDebug, "startup", "Loading passwords") server.logger.Debug("startup", "Loading passwords")
err = server.store.View(func(tx *buntdb.Tx) error { err = server.store.View(func(tx *buntdb.Tx) error {
saltString, err := tx.Get(keySalt) saltString, err := tx.Get(keySalt)
if err != nil { if err != nil {
@ -274,7 +275,7 @@ func NewServer(configFilename string, config *Config, logger *Logger) (*Server,
return nil, fmt.Errorf("Could not load salt: %s", err.Error()) return nil, fmt.Errorf("Could not load salt: %s", err.Error())
} }
server.logger.Log(LogDebug, "startup", "Loading MOTD") server.logger.Debug("startup", "Loading MOTD")
if config.Server.MOTD != "" { if config.Server.MOTD != "" {
file, err := os.Open(config.Server.MOTD) file, err := os.Open(config.Server.MOTD)
if err == nil { if err == nil {
@ -320,7 +321,7 @@ func NewServer(configFilename string, config *Config, logger *Logger) (*Server,
// start API if enabled // start API if enabled
if server.restAPI.Enabled { if server.restAPI.Enabled {
logger.Log(LogInfo, "startup", "server", fmt.Sprintf("%s rest API started on %s.", server.name, server.restAPI.Listen)) logger.Info("startup", "server", fmt.Sprintf("%s rest API started on %s.", server.name, server.restAPI.Listen))
server.startRestAPI() server.startRestAPI()
} }
@ -389,7 +390,7 @@ func (server *Server) Shutdown() {
server.clients.ByNickMutex.RUnlock() server.clients.ByNickMutex.RUnlock()
if err := server.store.Close(); err != nil { if err := server.store.Close(); err != nil {
server.logger.Log(LogError, "shutdown", fmt.Sprintln("Could not close datastore:", err)) server.logger.Error("shutdown", fmt.Sprintln("Could not close datastore:", err))
} }
} }
@ -406,10 +407,10 @@ func (server *Server) Run() {
done = true done = true
case <-server.rehashSignal: case <-server.rehashSignal:
server.logger.Log(LogInfo, "rehash", "Rehashing due to SIGHUP") server.logger.Info("rehash", "Rehashing due to SIGHUP")
err := server.rehash() err := server.rehash()
if err != nil { if err != nil {
server.logger.Log(LogError, "rehash", fmt.Sprintln("Failed to rehash:", err.Error())) server.logger.Error("rehash", fmt.Sprintln("Failed to rehash:", err.Error()))
} }
case conn := <-server.newConns: case conn := <-server.newConns:
@ -461,7 +462,7 @@ func (server *Server) Run() {
continue continue
} }
server.logger.Log(LogDebug, "localconnect-ip", fmt.Sprintf("Client connecting from %v", ipaddr)) server.logger.Debug("localconnect-ip", fmt.Sprintf("Client connecting from %v", ipaddr))
go NewClient(server, conn.Conn, conn.IsTLS) go NewClient(server, conn.Conn, conn.IsTLS)
continue continue
@ -510,7 +511,7 @@ func (server *Server) createListener(addr string, tlsMap map[string]*tls.Config)
server.listeners[addr] = li server.listeners[addr] = li
// start listening // start listening
server.logger.Log(LogInfo, "listeners", fmt.Sprintf("listening on %s using %s.", addr, tlsString)) server.logger.Info("listeners", fmt.Sprintf("listening on %s using %s.", addr, tlsString))
// setup accept goroutine // setup accept goroutine
go func() { go func() {
@ -562,7 +563,7 @@ func (server *Server) createListener(addr string, tlsMap map[string]*tls.Config)
server.listenerUpdateMutex.Unlock() server.listenerUpdateMutex.Unlock()
// print notice // print notice
server.logger.Log(LogInfo, "listeners", fmt.Sprintf("updated listener %s using %s.", addr, tlsString)) server.logger.Info("listeners", fmt.Sprintf("updated listener %s using %s.", addr, tlsString))
} }
default: default:
// no events waiting for us, fall-through and continue // no events waiting for us, fall-through and continue
@ -578,7 +579,7 @@ func (server *Server) createListener(addr string, tlsMap map[string]*tls.Config)
func (server *Server) wslisten(addr string, tlsMap map[string]*TLSListenConfig) { func (server *Server) wslisten(addr string, tlsMap map[string]*TLSListenConfig) {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" { if r.Method != "GET" {
server.logger.Log(LogError, "ws", addr, fmt.Sprintf("%s method not allowed", r.Method)) server.logger.Error("ws", addr, fmt.Sprintf("%s method not allowed", r.Method))
return return
} }
@ -591,7 +592,7 @@ func (server *Server) wslisten(addr string, tlsMap map[string]*TLSListenConfig)
ws, err := upgrader.Upgrade(w, r, nil) ws, err := upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
server.logger.Log(LogError, "ws", addr, fmt.Sprintf("%s websocket upgrade error: %s", server.name, err)) server.logger.Error("ws", addr, fmt.Sprintf("%s websocket upgrade error: %s", server.name, err))
return return
} }
@ -609,7 +610,7 @@ func (server *Server) wslisten(addr string, tlsMap map[string]*TLSListenConfig)
if listenTLS { if listenTLS {
tlsString = "TLS" tlsString = "TLS"
} }
server.logger.Log(LogInfo, "listeners", fmt.Sprintf("websocket listening on %s using %s.", addr, tlsString)) server.logger.Info("listeners", fmt.Sprintf("websocket listening on %s using %s.", addr, tlsString))
if listenTLS { if listenTLS {
err = http.ListenAndServeTLS(addr, config.Cert, config.Key, nil) err = http.ListenAndServeTLS(addr, config.Cert, config.Key, nil)
@ -617,7 +618,7 @@ func (server *Server) wslisten(addr string, tlsMap map[string]*TLSListenConfig)
err = http.ListenAndServe(addr, nil) err = http.ListenAndServe(addr, nil)
} }
if err != nil { if err != nil {
server.logger.Log(LogError, "listeners", fmt.Sprintf("listenAndServe error [%s]: %s", tlsString, err)) server.logger.Error("listeners", fmt.Sprintf("listenAndServe error [%s]: %s", tlsString, err))
} }
}() }()
} }
@ -651,7 +652,7 @@ func (server *Server) tryRegister(c *Client) {
} }
// continue registration // continue registration
server.logger.Log(LogDebug, "localconnect", fmt.Sprintf("Client registered [%s]", c.nick)) server.logger.Debug("localconnect", fmt.Sprintf("Client registered [%s]", c.nick))
c.Register() c.Register()
// send welcome text // send welcome text
@ -1241,13 +1242,13 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
// rehash reloads the config and applies the changes from the config file. // rehash reloads the config and applies the changes from the config file.
func (server *Server) rehash() error { func (server *Server) rehash() error {
server.logger.Log(LogDebug, "rehash", "Starting rehash") server.logger.Debug("rehash", "Starting rehash")
// only let one REHASH go on at a time // only let one REHASH go on at a time
server.rehashMutex.Lock() server.rehashMutex.Lock()
defer server.rehashMutex.Unlock() defer server.rehashMutex.Unlock()
server.logger.Log(LogDebug, "rehash", "Got rehash lock") server.logger.Debug("rehash", "Got rehash lock")
config, err := LoadConfig(server.configFilename) config, err := LoadConfig(server.configFilename)
@ -1326,7 +1327,7 @@ func (server *Server) rehash() error {
// STS // STS
stsValue := config.Server.STS.Value() stsValue := config.Server.STS.Value()
var stsDisabled bool var stsDisabled bool
server.logger.Log(LogDebug, "rehash", "STS Vals", CapValues[STS], stsValue, fmt.Sprintf("server[%v] config[%v]", server.stsEnabled, config.Server.STS.Enabled)) server.logger.Debug("rehash", "STS Vals", CapValues[STS], stsValue, fmt.Sprintf("server[%v] config[%v]", server.stsEnabled, config.Server.STS.Enabled))
if config.Server.STS.Enabled && !server.stsEnabled { if config.Server.STS.Enabled && !server.stsEnabled {
// enabling STS // enabling STS
SupportedCapabilities[STS] = true SupportedCapabilities[STS] = true
@ -1351,7 +1352,7 @@ func (server *Server) rehash() error {
// updated caps get DEL'd and then NEW'd // updated caps get DEL'd and then NEW'd
// so, we can just add updated ones to both removed and added lists here and they'll be correctly handled // so, we can just add updated ones to both removed and added lists here and they'll be correctly handled
server.logger.Log(LogDebug, "rehash", "Updated Caps", updatedCaps.String(Cap301), strconv.Itoa(len(updatedCaps))) server.logger.Debug("rehash", "Updated Caps", updatedCaps.String(Cap301), strconv.Itoa(len(updatedCaps)))
if len(updatedCaps) > 0 { if len(updatedCaps) > 0 {
for capab := range updatedCaps { for capab := range updatedCaps {
addedCaps[capab] = true addedCaps[capab] = true
@ -1470,13 +1471,13 @@ func (server *Server) rehash() error {
// REHASH // REHASH
func rehashHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { func rehashHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
server.logger.Log(LogInfo, "rehash", fmt.Sprintf("REHASH command used by %s", client.nick)) server.logger.Info("rehash", fmt.Sprintf("REHASH command used by %s", client.nick))
err := server.rehash() err := server.rehash()
if err == nil { if err == nil {
client.Send(nil, server.name, RPL_REHASHING, client.nick, "ircd.yaml", "Rehashing") client.Send(nil, server.name, RPL_REHASHING, client.nick, "ircd.yaml", "Rehashing")
} else { } else {
server.logger.Log(LogError, "rehash", fmt.Sprintln("Failed to rehash:", err.Error())) server.logger.Error("rehash", fmt.Sprintln("Failed to rehash:", err.Error()))
client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, "REHASH", err.Error()) client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, "REHASH", err.Error())
} }
return false return false

View File

@ -13,6 +13,7 @@ import (
"time" "time"
"github.com/DanielOaks/oragono/irc" "github.com/DanielOaks/oragono/irc"
"github.com/DanielOaks/oragono/irc/logger"
"github.com/DanielOaks/oragono/mkcerts" "github.com/DanielOaks/oragono/mkcerts"
"github.com/docopt/docopt-go" "github.com/docopt/docopt-go"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
@ -43,7 +44,20 @@ Options:
log.Fatal("Config file did not load successfully:", err.Error()) log.Fatal("Config file did not load successfully:", err.Error())
} }
logger, err := irc.NewLogger(config.Logging) // assemble separate log configs
var logConfigs []logger.Config
for _, lConfig := range config.Logging {
logConfigs = append(logConfigs, logger.Config{
MethodStderr: lConfig.MethodStderr,
MethodFile: lConfig.MethodFile,
Filename: lConfig.Filename,
Level: lConfig.Level,
Types: lConfig.Types,
ExcludedTypes: lConfig.ExcludedTypes,
})
}
logger, err := logger.NewManager(logConfigs...)
if err != nil { if err != nil {
log.Fatal("Logger did not load successfully:", err.Error()) log.Fatal("Logger did not load successfully:", err.Error())
} }
@ -91,16 +105,16 @@ Options:
} else if arguments["run"].(bool) { } else if arguments["run"].(bool) {
rand.Seed(time.Now().UTC().UnixNano()) rand.Seed(time.Now().UTC().UnixNano())
if !arguments["--quiet"].(bool) { if !arguments["--quiet"].(bool) {
logger.Log(irc.LogInfo, "startup", fmt.Sprintf("Oragono v%s starting", irc.SemVer)) logger.Info("startup", fmt.Sprintf("Oragono v%s starting", irc.SemVer))
} }
server, err := irc.NewServer(configfile, config, logger) server, err := irc.NewServer(configfile, config, logger)
if err != nil { if err != nil {
logger.Log(irc.LogError, "startup", fmt.Sprintf("Could not load server: %s", err.Error())) logger.Error("startup", fmt.Sprintf("Could not load server: %s", err.Error()))
return return
} }
if !arguments["--quiet"].(bool) { if !arguments["--quiet"].(bool) {
logger.Log(irc.LogInfo, "startup", "Server running") logger.Info("startup", "Server running")
defer logger.Log(irc.LogInfo, "shutdown", fmt.Sprintf("Oragono v%s exiting", irc.SemVer)) defer logger.Info("shutdown", fmt.Sprintf("Oragono v%s exiting", irc.SemVer))
} }
server.Run() server.Run()
} }