/* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. */ package logger import ( "io" "log" "os" "strings" ) type LogLevel int const ( LogLevelSilent LogLevel = iota LogLevelFatal LogLevelError LogLevelWarn LogLevelInfo LogLevelDebug ) var logLevelPrefix = []string{ "", "FATAL", "ERROR", "Warn", "Info", "debug", } const ( LogLevelDefault = LogLevelWarn FlagsDefault = log.LstdFlags | log.LUTC | log.Lmsgprefix | log.Lmicroseconds ) func NewLogger() *Logger { flags := FlagsDefault return &Logger{ logger: log.New(os.Stderr, "", flags), debug: log.New(os.Stderr, "", flags|log.Lshortfile), level: LogLevelDefault, context: make([]string, 0, 8), } } type Logger struct { logger *log.Logger debug *log.Logger level LogLevel context []string } func (l *Logger) Level() LogLevel { return l.level } func (l *Logger) SetLevel(level LogLevel) { l.level = level } func (l *Logger) Writer() io.Writer { return l.logger.Writer() } func (l *Logger) SetOutput(w io.Writer) { l.logger.SetOutput(w) l.debug.SetOutput(w) } func (l *Logger) Flags() int { return l.logger.Flags() } func (l *Logger) SetFlags(flags int) { l.logger.SetFlags(flags) l.debug.SetFlags(flags) } func (l *Logger) Push(s string) *Logger { next := *l next.context = make([]string, 0, 8) copy(next.context, l.context) next.context = append(next.context, s) return &next } func (l *Logger) logAs( level LogLevel, format string, msg []any, ) { if level > l.level { return } prefix := logLevelPrefix[level] logr := l.logger if level == LogLevelDebug { logr = l.debug } context := strings.Join(l.context, ": ") if len(context) > 0 { context += ": " } logr.Printf("["+prefix+"] "+context+format, msg...) } func (l *Logger) Fatal(format string, msg ...any) { l.logAs(LogLevelFatal, format, msg) os.Exit(1) } func (l *Logger) Error(format string, msg ...any) { l.logAs(LogLevelError, format, msg) } func (l *Logger) Warn(format string, msg ...any) { l.logAs(LogLevelWarn, format, msg) } func (l *Logger) Info(format string, msg ...any) { l.logAs(LogLevelInfo, format, msg) } func (l *Logger) Debug(format string, msg ...any) { l.logAs(LogLevelDebug, format, msg) }