package logger import ( "fmt" "log" "os" "sync" ) const ( LevelDebug Level = iota + 1 LevelInfo LevelNotice LevelFatal ) type Level int func NewLevel(str string) (Level, error) { switch str { case LevelDebug.String(): return LevelDebug, nil case LevelInfo.String(): return LevelInfo, nil case LevelNotice.String(): return LevelNotice, nil case LevelFatal.String(): return LevelFatal, nil } return Level(0), fmt.Errorf("unknown level %q", str) } func (lv Level) String() string { switch lv { case LevelDebug: return "DEBUG" case LevelInfo: return "INFO" case LevelNotice: return "NOTICE" case LevelFatal: return "FATAL" default: return "UNKNOWN" } } type Config struct { Level Level File *os.File } type Logger struct { cfg Config log log.Logger mutex sync.Mutex } func New(cfg Config) (l Logger) { l.Reconfigure(cfg) return } func (l *Logger) Reconfigure(cfg Config) { l.mutex.Lock() defer l.mutex.Unlock() if cfg.Level < LevelDebug || cfg.Level > LevelFatal { cfg.Level = LevelNotice } if cfg.File == nil { cfg.File = os.Stdout } l.cfg = cfg l.log = *log.New(l.cfg.File, "", log.Ldate|log.Ltime) } func (l *Logger) IsConfigured() bool { return l.cfg.File != nil } func (l *Logger) Debugf(format string, args ...interface{}) { l.printf(LevelDebug, format, args...) } func (l *Logger) Infof(format string, args ...interface{}) { l.printf(LevelInfo, format, args...) } func (l *Logger) Noticef(format string, args ...interface{}) { l.printf(LevelNotice, format, args...) } func (l *Logger) Fatalf(format string, args ...interface{}) { l.printf(LevelFatal, format, args...) } func (l *Logger) Dief(format string, args ...interface{}) { l.Fatalf(format, args...); os.Exit(1) } func (l *Logger) printf(lv Level, format string, args ...interface{}) { l.mutex.Lock() defer l.mutex.Unlock() if l.cfg.Level <= lv { l.log.Printf("["+lv.String()+"] "+format, args...) } }