fix(logger): invalid source call stack

Co-authored-by: Gaze <gazenw@users.noreply.github.com>
This commit is contained in:
Gaze
2024-04-10 03:30:09 +07:00
parent 721453a62d
commit 671c8efee7
2 changed files with 106 additions and 39 deletions

39
pkg/logger/context.go Normal file
View File

@@ -0,0 +1,39 @@
package logger
import (
"context"
"log/slog"
"os"
)
// DebugContext logs at [LevelDebug] with the given context.
func DebugContext(ctx context.Context, msg string, args ...any) {
log(ctx, logger, slog.LevelDebug, msg, args...)
}
// InfoContext logs at [LevelInfo] with the given context.
func InfoContext(ctx context.Context, msg string, args ...any) {
log(ctx, logger, slog.LevelInfo, msg, args...)
}
// WarnContext logs at [LevelWarn] with the given context.
func WarnContext(ctx context.Context, msg string, args ...any) {
log(ctx, logger, slog.LevelWarn, msg, args...)
}
// ErrorContext logs at [LevelError] with an error and the given context.
func ErrorContext(ctx context.Context, msg string, err error, args ...any) {
log(ctx, logger, slog.LevelError, msg, append(args, AttrError(err))...)
}
// PanicContext logs at [LevelPanic] and then panics with the given context.
func PanicContext(ctx context.Context, msg string, args ...any) {
log(ctx, logger, LevelPanic, msg, args...)
panic(msg)
}
// FatalContext logs at [LevelFatal] and then [os.Exit](1) with the given context.
func FatalContext(ctx context.Context, msg string, args ...any) {
log(ctx, logger, LevelFatal, msg, args...)
os.Exit(1)
}

View File

@@ -5,7 +5,9 @@ import (
"context"
"log/slog"
"os"
"runtime"
"strings"
"time"
)
const (
@@ -49,71 +51,53 @@ func SetLevel(level slog.Level) (old slog.Level) {
return old
}
// Debug calls [Logger.Debug] on the default logger.
// With returns a new logger with given attributes.
func With(args ...any) *slog.Logger {
return logger.With(args...)
}
// Debug calls [Logger.Debug] on the default logger.
// Debug logs at [LevelDebug].
func Debug(msg string, args ...any) {
logger.Debug(msg, args...)
log(context.Background(), logger, slog.LevelDebug, msg, args...)
}
// DebugContext calls [Logger.DebugContext] on the default logger.
func DebugContext(ctx context.Context, msg string, args ...any) {
logger.DebugContext(ctx, msg, args...)
}
// Info calls [Logger.Info] on the default logger.
// Info logs at [LevelInfo].
func Info(msg string, args ...any) {
logger.Info(msg, args...)
log(context.Background(), logger, slog.LevelInfo, msg, args...)
}
// InfoContext calls [Logger.InfoContext] on the default logger.
func InfoContext(ctx context.Context, msg string, args ...any) {
logger.InfoContext(ctx, msg, args...)
}
// Warn calls [Logger.Warn] on the default logger.
// Warn logs at [LevelWarn].
func Warn(msg string, args ...any) {
logger.Warn(msg, args...)
log(context.Background(), logger, slog.LevelWarn, msg, args...)
}
// WarnContext calls [Logger.WarnContext] on the default logger.
func WarnContext(ctx context.Context, msg string, args ...any) {
logger.WarnContext(ctx, msg, args...)
}
// Error calls [Logger.Error] on the default logger.
// Error logs at [LevelError] with an error.
func Error(msg string, err error, args ...any) {
logger.Error(msg, append(args, AttrError(err))...)
log(context.Background(), logger, slog.LevelError, msg, append(args, AttrError(err))...)
}
// ErrorContext calls [Logger.ErrorContext] on the default logger.
func ErrorContext(ctx context.Context, msg string, err error, args ...any) {
logger.ErrorContext(ctx, msg, append(args, AttrError(err))...)
}
// Panic calls [Logger.Log] with PANIC level on the default logger and then panic.
// Panic logs at [LevelPanic] and then panics.
func Panic(msg string, args ...any) {
logger.Log(context.Background(), LevelPanic, msg, args...)
log(context.Background(), logger, LevelPanic, msg, args...)
panic(msg)
}
// PanicContext calls [Logger.Log] with PANIC level on the default logger and then panic.
func PanicContext(ctx context.Context, msg string, args ...any) {
logger.Log(ctx, LevelPanic, msg, args...)
panic(msg)
// Fatal logs at [LevelFatal] followed by a call to [os.Exit](1).
func Fatal(msg string, args ...any) {
log(context.Background(), logger, LevelFatal, msg, args...)
os.Exit(1)
}
// Log calls [Logger.Log] on the default logger.
// Log emits a log record with the current time and the given level and message.
// The Record's Attrs consist of the Logger's attributes followed by
// the Attrs specified by args.
func Log(level slog.Level, msg string, args ...any) {
logger.Log(context.Background(), level, msg, args...)
log(context.Background(), logger, level, msg, args...)
}
// LogAttrs calls [Logger.LogAttrs] on the default logger.
// LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs.
func LogAttrs(ctx context.Context, level slog.Level, msg string, attrs ...slog.Attr) {
logger.LogAttrs(ctx, level, msg, attrs...)
logAttrs(ctx, logger, level, msg, attrs...)
}
// Config is the logger configuration.
@@ -184,3 +168,47 @@ func attrReplacerChain(replacers ...func([]string, slog.Attr) slog.Attr) func([]
return attr
}
}
// log is the low-level logging method for methods that take ...any.
// It must always be called directly by an exported logging method
// or function, because it uses a fixed call depth to obtain the pc.
func log(ctx context.Context, l *slog.Logger, level slog.Level, msg string, args ...any) {
if ctx == nil {
ctx = context.Background()
}
if !l.Enabled(ctx, level) {
return
}
var pc uintptr
var pcs [1]uintptr
// skip [runtime.Callers, this function, this function's caller]
runtime.Callers(3, pcs[:])
pc = pcs[0]
r := slog.NewRecord(time.Now(), level, msg, pc)
r.Add(args...)
_ = l.Handler().Handle(ctx, r)
}
// logAttrs is like [Logger.log], but for methods that take ...Attr.
func logAttrs(ctx context.Context, l *slog.Logger, level slog.Level, msg string, attrs ...slog.Attr) {
if ctx == nil {
ctx = context.Background()
}
if !l.Enabled(ctx, level) {
return
}
var pc uintptr
var pcs [1]uintptr
// skip [runtime.Callers, this function, this function's caller]
runtime.Callers(3, pcs[:])
pc = pcs[0]
r := slog.NewRecord(time.Now(), level, msg, pc)
r.AddAttrs(attrs...)
_ = l.Handler().Handle(ctx, r)
}