diff --git a/logger/logger.go b/logger/logger.go index 20a5d01f..325628ac 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -15,7 +15,7 @@ var ( // DefaultLevel used by logger DefaultLevel = InfoLevel // DefaultCallerSkipCount used by logger - DefaultCallerSkipCount = 2 + DefaultCallerSkipCount = 3 ) // Logger is a generic logging interface diff --git a/logger/slog/slog.go b/logger/slog/slog.go index 57d5d7c0..a723deb9 100644 --- a/logger/slog/slog.go +++ b/logger/slog/slog.go @@ -154,6 +154,241 @@ func (s *slogLogger) Init(opts ...logger.Option) error { } func (s *slogLogger) Log(ctx context.Context, lvl logger.Level, attrs ...interface{}) { + s.printLog(ctx, lvl, attrs...) +} + +// Logf DEPRECATED +func (s *slogLogger) Logf(ctx context.Context, lvl logger.Level, msg string, attrs ...interface{}) { + s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", lvl.String()).Inc() + if !s.V(lvl) || len(attrs) == 0 { + return + } + var pcs [1]uintptr + runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] + r := slog.NewRecord(s.opts.TimeFunc(), loggerToSlogLevel(lvl), msg, pcs[0]) + for _, fn := range s.opts.ContextAttrFuncs { + attrs = append(attrs, fn(ctx)...) + } + + for idx, attr := range attrs { + if ve, ok := attr.(error); ok && ve != nil { + attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) + break + } + } + if s.opts.AddStacktrace && lvl == logger.ErrorLevel { + stackInfo := make([]byte, 1024*1024) + if stackSize := runtime.Stack(stackInfo, false); stackSize > 0 { + traceLines := reTrace.Split(string(stackInfo[:stackSize]), -1) + if len(traceLines) != 0 { + attrs = append(attrs, (slog.String(s.opts.StacktraceKey, traceLines[len(traceLines)-1]))) + } + } + } + r.Add(attrs[1:]...) + r.Attrs(func(a slog.Attr) bool { + if a.Key == s.opts.ErrorKey { + if span, ok := tracer.SpanFromContext(ctx); ok { + span.SetStatus(tracer.SpanStatusError, a.Value.String()) + return false + } + } + return true + }) + _ = s.handler.Handle(ctx, r) +} + +func (s *slogLogger) Info(ctx context.Context, attrs ...interface{}) { + s.printLog(ctx, logger.InfoLevel, attrs...) +} + +// Infof DEPRECATED +func (s *slogLogger) Infof(ctx context.Context, msg string, attrs ...interface{}) { + s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", logger.InfoLevel.String()).Inc() + if !s.V(logger.InfoLevel) || len(attrs) == 0 { + return + } + var pcs [1]uintptr + runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] + r := slog.NewRecord(s.opts.TimeFunc(), slog.LevelInfo, msg, pcs[0]) + for _, fn := range s.opts.ContextAttrFuncs { + attrs = append(attrs, fn(ctx)...) + } + + for idx, attr := range attrs { + if ve, ok := attr.(error); ok && ve != nil { + attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) + break + } + } + r.Add(attrs...) + _ = s.handler.Handle(ctx, r) +} + +func (s *slogLogger) Debug(ctx context.Context, attrs ...interface{}) { + s.printLog(ctx, logger.DebugLevel, attrs...) +} + +// Debugf DEPRECATED +func (s *slogLogger) Debugf(ctx context.Context, msg string, attrs ...interface{}) { + s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", logger.DebugLevel.String()).Inc() + if !s.V(logger.DebugLevel) || len(attrs) == 0 { + return + } + var pcs [1]uintptr + runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] + r := slog.NewRecord(s.opts.TimeFunc(), slog.LevelDebug, msg, pcs[0]) + for _, fn := range s.opts.ContextAttrFuncs { + attrs = append(attrs, fn(ctx)...) + } + + for idx, attr := range attrs { + if ve, ok := attr.(error); ok && ve != nil { + attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) + break + } + } + r.Add(attrs...) + _ = s.handler.Handle(ctx, r) +} + +func (s *slogLogger) Trace(ctx context.Context, attrs ...interface{}) { + s.printLog(ctx, logger.TraceLevel, attrs...) +} + +// Tracef DEPRECATED +func (s *slogLogger) Tracef(ctx context.Context, msg string, attrs ...interface{}) { + s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", logger.TraceLevel.String()).Inc() + if !s.V(logger.TraceLevel) || len(attrs) == 0 { + return + } + var pcs [1]uintptr + runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] + r := slog.NewRecord(s.opts.TimeFunc(), slog.LevelDebug-1, msg, pcs[0]) + for _, fn := range s.opts.ContextAttrFuncs { + attrs = append(attrs, fn(ctx)...) + } + + for idx, attr := range attrs { + if ve, ok := attr.(error); ok && ve != nil { + attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) + break + } + } + r.Add(attrs[1:]...) + _ = s.handler.Handle(ctx, r) +} + +func (s *slogLogger) Error(ctx context.Context, attrs ...interface{}) { + s.printLog(ctx, logger.ErrorLevel, attrs...) +} + +// Errorf DEPRECATED +func (s *slogLogger) Errorf(ctx context.Context, msg string, attrs ...interface{}) { + s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", logger.ErrorLevel.String()).Inc() + if !s.V(logger.ErrorLevel) || len(attrs) == 0 { + return + } + var pcs [1]uintptr + runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] + r := slog.NewRecord(s.opts.TimeFunc(), slog.LevelError, msg, pcs[0]) + for _, fn := range s.opts.ContextAttrFuncs { + attrs = append(attrs, fn(ctx)...) + } + + for idx, attr := range attrs { + if ve, ok := attr.(error); ok && ve != nil { + attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) + break + } + } + if s.opts.AddStacktrace { + stackInfo := make([]byte, 1024*1024) + if stackSize := runtime.Stack(stackInfo, false); stackSize > 0 { + traceLines := reTrace.Split(string(stackInfo[:stackSize]), -1) + if len(traceLines) != 0 { + attrs = append(attrs, slog.String("stacktrace", traceLines[len(traceLines)-1])) + } + } + } + r.Add(attrs...) + r.Attrs(func(a slog.Attr) bool { + if a.Key == s.opts.ErrorKey { + if span, ok := tracer.SpanFromContext(ctx); ok { + span.SetStatus(tracer.SpanStatusError, a.Value.String()) + return false + } + } + return true + }) + _ = s.handler.Handle(ctx, r) +} + +func (s *slogLogger) Fatal(ctx context.Context, attrs ...interface{}) { + s.printLog(ctx, logger.FatalLevel, attrs...) + os.Exit(1) +} + +// Fatalf DEPRECATED +func (s *slogLogger) Fatalf(ctx context.Context, msg string, attrs ...interface{}) { + s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", logger.FatalLevel.String()).Inc() + if !s.V(logger.FatalLevel) || len(attrs) == 0 { + return + } + var pcs [1]uintptr + runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] + r := slog.NewRecord(s.opts.TimeFunc(), slog.LevelError+1, msg, pcs[0]) + for _, fn := range s.opts.ContextAttrFuncs { + attrs = append(attrs, fn(ctx)...) + } + + for idx, attr := range attrs { + if ve, ok := attr.(error); ok && ve != nil { + attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) + break + } + } + r.Add(attrs...) + _ = s.handler.Handle(ctx, r) + os.Exit(1) +} + +func (s *slogLogger) Warn(ctx context.Context, attrs ...interface{}) { + s.printLog(ctx, logger.WarnLevel, attrs...) +} + +// Warnf DEPRECATED +func (s *slogLogger) Warnf(ctx context.Context, msg string, attrs ...interface{}) { + s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", logger.WarnLevel.String()).Inc() + if !s.V(logger.WarnLevel) || len(attrs) == 0 { + return + } + var pcs [1]uintptr + runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] + r := slog.NewRecord(s.opts.TimeFunc(), slog.LevelWarn, msg, pcs[0]) + for _, fn := range s.opts.ContextAttrFuncs { + attrs = append(attrs, fn(ctx)...) + } + + for idx, attr := range attrs { + if ve, ok := attr.(error); ok && ve != nil { + attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) + break + } + } + r.Add(attrs[1:]...) + _ = s.handler.Handle(ctx, r) +} + +func (s *slogLogger) Name() string { + return s.opts.Name +} + +func (s *slogLogger) String() string { + return "slog" +} + +func (s *slogLogger) printLog(ctx context.Context, lvl logger.Level, attrs ...interface{}) { s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", lvl.String()).Inc() if !s.V(lvl) || len(attrs) == 0 { return @@ -205,237 +440,6 @@ func (s *slogLogger) Log(ctx context.Context, lvl logger.Level, attrs ...interfa _ = s.handler.Handle(ctx, r) } -// Logf DEPRECATED -func (s *slogLogger) Logf(ctx context.Context, lvl logger.Level, msg string, attrs ...interface{}) { - s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", lvl.String()).Inc() - if !s.V(lvl) || len(attrs) == 0 { - return - } - var pcs [1]uintptr - runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] - r := slog.NewRecord(s.opts.TimeFunc(), loggerToSlogLevel(lvl), msg, pcs[0]) - for _, fn := range s.opts.ContextAttrFuncs { - attrs = append(attrs, fn(ctx)...) - } - - for idx, attr := range attrs { - if ve, ok := attr.(error); ok && ve != nil { - attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) - break - } - } - if s.opts.AddStacktrace && lvl == logger.ErrorLevel { - stackInfo := make([]byte, 1024*1024) - if stackSize := runtime.Stack(stackInfo, false); stackSize > 0 { - traceLines := reTrace.Split(string(stackInfo[:stackSize]), -1) - if len(traceLines) != 0 { - attrs = append(attrs, (slog.String(s.opts.StacktraceKey, traceLines[len(traceLines)-1]))) - } - } - } - r.Add(attrs[1:]...) - r.Attrs(func(a slog.Attr) bool { - if a.Key == s.opts.ErrorKey { - if span, ok := tracer.SpanFromContext(ctx); ok { - span.SetStatus(tracer.SpanStatusError, a.Value.String()) - return false - } - } - return true - }) - _ = s.handler.Handle(ctx, r) -} - -func (s *slogLogger) Info(ctx context.Context, attrs ...interface{}) { - s.Log(ctx, logger.InfoLevel, attrs...) -} - -// Infof DEPRECATED -func (s *slogLogger) Infof(ctx context.Context, msg string, attrs ...interface{}) { - s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", logger.InfoLevel.String()).Inc() - if !s.V(logger.InfoLevel) || len(attrs) == 0 { - return - } - var pcs [1]uintptr - runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] - r := slog.NewRecord(s.opts.TimeFunc(), slog.LevelInfo, msg, pcs[0]) - for _, fn := range s.opts.ContextAttrFuncs { - attrs = append(attrs, fn(ctx)...) - } - - for idx, attr := range attrs { - if ve, ok := attr.(error); ok && ve != nil { - attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) - break - } - } - r.Add(attrs...) - _ = s.handler.Handle(ctx, r) -} - -func (s *slogLogger) Debug(ctx context.Context, attrs ...interface{}) { - s.Log(ctx, logger.DebugLevel, attrs...) -} - -// Debugf DEPRECATED -func (s *slogLogger) Debugf(ctx context.Context, msg string, attrs ...interface{}) { - s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", logger.DebugLevel.String()).Inc() - if !s.V(logger.DebugLevel) || len(attrs) == 0 { - return - } - var pcs [1]uintptr - runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] - r := slog.NewRecord(s.opts.TimeFunc(), slog.LevelDebug, msg, pcs[0]) - for _, fn := range s.opts.ContextAttrFuncs { - attrs = append(attrs, fn(ctx)...) - } - - for idx, attr := range attrs { - if ve, ok := attr.(error); ok && ve != nil { - attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) - break - } - } - r.Add(attrs...) - _ = s.handler.Handle(ctx, r) -} - -func (s *slogLogger) Trace(ctx context.Context, attrs ...interface{}) { - s.Log(ctx, logger.TraceLevel, attrs...) -} - -// Tracef DEPRECATED -func (s *slogLogger) Tracef(ctx context.Context, msg string, attrs ...interface{}) { - s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", logger.TraceLevel.String()).Inc() - if !s.V(logger.TraceLevel) || len(attrs) == 0 { - return - } - var pcs [1]uintptr - runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] - r := slog.NewRecord(s.opts.TimeFunc(), slog.LevelDebug-1, msg, pcs[0]) - for _, fn := range s.opts.ContextAttrFuncs { - attrs = append(attrs, fn(ctx)...) - } - - for idx, attr := range attrs { - if ve, ok := attr.(error); ok && ve != nil { - attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) - break - } - } - r.Add(attrs[1:]...) - _ = s.handler.Handle(ctx, r) -} - -func (s *slogLogger) Error(ctx context.Context, attrs ...interface{}) { - s.Log(ctx, logger.ErrorLevel, attrs...) -} - -// Errorf DEPRECATED -func (s *slogLogger) Errorf(ctx context.Context, msg string, attrs ...interface{}) { - s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", logger.ErrorLevel.String()).Inc() - if !s.V(logger.ErrorLevel) || len(attrs) == 0 { - return - } - var pcs [1]uintptr - runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] - r := slog.NewRecord(s.opts.TimeFunc(), slog.LevelError, msg, pcs[0]) - for _, fn := range s.opts.ContextAttrFuncs { - attrs = append(attrs, fn(ctx)...) - } - - for idx, attr := range attrs { - if ve, ok := attr.(error); ok && ve != nil { - attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) - break - } - } - if s.opts.AddStacktrace { - stackInfo := make([]byte, 1024*1024) - if stackSize := runtime.Stack(stackInfo, false); stackSize > 0 { - traceLines := reTrace.Split(string(stackInfo[:stackSize]), -1) - if len(traceLines) != 0 { - attrs = append(attrs, slog.String("stacktrace", traceLines[len(traceLines)-1])) - } - } - } - r.Add(attrs...) - r.Attrs(func(a slog.Attr) bool { - if a.Key == s.opts.ErrorKey { - if span, ok := tracer.SpanFromContext(ctx); ok { - span.SetStatus(tracer.SpanStatusError, a.Value.String()) - return false - } - } - return true - }) - _ = s.handler.Handle(ctx, r) -} - -func (s *slogLogger) Fatal(ctx context.Context, attrs ...interface{}) { - s.Log(ctx, logger.FatalLevel, attrs...) - os.Exit(1) -} - -// Fatalf DEPRECATED -func (s *slogLogger) Fatalf(ctx context.Context, msg string, attrs ...interface{}) { - s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", logger.FatalLevel.String()).Inc() - if !s.V(logger.FatalLevel) || len(attrs) == 0 { - return - } - var pcs [1]uintptr - runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] - r := slog.NewRecord(s.opts.TimeFunc(), slog.LevelError+1, msg, pcs[0]) - for _, fn := range s.opts.ContextAttrFuncs { - attrs = append(attrs, fn(ctx)...) - } - - for idx, attr := range attrs { - if ve, ok := attr.(error); ok && ve != nil { - attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) - break - } - } - r.Add(attrs...) - _ = s.handler.Handle(ctx, r) - os.Exit(1) -} - -func (s *slogLogger) Warn(ctx context.Context, attrs ...interface{}) { - s.Log(ctx, logger.WarnLevel, attrs...) -} - -// Warnf DEPRECATED -func (s *slogLogger) Warnf(ctx context.Context, msg string, attrs ...interface{}) { - s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", logger.WarnLevel.String()).Inc() - if !s.V(logger.WarnLevel) || len(attrs) == 0 { - return - } - var pcs [1]uintptr - runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof] - r := slog.NewRecord(s.opts.TimeFunc(), slog.LevelWarn, msg, pcs[0]) - for _, fn := range s.opts.ContextAttrFuncs { - attrs = append(attrs, fn(ctx)...) - } - - for idx, attr := range attrs { - if ve, ok := attr.(error); ok && ve != nil { - attrs[idx] = slog.String(s.opts.ErrorKey, ve.Error()) - break - } - } - r.Add(attrs[1:]...) - _ = s.handler.Handle(ctx, r) -} - -func (s *slogLogger) Name() string { - return s.opts.Name -} - -func (s *slogLogger) String() string { - return "slog" -} - func NewLogger(opts ...logger.Option) logger.Logger { s := &slogLogger{ opts: logger.NewOptions(opts...),