diff --git a/logger/options.go b/logger/options.go index 2458af8d..43ae1ded 100644 --- a/logger/options.go +++ b/logger/options.go @@ -39,8 +39,10 @@ type Options struct { SourceKey string // StacktraceKey is the key used for the stacktrace StacktraceKey string - // Stacktrace controls writing of stacktaces on error - Stacktrace bool + // AddStacktrace controls writing of stacktaces on error + AddStacktrace bool + // AddSource enabled writing source file and position in log + AddSource bool } // NewOptions creates new options struct @@ -52,6 +54,7 @@ func NewOptions(opts ...options.Option) Options { CallerSkipCount: DefaultCallerSkipCount, Context: context.Background(), ContextAttrFuncs: DefaultContextAttrFuncs, + AddSource: true, } _ = WithMicroKeys()(&options) @@ -207,9 +210,16 @@ func WithMicroKeys() options.Option { } } -// WithStacktrace controls writing stacktrace on error -func WithStacktrace(v bool) options.Option { +// WithAddStacktrace controls writing stacktrace on error +func WithAddStacktrace(v bool) options.Option { return func(src interface{}) error { - return options.Set(src, v, ".Stacktrace") + return options.Set(src, v, ".AddStacktrace") + } +} + +// WitAddSource controls writing source file and pos in log +func WithAddSource(v bool) options.Option { + return func(src interface{}) error { + return options.Set(src, v, ".AddSource") } } diff --git a/logger/slog/slog.go b/logger/slog/slog.go index 34eae039..948470ed 100644 --- a/logger/slog/slog.go +++ b/logger/slog/slog.go @@ -80,18 +80,11 @@ func (s *slogLogger) Clone(opts ...options.Option) logger.Logger { opts: options, } - /* - if slog, ok := s.opts.Context.Value(loggerKey{}).(*slog.Logger); ok { - l.slog = slog - return nil - } - */ - l.leveler = new(slog.LevelVar) handleOpt := &slog.HandlerOptions{ - ReplaceAttr: s.renameAttr, + ReplaceAttr: l.renameAttr, Level: l.leveler, - AddSource: true, + AddSource: l.opts.AddSource, } l.leveler.Set(loggerToSlogLevel(l.opts.Level)) handler := slog.NewJSONHandler(options.Out, handleOpt) @@ -116,50 +109,47 @@ func (s *slogLogger) Options() logger.Options { func (s *slogLogger) Attrs(attrs ...interface{}) logger.Logger { s.mu.RLock() - nl := &slogLogger{opts: s.opts} - nl.leveler = new(slog.LevelVar) - nl.leveler.Set(s.leveler.Level()) + l := &slogLogger{opts: s.opts} + l.leveler = new(slog.LevelVar) + l.leveler.Set(s.leveler.Level()) handleOpt := &slog.HandlerOptions{ - ReplaceAttr: nl.renameAttr, - Level: nl.leveler, - AddSource: true, + ReplaceAttr: l.renameAttr, + Level: l.leveler, + AddSource: l.opts.AddSource, } handler := slog.NewJSONHandler(s.opts.Out, handleOpt) - nl.slog = slog.New(handler).With(attrs...) + l.slog = slog.New(handler).With(attrs...) s.mu.RUnlock() - return nl + return l } func (s *slogLogger) Init(opts ...options.Option) error { + s.mu.Lock() + if len(s.opts.ContextAttrFuncs) == 0 { s.opts.ContextAttrFuncs = logger.DefaultContextAttrFuncs } + for _, o := range opts { if err := o(&s.opts); err != nil { return err } } - /* - if slog, ok := s.opts.Context.Value(loggerKey{}).(*slog.Logger); ok { - s.slog = slog - return nil - } - */ - s.leveler = new(slog.LevelVar) handleOpt := &slog.HandlerOptions{ ReplaceAttr: s.renameAttr, Level: s.leveler, - AddSource: true, + AddSource: s.opts.AddSource, } s.leveler.Set(loggerToSlogLevel(s.opts.Level)) handler := slog.NewJSONHandler(s.opts.Out, handleOpt) s.slog = slog.New(handler).With(s.opts.Attrs...) + s.mu.Unlock() return nil } @@ -180,7 +170,7 @@ func (s *slogLogger) Log(ctx context.Context, lvl logger.Level, msg string, attr break } } - if s.opts.Stacktrace && lvl == logger.ErrorLevel { + 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) @@ -260,7 +250,7 @@ func (s *slogLogger) Error(ctx context.Context, msg string, attrs ...interface{} break } } - if s.opts.Stacktrace { + if s.opts.AddStacktrace { stackInfo := make([]byte, 1024*1024) if stackSize := runtime.Stack(stackInfo, false); stackSize > 0 { traceLines := reTrace.Split(string(stackInfo[:stackSize]), -1) diff --git a/logger/slog/slog_test.go b/logger/slog/slog_test.go index 38a9cdda..05462d94 100644 --- a/logger/slog/slog_test.go +++ b/logger/slog/slog_test.go @@ -13,7 +13,7 @@ import ( func TestError(t *testing.T) { ctx := context.TODO() buf := bytes.NewBuffer(nil) - l := NewLogger(logger.WithLevel(logger.ErrorLevel), logger.WithOutput(buf), logger.WithStacktrace(true)) + l := NewLogger(logger.WithLevel(logger.ErrorLevel), logger.WithOutput(buf), logger.WithAddStacktrace(true)) if err := l.Init(); err != nil { t.Fatal(err) } diff --git a/tracer/memory/memory_test.go b/tracer/memory/memory_test.go index f681d166..e00b532e 100644 --- a/tracer/memory/memory_test.go +++ b/tracer/memory/memory_test.go @@ -27,12 +27,12 @@ func TestLoggerWithTracer(t *testing.T) { logger.Error(ctx, "my test error", fmt.Errorf("error")) if !strings.Contains(buf.String(), span.TraceID()) { - t.Fatalf("log does not contains tracer id: %s", buf.Bytes()) + t.Fatalf("log does not contains trace id: %s", buf.Bytes()) } _, _ = tr.Start(ctx, "test2") for _, s := range tr.Spans() { - t.Logf("span %#+v\n", s) + _ = s } } diff --git a/tracer/tracer.go b/tracer/tracer.go index db61567a..de3f6a7e 100644 --- a/tracer/tracer.go +++ b/tracer/tracer.go @@ -13,6 +13,26 @@ import ( // DefaultTracer is the global default tracer var DefaultTracer = NewTracer() +var ( + // TraceIDKey is the key used for the trace id in the log call + TraceIDKey = "trace-id" + // SpanIDKey is the key used for the span id in the log call + SpanIDKey = "span-id" +) + +func init() { + logger.DefaultContextAttrFuncs = append(logger.DefaultContextAttrFuncs, + func(ctx context.Context) []interface{} { + if span, ok := SpanFromContext(ctx); ok { + return []interface{}{ + TraceIDKey, span.TraceID(), + SpanIDKey, span.SpanID(), + } + } + return nil + }) +} + // Tracer is an interface for distributed tracing type Tracer interface { // Name return tracer name @@ -52,16 +72,6 @@ type Span interface { SpanID() string } -func init() { - logger.DefaultContextAttrFuncs = append(logger.DefaultContextAttrFuncs, func(ctx context.Context) []interface{} { - span, ok := SpanFromContext(ctx) - if !ok || span == nil { - return nil - } - return []interface{}{"trace", span.TraceID(), "span", span.SpanID()} - }) -} - // sort labels alphabeticaly by label name type byKey []interface{} @@ -76,6 +86,7 @@ func UniqLabels(labels []interface{}) []interface{} { if len(labels)%2 == 1 { labels = labels[:len(labels)-1] } + if len(labels) > 2 { sort.Sort(byKey(labels))