From 79438f11e0d5edaea1fc93cfbb85de8035691102 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 17 Oct 2023 01:48:50 +0300 Subject: [PATCH] logger: slog break import cycle Signed-off-by: Vasiliy Tolstov --- logger/logger.go | 6 +- logger/noop.go | 71 +++++++++++++ logger/{ => slog}/slog.go | 104 +++++++++++-------- logger/{logger_test.go => slog/slog_test.go} | 30 +++--- tracer/tracer_test.go | 12 ++- 5 files changed, 156 insertions(+), 67 deletions(-) create mode 100644 logger/noop.go rename logger/{ => slog}/slog.go (75%) rename logger/{logger_test.go => slog/slog_test.go} (78%) diff --git a/logger/logger.go b/logger/logger.go index 0b8675ab..8df1523b 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -3,7 +3,6 @@ package logger import ( "context" - "os" "go.unistack.org/micro/v4/options" ) @@ -14,10 +13,7 @@ var DefaultContextAttrFuncs []ContextAttrFunc var ( // DefaultLogger variable - DefaultLogger = NewLogger( - WithLevel(ParseLevel(os.Getenv("MICRO_LOG_LEVEL"))), - WithContextAttrFuncs(DefaultContextAttrFuncs...), - ) + DefaultLogger = NewLogger() // DefaultLevel used by logger DefaultLevel = InfoLevel // DefaultCallerSkipCount used by logger diff --git a/logger/noop.go b/logger/noop.go new file mode 100644 index 00000000..e59f932f --- /dev/null +++ b/logger/noop.go @@ -0,0 +1,71 @@ +package logger + +import ( + "context" + + "go.unistack.org/micro/v4/options" +) + +type noopLogger struct { + opts Options +} + +func NewLogger(opts ...options.Option) Logger { + options := NewOptions(opts...) + return &noopLogger{opts: options} +} + +func (l *noopLogger) V(lvl Level) bool { + return false +} + +func (l *noopLogger) Level(lvl Level) { +} + +func (l *noopLogger) Init(opts ...options.Option) error { + for _, o := range opts { + o(&l.opts) + } + return nil +} + +func (l *noopLogger) Clone(opts ...options.Option) Logger { + nl := &noopLogger{opts: l.opts} + for _, o := range opts { + o(&nl.opts) + } + return nl +} + +func (l *noopLogger) Attrs(attrs ...interface{}) Logger { + return l +} + +func (l *noopLogger) Options() Options { + return l.opts +} + +func (l *noopLogger) String() string { + return "noop" +} + +func (l *noopLogger) Log(ctx context.Context, lvl Level, msg string, attrs ...interface{}) { +} + +func (l *noopLogger) Info(ctx context.Context, msg string, attrs ...interface{}) { +} + +func (l *noopLogger) Debug(ctx context.Context, msg string, attrs ...interface{}) { +} + +func (l *noopLogger) Error(ctx context.Context, msg string, attrs ...interface{}) { +} + +func (l *noopLogger) Trace(ctx context.Context, msg string, attrs ...interface{}) { +} + +func (l *noopLogger) Warn(ctx context.Context, msg string, attrs ...interface{}) { +} + +func (l *noopLogger) Fatal(ctx context.Context, msg string, attrs ...interface{}) { +} diff --git a/logger/slog.go b/logger/slog/slog.go similarity index 75% rename from logger/slog.go rename to logger/slog/slog.go index b0c87711..eca419b4 100644 --- a/logger/slog.go +++ b/logger/slog/slog.go @@ -1,4 +1,4 @@ -package logger +package slog import ( "context" @@ -8,7 +8,9 @@ import ( "strconv" "time" + "go.unistack.org/micro/v4/logger" "go.unistack.org/micro/v4/options" + "go.unistack.org/micro/v4/tracer" ) var ( @@ -35,17 +37,17 @@ func (s *slogLogger) renameAttr(_ []string, a slog.Attr) slog.Attr { lvl := slogToLoggerLevel(level) a.Key = s.opts.LevelKey switch { - case lvl < DebugLevel: + case lvl < logger.DebugLevel: a.Value = traceValue - case lvl < InfoLevel: + case lvl < logger.InfoLevel: a.Value = debugValue - case lvl < WarnLevel: + case lvl < logger.WarnLevel: a.Value = infoValue - case lvl < ErrorLevel: + case lvl < logger.ErrorLevel: a.Value = warnValue - case lvl < FatalLevel: + case lvl < logger.FatalLevel: a.Value = errorValue - case lvl >= FatalLevel: + case lvl >= logger.FatalLevel: a.Value = fatalValue default: a.Value = infoValue @@ -58,10 +60,10 @@ func (s *slogLogger) renameAttr(_ []string, a slog.Attr) slog.Attr { type slogLogger struct { slog *slog.Logger leveler *slog.LevelVar - opts Options + opts logger.Options } -func (s *slogLogger) Clone(opts ...options.Option) Logger { +func (s *slogLogger) Clone(opts ...options.Option) logger.Logger { options := s.opts for _, o := range opts { @@ -72,10 +74,12 @@ func (s *slogLogger) Clone(opts ...options.Option) Logger { opts: options, } - if slog, ok := s.opts.Context.Value(loggerKey{}).(*slog.Logger); ok { - l.slog = slog - return nil - } + /* + if slog, ok := s.opts.Context.Value(loggerKey{}).(*slog.Logger); ok { + l.slog = slog + return nil + } + */ l.leveler = new(slog.LevelVar) handleOpt := &slog.HandlerOptions{ @@ -90,19 +94,19 @@ func (s *slogLogger) Clone(opts ...options.Option) Logger { return l } -func (s *slogLogger) V(level Level) bool { +func (s *slogLogger) V(level logger.Level) bool { return s.opts.Level.Enabled(level) } -func (s *slogLogger) Level(level Level) { +func (s *slogLogger) Level(level logger.Level) { s.leveler.Set(loggerToSlogLevel(level)) } -func (s *slogLogger) Options() Options { +func (s *slogLogger) Options() logger.Options { return s.opts } -func (s *slogLogger) Attrs(attrs ...interface{}) Logger { +func (s *slogLogger) Attrs(attrs ...interface{}) logger.Logger { nl := &slogLogger{opts: s.opts} nl.leveler = new(slog.LevelVar) nl.leveler.Set(s.leveler.Level()) @@ -121,17 +125,20 @@ func (s *slogLogger) Attrs(attrs ...interface{}) Logger { func (s *slogLogger) Init(opts ...options.Option) error { if len(s.opts.ContextAttrFuncs) == 0 { - s.opts.ContextAttrFuncs = DefaultContextAttrFuncs + 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 - } + + /* + if slog, ok := s.opts.Context.Value(loggerKey{}).(*slog.Logger); ok { + s.slog = slog + return nil + } + */ s.leveler = new(slog.LevelVar) handleOpt := &slog.HandlerOptions{ @@ -146,7 +153,7 @@ func (s *slogLogger) Init(opts ...options.Option) error { return nil } -func (s *slogLogger) Log(ctx context.Context, lvl Level, msg string, attrs ...interface{}) { +func (s *slogLogger) Log(ctx context.Context, lvl logger.Level, msg string, attrs ...interface{}) { if !s.V(lvl) { return } @@ -161,7 +168,7 @@ func (s *slogLogger) Log(ctx context.Context, lvl Level, msg string, attrs ...in } func (s *slogLogger) Info(ctx context.Context, msg string, attrs ...interface{}) { - if !s.V(InfoLevel) { + if !s.V(logger.InfoLevel) { return } var pcs [1]uintptr @@ -175,7 +182,7 @@ func (s *slogLogger) Info(ctx context.Context, msg string, attrs ...interface{}) } func (s *slogLogger) Debug(ctx context.Context, msg string, attrs ...interface{}) { - if !s.V(InfoLevel) { + if !s.V(logger.DebugLevel) { return } var pcs [1]uintptr @@ -189,7 +196,7 @@ func (s *slogLogger) Debug(ctx context.Context, msg string, attrs ...interface{} } func (s *slogLogger) Trace(ctx context.Context, msg string, attrs ...interface{}) { - if !s.V(InfoLevel) { + if !s.V(logger.TraceLevel) { return } var pcs [1]uintptr @@ -203,7 +210,7 @@ func (s *slogLogger) Trace(ctx context.Context, msg string, attrs ...interface{} } func (s *slogLogger) Error(ctx context.Context, msg string, attrs ...interface{}) { - if !s.V(InfoLevel) { + if !s.V(logger.ErrorLevel) { return } var pcs [1]uintptr @@ -213,11 +220,20 @@ func (s *slogLogger) Error(ctx context.Context, msg string, attrs ...interface{} attrs = append(attrs, fn(ctx)...) } r.Add(attrs...) + r.Attrs(func(a slog.Attr) bool { + if a.Key == "error" { + if span, ok := tracer.SpanFromContext(ctx); ok { + span.SetStatus(tracer.SpanStatusError, a.Value.String()) + return false + } + } + return true + }) _ = s.slog.Handler().Handle(ctx, r) } func (s *slogLogger) Fatal(ctx context.Context, msg string, attrs ...interface{}) { - if !s.V(InfoLevel) { + if !s.V(logger.FatalLevel) { return } var pcs [1]uintptr @@ -232,7 +248,7 @@ func (s *slogLogger) Fatal(ctx context.Context, msg string, attrs ...interface{} } func (s *slogLogger) Warn(ctx context.Context, msg string, attrs ...interface{}) { - if !s.V(InfoLevel) { + if !s.V(logger.WarnLevel) { return } var pcs [1]uintptr @@ -249,43 +265,43 @@ func (s *slogLogger) String() string { return "slog" } -func NewLogger(opts ...options.Option) Logger { +func NewLogger(opts ...options.Option) logger.Logger { l := &slogLogger{ - opts: NewOptions(opts...), + opts: logger.NewOptions(opts...), } return l } -func loggerToSlogLevel(level Level) slog.Level { +func loggerToSlogLevel(level logger.Level) slog.Level { switch level { - case DebugLevel: + case logger.DebugLevel: return slog.LevelDebug - case WarnLevel: + case logger.WarnLevel: return slog.LevelWarn - case ErrorLevel: + case logger.ErrorLevel: return slog.LevelError - case TraceLevel: + case logger.TraceLevel: return slog.LevelDebug - 1 - case FatalLevel: + case logger.FatalLevel: return slog.LevelError + 1 default: return slog.LevelInfo } } -func slogToLoggerLevel(level slog.Level) Level { +func slogToLoggerLevel(level slog.Level) logger.Level { switch level { case slog.LevelDebug: - return DebugLevel + return logger.DebugLevel case slog.LevelWarn: - return WarnLevel + return logger.WarnLevel case slog.LevelError: - return ErrorLevel + return logger.ErrorLevel case slog.LevelDebug - 1: - return TraceLevel + return logger.TraceLevel case slog.LevelError + 1: - return FatalLevel + return logger.FatalLevel default: - return InfoLevel + return logger.InfoLevel } } diff --git a/logger/logger_test.go b/logger/slog/slog_test.go similarity index 78% rename from logger/logger_test.go rename to logger/slog/slog_test.go index 0d4d579b..20e9d66f 100644 --- a/logger/logger_test.go +++ b/logger/slog/slog_test.go @@ -1,21 +1,23 @@ -package logger +package slog import ( "bytes" "context" "log" "testing" + + "go.unistack.org/micro/v4/logger" ) func TestContext(t *testing.T) { ctx := context.TODO() buf := bytes.NewBuffer(nil) - l := NewLogger(WithLevel(TraceLevel), WithOutput(buf)) + l := NewLogger(logger.WithLevel(logger.TraceLevel), logger.WithOutput(buf)) if err := l.Init(); err != nil { t.Fatal(err) } - nl, ok := FromContext(NewContext(ctx, l.Attrs("key", "val"))) + nl, ok := logger.FromContext(logger.NewContext(ctx, l.Attrs("key", "val"))) if !ok { t.Fatal("context without logger") } @@ -28,7 +30,7 @@ func TestContext(t *testing.T) { func TestAttrs(t *testing.T) { ctx := context.TODO() buf := bytes.NewBuffer(nil) - l := NewLogger(WithLevel(TraceLevel), WithOutput(buf)) + l := NewLogger(logger.WithLevel(logger.TraceLevel), logger.WithOutput(buf)) if err := l.Init(); err != nil { t.Fatal(err) } @@ -45,15 +47,15 @@ func TestFromContextWithFields(t *testing.T) { ctx := context.TODO() buf := bytes.NewBuffer(nil) var ok bool - l := NewLogger(WithLevel(TraceLevel), WithOutput(buf)) + l := NewLogger(logger.WithLevel(logger.TraceLevel), logger.WithOutput(buf)) if err := l.Init(); err != nil { t.Fatal(err) } nl := l.Attrs("key", "val") - ctx = NewContext(ctx, nl) + ctx = logger.NewContext(ctx, nl) - l, ok = FromContext(ctx) + l, ok = logger.FromContext(ctx) if !ok { t.Fatalf("context does not have logger") } @@ -67,11 +69,11 @@ func TestFromContextWithFields(t *testing.T) { func TestClone(t *testing.T) { ctx := context.TODO() buf := bytes.NewBuffer(nil) - l := NewLogger(WithLevel(TraceLevel), WithOutput(buf)) + l := NewLogger(logger.WithLevel(logger.TraceLevel), logger.WithOutput(buf)) if err := l.Init(); err != nil { t.Fatal(err) } - nl := l.Clone(WithLevel(ErrorLevel)) + nl := l.Clone(logger.WithLevel(logger.ErrorLevel)) if err := nl.Init(); err != nil { t.Fatal(err) } @@ -87,11 +89,11 @@ func TestClone(t *testing.T) { func TestRedirectStdLogger(t *testing.T) { buf := bytes.NewBuffer(nil) - l := NewLogger(WithLevel(ErrorLevel), WithOutput(buf)) + l := NewLogger(logger.WithLevel(logger.ErrorLevel), logger.WithOutput(buf)) if err := l.Init(); err != nil { t.Fatal(err) } - fn := RedirectStdLogger(l, ErrorLevel) + fn := logger.RedirectStdLogger(l, logger.ErrorLevel) defer fn() log.Print("test") if !(bytes.Contains(buf.Bytes(), []byte(`"level":"error"`)) && bytes.Contains(buf.Bytes(), []byte(`"msg":"test"`))) { @@ -101,11 +103,11 @@ func TestRedirectStdLogger(t *testing.T) { func TestStdLogger(t *testing.T) { buf := bytes.NewBuffer(nil) - l := NewLogger(WithLevel(TraceLevel), WithOutput(buf)) + l := NewLogger(logger.WithLevel(logger.TraceLevel), logger.WithOutput(buf)) if err := l.Init(); err != nil { t.Fatal(err) } - lg := NewStdLogger(l, ErrorLevel) + lg := logger.NewStdLogger(l, logger.ErrorLevel) lg.Print("test") if !(bytes.Contains(buf.Bytes(), []byte(`"level":"error"`)) && bytes.Contains(buf.Bytes(), []byte(`"msg":"test"`))) { t.Fatalf("logger error, buf %s", buf.Bytes()) @@ -115,7 +117,7 @@ func TestStdLogger(t *testing.T) { func TestLogger(t *testing.T) { ctx := context.TODO() buf := bytes.NewBuffer(nil) - l := NewLogger(WithLevel(TraceLevel), WithOutput(buf)) + l := NewLogger(logger.WithLevel(logger.TraceLevel), logger.WithOutput(buf)) if err := l.Init(); err != nil { t.Fatal(err) } diff --git a/tracer/tracer_test.go b/tracer/tracer_test.go index 808df112..6d66df31 100644 --- a/tracer/tracer_test.go +++ b/tracer/tracer_test.go @@ -1,4 +1,4 @@ -package tracer +package tracer_test import ( "bytes" @@ -7,16 +7,20 @@ import ( "testing" "go.unistack.org/micro/v4/logger" + "go.unistack.org/micro/v4/logger/slog" + "go.unistack.org/micro/v4/tracer" ) func TestLoggerWithTracer(t *testing.T) { ctx := context.TODO() buf := bytes.NewBuffer(nil) - if err := logger.Init(logger.WithOutput(buf)); err != nil { + logger.DefaultLogger = slog.NewLogger(logger.WithOutput(buf)) + + if err := logger.Init(); err != nil { t.Fatal(err) } - var span Span - ctx, span = DefaultTracer.Start(ctx, "test") + var span tracer.Span + ctx, span = tracer.DefaultTracer.Start(ctx, "test") logger.Info(ctx, "msg") if !strings.Contains(buf.String(), span.TraceID()) { t.Fatalf("log does not contains tracer id")