diff options
Diffstat (limited to 'ethlog/loggers.go')
-rw-r--r-- | ethlog/loggers.go | 87 |
1 files changed, 70 insertions, 17 deletions
diff --git a/ethlog/loggers.go b/ethlog/loggers.go index edf77bda1..d1a4c5863 100644 --- a/ethlog/loggers.go +++ b/ethlog/loggers.go @@ -1,3 +1,36 @@ +/* +Package ethlog implements a multi-output leveled logger. + +Features + +Other packages use tagged logger to send log messages to shared (process-wide) logging engine. +The shared logging engine dispatches to multiple log systems. +The log level can be set separately per log system. + +Logging is asynchrounous and does not block the main thread. Message +formatting is performed by the caller goroutine to avoid incorrect +logging of mutable state. + +Usage + +The Logger type provides named Printf and Println style methods for +all loglevels. Each ethereum component should have its own logger with +a unique prefix. + + logger.Infoln("this is info") # > [TAG] This is info + logger.Infof("this %v is info", object) # > [TAG] This object is info + +ethlog also provides constructors for that wrap io.Writers into a +standard logger with a settable level: + + filename := "test.log" + file, _ := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm) + fileLogSystem := NewStdLogSystem(file, 0, WarnLevel) + AddLogSystem(fileLogSystem) + stdOutLogSystem := NewStdLogSystem(os.Stdout, 0, WarnLevel) + AddLogSystem(stdOutLogSystem) + +*/ package ethlog import ( @@ -9,6 +42,8 @@ import ( "sync/atomic" ) +// LogSystem is implemented by log output devices. +// All methods can be called concurrently from multiple goroutines. type LogSystem interface { GetLogLevel() LogLevel SetLogLevel(i LogLevel) @@ -33,6 +68,7 @@ func newPrintfLogMessage(level LogLevel, tag string, format string, v ...interfa type LogLevel uint8 const ( + // Standard log levels Silence LogLevel = iota ErrorLevel WarnLevel @@ -102,7 +138,7 @@ func send(msg *logMessage) { logMessages <- msg } -// Reset removes all registered log systems. +// Reset removes all active log systems. func Reset() { mutex.Lock() logSystems = nil @@ -117,6 +153,15 @@ func Flush() { <-waiter } +// AddLogSystem starts printing messages to the given LogSystem. +func AddLogSystem(logSystem LogSystem) { + mutex.Lock() + logSystems = append(logSystems, logSystem) + mutex.Unlock() +} + +// A Logger prints messages prefixed by a given tag. +// You should create one with a unique tag for each high-level component. type Logger struct { tag string } @@ -125,12 +170,6 @@ func NewLogger(tag string) *Logger { return &Logger{tag} } -func AddLogSystem(logSystem LogSystem) { - mutex.Lock() - logSystems = append(logSystems, logSystem) - mutex.Unlock() -} - func (logger *Logger) sendln(level LogLevel, v ...interface{}) { if logMessages != nil { msg := newPrintlnLogMessage(level, logger.tag, v...) @@ -145,80 +184,94 @@ func (logger *Logger) sendf(level LogLevel, format string, v ...interface{}) { } } +// Errorln writes a message with ErrorLevel. func (logger *Logger) Errorln(v ...interface{}) { logger.sendln(ErrorLevel, v...) } +// Warnln writes a message with WarnLevel. func (logger *Logger) Warnln(v ...interface{}) { logger.sendln(WarnLevel, v...) } +// Infoln writes a message with InfoLevel. func (logger *Logger) Infoln(v ...interface{}) { logger.sendln(InfoLevel, v...) } +// Debugln writes a message with DebugLevel. func (logger *Logger) Debugln(v ...interface{}) { logger.sendln(DebugLevel, v...) } +// DebugDetailln writes a message with DebugDetailLevel. func (logger *Logger) DebugDetailln(v ...interface{}) { logger.sendln(DebugDetailLevel, v...) } +// Errorf writes a message with ErrorLevel. func (logger *Logger) Errorf(format string, v ...interface{}) { logger.sendf(ErrorLevel, format, v...) } +// Warnf writes a message with WarnLevel. func (logger *Logger) Warnf(format string, v ...interface{}) { logger.sendf(WarnLevel, format, v...) } +// Infof writes a message with InfoLevel. func (logger *Logger) Infof(format string, v ...interface{}) { logger.sendf(InfoLevel, format, v...) } +// Debugf writes a message with DebugLevel. func (logger *Logger) Debugf(format string, v ...interface{}) { logger.sendf(DebugLevel, format, v...) } +// DebugDetailf writes a message with DebugDetailLevel. func (logger *Logger) DebugDetailf(format string, v ...interface{}) { logger.sendf(DebugDetailLevel, format, v...) } +// Fatalln writes a message with ErrorLevel and exits the program. func (logger *Logger) Fatalln(v ...interface{}) { logger.sendln(ErrorLevel, v...) Flush() os.Exit(0) } +// Fatalf writes a message with ErrorLevel and exits the program. func (logger *Logger) Fatalf(format string, v ...interface{}) { logger.sendf(ErrorLevel, format, v...) Flush() os.Exit(0) } -type StdLogSystem struct { +// NewStdLogSystem creates a LogSystem that prints to the given writer. +// The flag values are defined package log. +func NewStdLogSystem(writer io.Writer, flags int, level LogLevel) LogSystem { + logger := log.New(writer, "", flags) + return &stdLogSystem{logger, uint32(level)} +} + +type stdLogSystem struct { logger *log.Logger level uint32 } -func (t *StdLogSystem) Println(v ...interface{}) { +func (t *stdLogSystem) Println(v ...interface{}) { t.logger.Println(v...) } -func (t *StdLogSystem) Printf(format string, v ...interface{}) { +func (t *stdLogSystem) Printf(format string, v ...interface{}) { t.logger.Printf(format, v...) } -func (t *StdLogSystem) SetLogLevel(i LogLevel) { +func (t *stdLogSystem) SetLogLevel(i LogLevel) { atomic.StoreUint32(&t.level, uint32(i)) } -func (t *StdLogSystem) GetLogLevel() LogLevel { +func (t *stdLogSystem) GetLogLevel() LogLevel { return LogLevel(atomic.LoadUint32(&t.level)) } - -func NewStdLogSystem(writer io.Writer, flags int, level LogLevel) *StdLogSystem { - logger := log.New(writer, "", flags) - return &StdLogSystem{logger, uint32(level)} -} |