add Write method to Logger interface to allow expressing all operations in the root logger in terms of Logger

This commit is contained in:
Jared Wasinger 2023-11-22 13:50:26 +08:00
parent 98166316b9
commit eb04be1635
4 changed files with 27 additions and 32 deletions

View file

@ -102,6 +102,8 @@ func (l *logger) Inner() *slog.Logger {
return l.l.Inner()
}
func (l *logger) Write(level slog.Level, msg string, ctx ...interface{}) {}
func (l *logger) Trace(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()

View file

@ -212,6 +212,8 @@ func builtinReplace(_ []string, attr slog.Attr, logfmt bool) slog.Attr {
} else {
attr.Value = slog.StringValue(v.Dec())
}
case fmt.Stringer:
attr.Value = slog.StringValue(v.String())
}
return attr
}

View file

@ -136,6 +136,9 @@ type Logger interface {
// Inner returns the underlying slog logger that is wrapped
Inner() *slog.Logger
// Write logs a message at the specified level
Write(level slog.Level, msg string, attrs ...any)
}
type logger struct {
@ -155,7 +158,7 @@ func (l *logger) Inner() *slog.Logger {
}
// write logs a message at the specified level:
func (l *logger) write(level slog.Level, msg string, attrs ...any) {
func (l *logger) Write(level slog.Level, msg string, attrs ...any) {
if !l.inner.Enabled(context.Background(), level) {
return
}
@ -192,7 +195,7 @@ func (l *logger) write(level slog.Level, msg string, attrs ...any) {
}
func (l *logger) Log(level slog.Level, msg string, attrs ...any) {
l.write(level, msg, attrs...)
l.Write(level, msg, attrs...)
}
func (l *logger) With(ctx ...interface{}) Logger {
@ -204,26 +207,26 @@ func (l *logger) New(ctx ...interface{}) Logger {
}
func (l *logger) Trace(msg string, ctx ...interface{}) {
l.write(LevelTrace, msg, ctx...)
l.Write(LevelTrace, msg, ctx...)
}
func (l *logger) Debug(msg string, ctx ...interface{}) {
l.write(slog.LevelDebug, msg, ctx...)
l.Write(slog.LevelDebug, msg, ctx...)
}
func (l *logger) Info(msg string, ctx ...interface{}) {
l.write(slog.LevelInfo, msg, ctx...)
l.Write(slog.LevelInfo, msg, ctx...)
}
func (l *logger) Warn(msg string, ctx ...any) {
l.write(slog.LevelWarn, msg, ctx...)
l.Write(slog.LevelWarn, msg, ctx...)
}
func (l *logger) Error(msg string, ctx ...interface{}) {
l.write(slog.LevelError, msg, ctx...)
l.Write(slog.LevelError, msg, ctx...)
}
func (l *logger) Crit(msg string, ctx ...interface{}) {
l.write(LevelCrit, msg, ctx...)
l.Write(LevelCrit, msg, ctx...)
os.Exit(1)
}

View file

@ -2,42 +2,30 @@ package log
import (
"os"
"sync"
"golang.org/x/exp/slog"
)
var (
rootMu sync.Mutex
root logger
)
var root Logger
func init() {
defaultLogger := &logger{slog.New(DiscardHandler())}
SetDefault(defaultLogger)
}
// SetDefault sets the default global logger
func SetDefault(l Logger) {
rootMu.Lock()
defer rootMu.Unlock()
root := l
root = l
slog.SetDefault(root.Inner())
}
// Root returns the root logger
func Root() Logger {
return rootLogger()
}
func rootLogger() *logger {
rootMu.Lock()
defer rootMu.Unlock()
res := root
return &res
return Root()
}
// The following functions bypass the exported logger methods (logger.Debug,
// etc.) to keep the call depth the same for all paths to logger.write so
// etc.) to keep the call depth the same for all paths to logger.Write so
// runtime.Caller(2) always refers to the call site in client code.
// Trace is a convenient alias for Root().Trace
@ -50,7 +38,7 @@ func rootLogger() *logger {
// log.Trace("msg", "key1", val1)
// log.Trace("msg", "key1", val1, "key2", val2)
func Trace(msg string, ctx ...interface{}) {
rootLogger().write(LevelTrace, msg, ctx...)
Root().Write(LevelTrace, msg, ctx...)
}
// Debug is a convenient alias for Root().Debug
@ -63,7 +51,7 @@ func Trace(msg string, ctx ...interface{}) {
// log.Debug("msg", "key1", val1)
// log.Debug("msg", "key1", val1, "key2", val2)
func Debug(msg string, ctx ...interface{}) {
rootLogger().write(slog.LevelDebug, msg, ctx...)
Root().Write(slog.LevelDebug, msg, ctx...)
}
// Info is a convenient alias for Root().Info
@ -76,7 +64,7 @@ func Debug(msg string, ctx ...interface{}) {
// log.Info("msg", "key1", val1)
// log.Info("msg", "key1", val1, "key2", val2)
func Info(msg string, ctx ...interface{}) {
rootLogger().write(slog.LevelInfo, msg, ctx...)
Root().Write(slog.LevelInfo, msg, ctx...)
}
// Warn is a convenient alias for Root().Warn
@ -89,7 +77,7 @@ func Info(msg string, ctx ...interface{}) {
// log.Warn("msg", "key1", val1)
// log.Warn("msg", "key1", val1, "key2", val2)
func Warn(msg string, ctx ...interface{}) {
rootLogger().write(slog.LevelWarn, msg, ctx...)
Root().Write(slog.LevelWarn, msg, ctx...)
}
// Error is a convenient alias for Root().Error
@ -102,7 +90,7 @@ func Warn(msg string, ctx ...interface{}) {
// log.Error("msg", "key1", val1)
// log.Error("msg", "key1", val1, "key2", val2)
func Error(msg string, ctx ...interface{}) {
rootLogger().write(slog.LevelError, msg, ctx...)
Root().Write(slog.LevelError, msg, ctx...)
}
// Crit is a convenient alias for Root().Crit
@ -115,12 +103,12 @@ func Error(msg string, ctx ...interface{}) {
// log.Crit("msg", "key1", val1)
// log.Crit("msg", "key1", val1, "key2", val2)
func Crit(msg string, ctx ...interface{}) {
rootLogger().write(LevelCrit, msg, ctx...)
Root().Write(LevelCrit, msg, ctx...)
os.Exit(1)
}
// New returns a new logger with the given context.
// New is a convenient alias for Root().New
func New(ctx ...interface{}) Logger {
return rootLogger().With(ctx...)
return Root().With(ctx...)
}