package logger import ( "log" "os" ) type Logger struct { *log.Logger name string file string verbose bool } // DEBUG/WARNING will only be written to file // INFO/ERROR will be written to file and printed to stdout/stderr const ( DEBUG = iota INFO WARNING ERROR ) var levels = map[int]string{ DEBUG: "[DEBUG]", INFO: "[INFO]", WARNING: "[WARNING]", ERROR: "[ERROR]", } var outLogger = log.New(os.Stdout, "", log.LstdFlags) var errLogger = log.New(os.Stderr, "", log.LstdFlags) // log to stdout func OutLog(v ...interface{}) { outLogger.Println(v...) } // log to stderr func ErrLog(v ...interface{}) { errLogger.Println(v...) } // initialize a logger func NewLogger(name, file string, verbose bool) *Logger { logger := Logger{ Logger: log.New(os.Stderr, "", log.LstdFlags), name: name, file: file, verbose: verbose, } return &logger } // write something to the logger func (logger *Logger) log(level int, v ...interface{}) { f, err := os.OpenFile(logger.file, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) if err != nil { ErrLog(err.Error()) } defer f.Close() levelStr := levels[level] args := []interface{}{levelStr + ":"} args = append(args, v...) logger.SetOutput(f) logger.Println(args) } // write debug information to the logfile func (logger *Logger) Debug(v ...interface{}) { if logger.verbose { logger.log(DEBUG, v...) } } // write information to the logfile and to stdout func (logger *Logger) Info(v ...interface{}) { OutLog(append([]interface{}{"[" + logger.name + "]"}, v...)) logger.log(INFO, v...) } // write warnings to the logfile func (logger *Logger) Warning(v ...interface{}) { logger.log(WARNING, v...) } // write errors to the logfile and to stderr func (logger *Logger) Error(v ...interface{}) { ErrLog(append([]interface{}{"[" + logger.name + "]"}, v...)) logger.log(ERROR, v...) }