package main import ( "fmt" "io" "log" "os" "time" ) type logWriter struct { level string writer io.Writer } func (w logWriter) Write(bytes []byte) (int, error) { timestamp := time.Now().UTC().Format(time.RFC3339) return fmt.Fprintf(w.writer, timestamp + " ["+w.level+"]\t"+string(bytes)) } type logger struct { infoLogger *log.Logger errorLogger *log.Logger debugLogger *log.Logger } func newLogger(debug bool) *logger { infoLogWriter := logWriter{ level: "INFO", writer: os.Stdout, } infoLogger := log.New(infoLogWriter, "", 0) errorLogWriter := logWriter{ level: "ERROR", writer: os.Stderr, } errorLogger := log.New(errorLogWriter, "", 0) var baseDebugWriter io.Writer if debug { baseDebugWriter = os.Stdout } else { baseDebugWriter = io.Discard } debugLogWriter := logWriter{ level: "DEBUG", writer: baseDebugWriter, } debugLogger := log.New(debugLogWriter, "", log.Lshortfile) l := logger{ infoLogger: infoLogger, errorLogger: errorLogger, debugLogger: debugLogger, } return &l } func (l *logger) Infoln(v ...interface{}) { l.infoLogger.Println(v...) } func (l *logger) Infof(format string, v ...interface{}) { l.infoLogger.Printf(format, v...) } func (l *logger) Errorln(v ...interface{}) { l.errorLogger.Fatalln(v...) } func (l *logger) Errorf(format string, v ...interface{}) { l.errorLogger.Fatalf(format, v...) } func (l *logger) Debugln(v ...interface{}) { l.debugLogger.Println(v...) } func (l *logger) Debugf(format string, v ...interface{}) { l.debugLogger.Printf(format, v...) }