diff options
Diffstat (limited to 'logger/logger.go')
-rw-r--r-- | logger/logger.go | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/logger/logger.go b/logger/logger.go new file mode 100644 index 0000000..c47d268 --- /dev/null +++ b/logger/logger.go @@ -0,0 +1,290 @@ +// Package logger offers simple logging +package logger + +import ( + "fmt" + "log" + "os" + "runtime/debug" + "sync" +) + +type severity int + +type logger interface { + Output(calldepth int, s string) error + SetFlags(flag int) +} + +// Severity levels. +const ( + sInfo severity = iota + sWarning + sError + sFatal +) + +// Severity tags. +const ( + tagInfo = "[INFO] " + tagWarning = "[WARN] " + tagError = "[ERROR] " + tagFatal = "[FATAL] " +) + +const ( + flags = log.Lmsgprefix | log.LstdFlags | log.Lshortfile +) + +var ( + logLock sync.Mutex + defaultLogger *Logger +) + +// initialize resets defaultLogger. Which allows tests to reset environment. +func initialize() { + defaultLogger = &Logger{ + loggers: []logger{ + log.New(os.Stderr, tagInfo, flags), + log.New(os.Stderr, tagWarning, flags), + log.New(os.Stderr, tagError, flags), + log.New(os.Stderr, tagFatal, flags), + }, + level: 3, + } +} + +func init() { + initialize() +} + +// Init sets up logging and should be called before log functions, usually in +// the caller's main(). Default log functions can be called before Init(), but +// every severity will be logged. +// The first call to Init populates the default logger and returns the +// generated logger, subsequent calls to Init will only return the generated +// logger. +func Init(level int) *Logger { + + loggers := []logger{ + log.New(os.Stderr, tagInfo, flags), + log.New(os.Stderr, tagWarning, flags), + log.New(os.Stderr, tagError, flags), + log.New(os.Stderr, tagFatal, flags), + } + l := Logger{loggers: loggers, level: level, initialized: true} + + logLock.Lock() + defer logLock.Unlock() + if !defaultLogger.initialized { + defaultLogger = &l + } + + return &l +} + +// A Logger represents an active logging object. Multiple loggers can be used +// simultaneously even if they are using the same writers. +type Logger struct { + loggers []logger + level int + initialized bool +} + +func (l *Logger) output(s severity, depth int, txt string) { + if s < sFatal-severity(l.level) { + return + } + logLock.Lock() + defer logLock.Unlock() + if int(s) >= len(l.loggers) { + panic(fmt.Sprintln("unrecognized severity:", s)) + } + l.loggers[s].Output(3+depth, txt) +} + +// SetFlags sets the output flags for the logger. +func (l *Logger) SetFlags(flag int) { + for _, logger := range l.loggers { + logger.SetFlags(flag) + } +} + +// Info logs with the Info severity. +// Arguments are handled in the manner of fmt.Print. +func (l *Logger) Info(v ...interface{}) { + l.output(sInfo, 0, fmt.Sprint(v...)) +} + +// InfoDepth acts as Info but uses depth to determine which call frame to log. +// InfoDepth(0, "msg") is the same as Info("msg"). +func (l *Logger) InfoDepth(depth int, v ...interface{}) { + l.output(sInfo, depth, fmt.Sprint(v...)) +} + +// Infoln logs with the Info severity. +// Arguments are handled in the manner of fmt.Println. +func (l *Logger) Infoln(v ...interface{}) { + l.output(sInfo, 0, fmt.Sprintln(v...)) +} + +// Infof logs with the Info severity. +// Arguments are handled in the manner of fmt.Printf. +func (l *Logger) Infof(format string, v ...interface{}) { + l.output(sInfo, 0, fmt.Sprintf(format, v...)) +} + +// Warning logs with the Warning severity. +// Arguments are handled in the manner of fmt.Print. +func (l *Logger) Warning(v ...interface{}) { + l.output(sWarning, 0, fmt.Sprint(v...)) +} + +// WarningDepth acts as Warning but uses depth to determine which call frame to log. +// WarningDepth(0, "msg") is the same as Warning("msg"). +func (l *Logger) WarningDepth(depth int, v ...interface{}) { + l.output(sWarning, depth, fmt.Sprint(v...)) +} + +// Warningln logs with the Warning severity. +// Arguments are handled in the manner of fmt.Println. +func (l *Logger) Warningln(v ...interface{}) { + l.output(sWarning, 0, fmt.Sprintln(v...)) +} + +// Warningf logs with the Warning severity. +// Arguments are handled in the manner of fmt.Printf. +func (l *Logger) Warningf(format string, v ...interface{}) { + l.output(sWarning, 0, fmt.Sprintf(format, v...)) +} + +// Error logs with the ERROR severity. +// Arguments are handled in the manner of fmt.Print. +func (l *Logger) Error(v ...interface{}) { + l.output(sError, 0, fmt.Sprint(v...)) +} + +// ErrorDepth acts as Error but uses depth to determine which call frame to log. +// ErrorDepth(0, "msg") is the same as Error("msg"). +func (l *Logger) ErrorDepth(depth int, v ...interface{}) { + l.output(sError, depth, fmt.Sprint(v...)) +} + +// Errorln logs with the ERROR severity. +// Arguments are handled in the manner of fmt.Println. +func (l *Logger) Errorln(v ...interface{}) { + l.output(sError, 0, fmt.Sprintln(v...)) +} + +// Errorf logs with the Error severity. +// Arguments are handled in the manner of fmt.Printf. +func (l *Logger) Errorf(format string, v ...interface{}) { + l.output(sError, 0, fmt.Sprintf(format, v...)) +} + +// Fatal logs with the Fatal severity, and ends with os.Exit(1). +// Arguments are handled in the manner of fmt.Print. +func (l *Logger) Fatal(v ...interface{}) { + l.output(sFatal, 0, fmt.Sprint(v...)) + os.Exit(1) +} + +// Fatalln logs with the Fatal severity, and ends with os.Exit(1). +// Arguments are handled in the manner of fmt.Println. +func (l *Logger) Fatalln(v ...interface{}) { + l.output(sFatal, 0, fmt.Sprintln(v...)) + os.Exit(1) +} + +// Fatalf logs with the Fatal severity, and ends with os.Exit(1). +// Arguments are handled in the manner of fmt.Printf. +func (l *Logger) Fatalf(format string, v ...interface{}) { + l.output(sFatal, 0, fmt.Sprintf(format, v...)) + os.Exit(1) +} + +// SetFlags sets the output flags for the logger. +func SetFlags(flag int) { + defaultLogger.SetFlags(flag) +} + +// Info uses the default logger and logs with the Info severity. +// Arguments are handled in the manner of fmt.Print. +func Info(v ...interface{}) { + defaultLogger.output(sInfo, 0, fmt.Sprint(v...)) +} + +// Infoln uses the default logger and logs with the Info severity. +// Arguments are handled in the manner of fmt.Println. +func Infoln(v ...interface{}) { + defaultLogger.output(sInfo, 0, fmt.Sprintln(v...)) +} + +// Infof uses the default logger and logs with the Info severity. +// Arguments are handled in the manner of fmt.Printf. +func Infof(format string, v ...interface{}) { + defaultLogger.output(sInfo, 0, fmt.Sprintf(format, v...)) +} + +// Warning uses the default logger and logs with the Warning severity. +// Arguments are handled in the manner of fmt.Print. +func Warning(v ...interface{}) { + defaultLogger.output(sWarning, 0, fmt.Sprint(v...)) +} + +// Warningln uses the default logger and logs with the Warning severity. +// Arguments are handled in the manner of fmt.Println. +func Warningln(v ...interface{}) { + defaultLogger.output(sWarning, 0, fmt.Sprintln(v...)) +} + +// Warningf uses the default logger and logs with the Warning severity. +// Arguments are handled in the manner of fmt.Printf. +func Warningf(format string, v ...interface{}) { + defaultLogger.output(sWarning, 0, fmt.Sprintf(format, v...)) +} + +// Error uses the default logger and logs with the Error severity. +// Arguments are handled in the manner of fmt.Print. +func Error(v ...interface{}) { + defaultLogger.output(sError, 0, fmt.Sprint(v...)) +} + +// Errorln uses the default logger and logs with the Error severity. +// Arguments are handled in the manner of fmt.Println. +func Errorln(v ...interface{}) { + defaultLogger.output(sError, 0, fmt.Sprintln(v...)) +} + +// Errorf uses the default logger and logs with the Error severity. +// Arguments are handled in the manner of fmt.Printf. +func Errorf(format string, v ...interface{}) { + defaultLogger.output(sError, 0, fmt.Sprintf(format, v...)) +} + +// Fatal uses the default logger, logs with the Fatal severity, +// and ends with os.Exit(1). +// Arguments are handled in the manner of fmt.Print. +func Fatal(v ...interface{}) { + defaultLogger.output(sFatal, 0, fmt.Sprint(v...)) + debug.PrintStack() + os.Exit(1) +} + +// Fatalln uses the default logger, logs with the Fatal severity, +// and ends with os.Exit(1). +// Arguments are handled in the manner of fmt.Println. +func Fatalln(v ...interface{}) { + defaultLogger.output(sFatal, 0, fmt.Sprintln(v...)) + debug.PrintStack() + os.Exit(1) +} + +// Fatalf uses the default logger, logs with the Fatal severity, +// and ends with os.Exit(1). +// Arguments are handled in the manner of fmt.Printf. +func Fatalf(format string, v ...interface{}) { + defaultLogger.output(sFatal, 0, fmt.Sprintf(format, v...)) + debug.PrintStack() + os.Exit(1) +} |