var logVerbosity int = 0
var logLevel string = "notice"
-type Logger struct {
+// interface coreLogger contains only the core functionality needed for logging, without
+// level or verbosity methods.
+//
+// This interface can be implemented by mocks for testing.
+type coreLogger interface {
+ WithLevel(Level) coreLogger
+
+ Print(...any)
+ Printf(string, ...any)
+ Println(...any)
+ Fatal(...any)
+ Fatalf(string, ...any)
+ Panic(...any)
+ Panicf(string, ...any)
+ Panicln(...any)
+}
+
+// interface Logger describes a logger with verbosity and level filtering, and prefix
+// management.
+type Logger interface {
+ coreLogger
+
+ AppendPrefix(string) Logger
+ WithPrefix(string) Logger
+ V(int) Logger
+
+ Debug(...any)
+ Debugf(string, ...any)
+ Info(...any)
+ Infof(string, ...any)
+ Notice(...any)
+ Noticef(string, ...any)
+ Warning(...any)
+ Warningf(string, ...any)
+ Warn(...any)
+ Warnf(string, ...any)
+ Error(...any)
+ Errorf(string, ...any)
+ Critical(...any)
+ Criticalf(string, ...any)
+ Alert(...any)
+ Alertf(string, ...any)
+}
+
+type internalLogger struct {
*log.Logger
level Level
prefix string
}
-var defaultLogger *Logger
+type logger struct {
+ *internalLogger
+}
+
+var defaultLogger Logger
var defaultLoggerOnce sync.Once
func init() {
flag.StringVar(&logLevel, "v", INFO.String(), "syslog log level for logs")
}
-func V(level int) *Logger {
+func V(level int) Logger {
if logVerbosity >= level {
return Default()
}
return NullLogger()
}
-func Default() *Logger {
+func Default() Logger {
defaultLoggerOnce.Do(func() {
- defaultLogger = &Logger{
- Logger: log.New(os.Stderr, "", log.LstdFlags),
+ defaultLogger = &logger{
+ internalLogger: &internalLogger{
+ Logger: log.New(os.Stderr, "", log.LstdFlags),
+ },
}
})
return defaultLogger
}
-func WithPrefix(prefix string) *Logger {
+func WithPrefix(prefix string) Logger {
return Default().WithPrefix(prefix)
}
-func NullLogger() *Logger {
- return &Logger{Logger: log.New(io.Discard, "", 0)}
+func NullLogger() Logger {
+ return &logger{
+ internalLogger: &internalLogger{
+ Logger: log.New(io.Discard, "", 0),
+ },
+ }
}
func Print(v ...any) {
Default().Panicln(v...)
}
-func (l *Logger) V(level int) *Logger {
- if logVerbosity >= level {
- return l
- }
- return NullLogger()
-}
-
-func (l *Logger) WithPrefix(prefix string) *Logger {
- return &Logger{
- Logger: l.Logger,
- prefix: prefix,
- level: l.level,
- }
-}
-
-func (l Logger) WithLevel(lv Level) *Logger {
+func (l *internalLogger) WithLevel(lv Level) coreLogger {
if lv < LevelFromString(logLevel) {
return NullLogger()
}
- return &Logger{
+ return &internalLogger{
Logger: l.Logger,
prefix: l.prefix,
level: lv,
}
}
-func (l *Logger) AppendPrefix(prefix string) *Logger {
- return &Logger{
- Logger: l.Logger,
- prefix: l.prefix + prefix,
- level: l.level,
+func (l *internalLogger) Print(v ...any) {
+ args := l.prependPrefixes(v)
+ l.Logger.Print(args...)
+}
+
+func (l *internalLogger) Printf(fmtstr string, v ...any) {
+ if l.prefix != "" {
+ fmtstr = "[" + l.prefix + "] " + fmtstr
}
+
+ l.Logger.Printf(l.level.prefix(l.Writer())+fmtstr, v...)
}
-func (l *Logger) prependPrefixes(v []any) []any {
+func (l *internalLogger) Println(v ...any) {
+ l.Print(v...)
+}
+
+func (l *internalLogger) prependPrefixes(v []any) []any {
prefix := ""
if l.prefix != "" {
prefix = "[" + l.prefix + "] "
return args
}
-func (l *Logger) Print(v ...any) {
- args := l.prependPrefixes(v)
- l.Logger.Print(args...)
+func (l *internalLogger) Fatal(v ...any) {
+ if len(v) > 0 {
+ if arg1, ok := v[0].(string); ok {
+ if l.prefix != "" {
+ v[0] = FATAL.prefix(l.Writer()) + "[" + l.prefix + "] " + arg1
+ }
+ }
+ }
+
+ l.Logger.Fatal(v...)
}
-func (l *Logger) Printf(fmtstr string, v ...any) {
+func (l *internalLogger) Fatalf(fmtstr string, v ...any) {
if l.prefix != "" {
- fmtstr = "[" + l.prefix + "] " + fmtstr
+ fmtstr = FATAL.prefix(l.Writer()) + "[" + l.prefix + "] " + fmtstr
}
- l.Logger.Printf(l.level.prefix(l.Writer())+fmtstr, v...)
+ l.Logger.Fatalf(fmtstr, v...)
}
-func (l *Logger) Println(v ...any) {
- l.Print(v...)
+func (l *logger) V(level int) Logger {
+ if logVerbosity >= level {
+ return l
+ }
+ return NullLogger()
+}
+
+func (l *logger) WithPrefix(prefix string) Logger {
+ return &logger{
+ internalLogger: &internalLogger{
+ Logger: l.Logger,
+ prefix: l.internalLogger.prefix,
+ level: l.level,
+ },
+ }
}
-func (l *Logger) Debug(v ...any) {
+func (l *logger) AppendPrefix(prefix string) Logger {
+ return &logger{
+ internalLogger: &internalLogger{
+ Logger: l.Logger,
+ prefix: l.internalLogger.prefix + prefix,
+ level: l.level,
+ },
+ }
+}
+
+func (l *logger) Debug(v ...any) {
l.WithLevel(DEBUG).Print(v...)
}
-func (l *Logger) Debugf(fmtstr string, v ...any) {
+func (l *logger) Debugf(fmtstr string, v ...any) {
l.WithLevel(DEBUG).Printf(fmtstr, v...)
}
-func (l *Logger) Info(v ...any) {
+func (l *logger) Info(v ...any) {
l.WithLevel(INFO).Print(v...)
}
-func (l *Logger) Infof(fmtstr string, v ...any) {
+func (l *logger) Infof(fmtstr string, v ...any) {
l.WithLevel(INFO).Printf(fmtstr, v...)
}
-func (l *Logger) Notice(v ...any) {
+func (l *logger) Notice(v ...any) {
l.WithLevel(NOTICE).Print(v...)
}
-func (l *Logger) Noticef(fmtstr string, v ...any) {
+func (l *logger) Noticef(fmtstr string, v ...any) {
l.WithLevel(NOTICE).Printf(fmtstr, v...)
}
-func (l *Logger) Warning(v ...any) {
+func (l *logger) Warning(v ...any) {
l.WithLevel(WARNING).Print(v...)
}
-func (l *Logger) Warningf(fmtstr string, v ...any) {
+func (l *logger) Warningf(fmtstr string, v ...any) {
l.WithLevel(WARNING).Printf(fmtstr, v...)
}
-func (l *Logger) Warn(v ...any) {
+func (l *logger) Warn(v ...any) {
l.WithLevel(WARNING).Print(v...)
}
-func (l *Logger) Warnf(fmtstr string, v ...any) {
+func (l *logger) Warnf(fmtstr string, v ...any) {
l.WithLevel(WARNING).Printf(fmtstr, v...)
}
-func (l *Logger) Error(v ...any) {
+func (l *logger) Error(v ...any) {
l.WithLevel(ERROR).Print(v...)
}
-func (l *Logger) Errorf(fmtstr string, v ...any) {
+func (l *logger) Errorf(fmtstr string, v ...any) {
l.WithLevel(ERROR).Printf(fmtstr, v...)
}
-func (l *Logger) Critical(v ...any) {
+func (l *logger) Critical(v ...any) {
l.WithLevel(CRITICAL).Print(v...)
}
-func (l *Logger) Criticalf(fmtstr string, v ...any) {
+func (l *logger) Criticalf(fmtstr string, v ...any) {
l.WithLevel(CRITICAL).Printf(fmtstr, v...)
}
-func (l *Logger) Alert(v ...any) {
+func (l *logger) Alert(v ...any) {
l.WithLevel(ALERT).Print(v...)
}
-func (l *Logger) Alertf(fmtstr string, v ...any) {
+func (l *logger) Alertf(fmtstr string, v ...any) {
l.WithLevel(ALERT).Printf(fmtstr, v...)
}
-
-func (l *Logger) Fatal(v ...any) {
- if len(v) > 0 {
- if arg1, ok := v[0].(string); ok {
- if l.prefix != "" {
- v[0] = FATAL.prefix(l.Writer()) + "[" + l.prefix + "] " + arg1
- }
- }
- }
-
- l.Logger.Fatal(v...)
-}
-
-func (l *Logger) Fatalf(fmtstr string, v ...any) {
- if l.prefix != "" {
- fmtstr = FATAL.prefix(l.Writer()) + "[" + l.prefix + "] " + fmtstr
- }
-
- l.Logger.Fatalf(fmtstr, v...)
-}