package beaver import ( "fmt" "io" "os" "runtime" "strings" "time" "go.jolheiser.com/beaver/color" ) // Logger is a base Beaver logger type Logger struct { Writer io.Writer Level Level Format FormatOptions skip int } // FormatOptions defines formatting options for a logger type FormatOptions struct { TimePrefix bool StackPrefix bool StackLimit int LevelPrefix bool LevelColor bool MessageColor bool } // New returns a new Beaver logger func New(writer io.Writer, level Level, opts FormatOptions) *Logger { return &Logger{ Writer: writer, Level: level, Format: opts, skip: 3, } } func (l *Logger) write(level Level, text string) { if l.Level <= level { _, file, line, _ := runtime.Caller(l.skip) var message string if l.Format.TimePrefix { message += color.Time.Format(timePrefix(time.Now())) + " " } if l.Format.StackPrefix { idx := len(file) - l.Format.StackLimit if l.Format.StackLimit <= 0 { idx = 0 } if idx > 0 { file = fmt.Sprintf("...%s", file[idx:]) } message += color.Stack.Format(fmt.Sprintf("%s:%d", file, line)) + " " } if l.Format.LevelPrefix { if l.Format.LevelColor { message += level.Color().Format(level.Prefix()) } else { message += level.Prefix() } message += " " } if l.Format.MessageColor { message += level.Color().Format(text) } else { message += text } message += "\n" _, _ = l.Writer.Write([]byte(message)) } } func (l *Logger) log(level Level, v ...interface{}) { var args = make([]string, len(v)) for i := 0; i < len(v); i++ { args[i] = fmt.Sprintf("%v", v[i]) } text := strings.Join(args, " ") l.write(level, text) } func (l *Logger) logf(level Level, format string, v ...interface{}) { text := fmt.Sprintf(format, v...) l.write(level, text) } // Low-Level Log func (l *Logger) Log(level Level, v ...interface{}) { l.log(level, v...) } // Low-Level formatted Log func (l *Logger) Logf(level Level, format string, v ...interface{}) { l.logf(level, format, v...) } // Trace logs at TRACE Level func (l *Logger) Trace(v ...interface{}) { l.log(TRACE, v...) } // Tracef formats logs at TRACE Level func (l *Logger) Tracef(format string, v ...interface{}) { l.logf(TRACE, format, v...) } // Debug logs at DEBUG Level func (l *Logger) Debug(v ...interface{}) { l.log(DEBUG, v...) } // Debugf formats logs at DEBUG Level func (l *Logger) Debugf(format string, v ...interface{}) { l.logf(DEBUG, format, v...) } // Info logs at INFO Level func (l *Logger) Info(v ...interface{}) { l.log(INFO, v...) } // Infof formats logs at INFO Level func (l *Logger) Infof(format string, v ...interface{}) { l.logf(INFO, format, v...) } // Warn logs at WARN Level func (l *Logger) Warn(v ...interface{}) { l.log(WARN, v...) } // Warnf formats logs at WARN Level func (l *Logger) Warnf(format string, v ...interface{}) { l.logf(WARN, format, v...) } // Error logs at ERROR Level func (l *Logger) Error(v ...interface{}) { l.log(ERROR, v...) } // Errorf formats logs at ERROR Level func (l *Logger) Errorf(format string, v ...interface{}) { l.logf(ERROR, format, v...) } // Fatal logs at FATAL Level func (l *Logger) Fatal(v ...interface{}) { l.log(FATAL, v...) os.Exit(1) } // Fatalf formats logs at FATAL Level func (l *Logger) Fatalf(format string, v ...interface{}) { l.logf(FATAL, format, v...) os.Exit(1) }