feat(logger): add logger context utilities

Co-authored-by: Gaze <gazenw@users.noreply.github.com>
This commit is contained in:
Gaze
2024-04-10 03:41:40 +07:00
parent 671c8efee7
commit dc60975437
2 changed files with 65 additions and 14 deletions

View File

@@ -6,34 +6,73 @@ import (
"os"
)
// DebugContext logs at [LevelDebug] with the given context.
type loggerKey struct{}
// FromContext returns the logger from the context. If no logger is found, a new
func FromContext(ctx context.Context) *slog.Logger {
if ctx == nil {
return logger.With()
}
if log, ok := ctx.Value(loggerKey{}).(*slog.Logger); ok {
return log
}
return logger.With()
}
// NewContext returns a new context with logger attached.
func NewContext(ctx context.Context, log *slog.Logger) context.Context {
if ctx == nil {
ctx = context.Background()
}
return context.WithValue(ctx, loggerKey{}, log)
}
// WithContext returns a new context with given logger attributes.
func WithContext(ctx context.Context, args ...any) context.Context {
return NewContext(ctx, FromContext(ctx).With(args...))
}
// WithGroupContext returns a new context with given group.
func WithGroupContext(ctx context.Context, group string) context.Context {
return NewContext(ctx, FromContext(ctx).WithGroup(group))
}
// DebugContext logs at [LevelDebug] from logger in the given context.
func DebugContext(ctx context.Context, msg string, args ...any) {
log(ctx, logger, slog.LevelDebug, msg, args...)
log(ctx, FromContext(ctx), slog.LevelDebug, msg, args...)
}
// InfoContext logs at [LevelInfo] with the given context.
// InfoContext logs at [LevelInfo] from logger in the given context.
func InfoContext(ctx context.Context, msg string, args ...any) {
log(ctx, logger, slog.LevelInfo, msg, args...)
log(ctx, FromContext(ctx), slog.LevelInfo, msg, args...)
}
// WarnContext logs at [LevelWarn] with the given context.
// WarnContext logs at [LevelWarn] from logger in the given context.
func WarnContext(ctx context.Context, msg string, args ...any) {
log(ctx, logger, slog.LevelWarn, msg, args...)
log(ctx, FromContext(ctx), slog.LevelWarn, msg, args...)
}
// ErrorContext logs at [LevelError] with an error and the given context.
// ErrorContext logs at [LevelError] from logger in the given context.
func ErrorContext(ctx context.Context, msg string, err error, args ...any) {
log(ctx, logger, slog.LevelError, msg, append(args, AttrError(err))...)
log(ctx, FromContext(ctx), slog.LevelError, msg, append(args, AttrError(err))...)
}
// PanicContext logs at [LevelPanic] and then panics with the given context.
// PanicContext logs at [LevelPanic] and then panics from logger in the given context.
func PanicContext(ctx context.Context, msg string, args ...any) {
log(ctx, logger, LevelPanic, msg, args...)
log(ctx, FromContext(ctx), LevelPanic, msg, args...)
panic(msg)
}
// FatalContext logs at [LevelFatal] and then [os.Exit](1) with the given context.
// FatalContext logs at [LevelFatal] and then [os.Exit](1) from logger in the given context.
func FatalContext(ctx context.Context, msg string, args ...any) {
log(ctx, logger, LevelFatal, msg, args...)
log(ctx, FromContext(ctx), LevelFatal, msg, args...)
os.Exit(1)
}
// LogContext logs at the given level from logger in the given context.
func LogContext(ctx context.Context, level slog.Level, msg string, args ...any) {
log(ctx, FromContext(ctx), level, msg, args...)
}

View File

@@ -51,11 +51,23 @@ func SetLevel(level slog.Level) (old slog.Level) {
return old
}
// With returns a new logger with given attributes.
// With returns a Logger that includes the given attributes
// in each output operation. Arguments are converted to
// attributes as if by [Logger.Log].
func With(args ...any) *slog.Logger {
return logger.With(args...)
}
// WithGroup returns a Logger that starts a group, if name is non-empty.
// The keys of all attributes added to the Logger will be qualified by the given
// name. (How that qualification happens depends on the [Handler.WithGroup]
// method of the Logger's Handler.)
//
// If name is empty, WithGroup returns the receiver.
func WithGroup(group string) *slog.Logger {
return logger.WithGroup(group)
}
// Debug logs at [LevelDebug].
func Debug(msg string, args ...any) {
log(context.Background(), logger, slog.LevelDebug, msg, args...)
@@ -97,7 +109,7 @@ func Log(level slog.Level, msg string, args ...any) {
// 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) {
logAttrs(ctx, logger, level, msg, attrs...)
logAttrs(ctx, FromContext(ctx), level, msg, attrs...)
}
// Config is the logger configuration.