| @@ -192,27 +192,34 @@ func (s *slogLogger) String() string { | |||||||
| 	return "slog" | 	return "slog" | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *slogLogger) printLog(ctx context.Context, lvl logger.Level, msg string, attrs ...interface{}) { | func (s *slogLogger) printLog(ctx context.Context, lvl logger.Level, msg string, args ...interface{}) { | ||||||
| 	if !s.V(lvl) { | 	if !s.V(lvl) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | 	var argError error | ||||||
|  |  | ||||||
| 	s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", lvl.String()).Inc() | 	s.opts.Meter.Counter(semconv.LoggerMessageTotal, "level", lvl.String()).Inc() | ||||||
|  |  | ||||||
| 	attrs = prepareAttributes(attrs) | 	attrs, err := s.argsAttrs(args) | ||||||
|  | 	if err != nil { | ||||||
| 	for _, fn := range s.opts.ContextAttrFuncs { | 		argError = err | ||||||
| 		a := prepareAttributes(fn(ctx)) | 	} | ||||||
| 		attrs = append(attrs, a...) | 	if argError != nil { | ||||||
|  | 		if span, ok := tracer.SpanFromContext(ctx); ok { | ||||||
|  | 			span.SetStatus(tracer.SpanStatusError, argError.Error()) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, attr := range attrs { | 	for _, fn := range s.opts.ContextAttrFuncs { | ||||||
| 		if ve, hasErr := attr.(error); hasErr && ve != nil { | 		ctxAttrs, err := s.argsAttrs(fn(ctx)) | ||||||
| 			attrs = append(attrs, slog.String(s.opts.ErrorKey, ve.Error())) | 		if err != nil { | ||||||
| 			if span, ok := tracer.SpanFromContext(ctx); ok { | 			argError = err | ||||||
| 				span.SetStatus(tracer.SpanStatusError, ve.Error()) | 		} | ||||||
| 			} | 		attrs = append(attrs, ctxAttrs...) | ||||||
| 			break | 	} | ||||||
|  | 	if argError != nil { | ||||||
|  | 		if span, ok := tracer.SpanFromContext(ctx); ok { | ||||||
|  | 			span.SetStatus(tracer.SpanStatusError, argError.Error()) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -229,7 +236,7 @@ func (s *slogLogger) printLog(ctx context.Context, lvl logger.Level, msg string, | |||||||
| 	var pcs [1]uintptr | 	var pcs [1]uintptr | ||||||
| 	runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, printLog, LogLvlMethod] | 	runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, printLog, LogLvlMethod] | ||||||
| 	r := slog.NewRecord(s.opts.TimeFunc(), loggerToSlogLevel(lvl), msg, pcs[0]) | 	r := slog.NewRecord(s.opts.TimeFunc(), loggerToSlogLevel(lvl), msg, pcs[0]) | ||||||
| 	r.Add(attrs...) | 	r.AddAttrs(attrs...) | ||||||
| 	_ = s.handler.Handle(ctx, r) | 	_ = s.handler.Handle(ctx, r) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -276,11 +283,26 @@ func slogToLoggerLevel(level slog.Level) logger.Level { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func prepareAttributes(attrs []interface{}) []interface{} { | func (s *slogLogger) argsAttrs(args []interface{}) ([]slog.Attr, error) { | ||||||
| 	if len(attrs)%2 == 1 { | 	attrs := make([]slog.Attr, 0, len(args)) | ||||||
| 		attrs = append(attrs, badKey) | 	var err error | ||||||
| 		attrs[len(attrs)-1], attrs[len(attrs)-2] = attrs[len(attrs)-2], attrs[len(attrs)-1] |  | ||||||
|  | 	for idx := 0; idx < len(args); idx++ { | ||||||
|  | 		switch arg := args[idx].(type) { | ||||||
|  | 		case slog.Attr: | ||||||
|  | 			attrs = append(attrs, arg) | ||||||
|  | 		case string: | ||||||
|  | 			if idx+1 < len(args) { | ||||||
|  | 				attrs = append(attrs, slog.Any(arg, args[idx+1])) | ||||||
|  | 				idx += 1 | ||||||
|  | 			} else { | ||||||
|  | 				attrs = append(attrs, slog.String(badKey, arg)) | ||||||
|  | 			} | ||||||
|  | 		case error: | ||||||
|  | 			attrs = append(attrs, slog.String(s.opts.ErrorKey, arg.Error())) | ||||||
|  | 			err = arg | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return attrs | 	return attrs, err | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,12 +5,13 @@ import ( | |||||||
| 	"context" | 	"context" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"github.com/google/uuid" |  | ||||||
| 	"go.unistack.org/micro/v3/metadata" |  | ||||||
| 	"log" | 	"log" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/google/uuid" | ||||||
|  | 	"go.unistack.org/micro/v3/metadata" | ||||||
|  |  | ||||||
| 	"go.unistack.org/micro/v3/logger" | 	"go.unistack.org/micro/v3/logger" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -43,9 +44,6 @@ func TestErrorf(t *testing.T) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	l.Log(ctx, logger.ErrorLevel, "message", errors.New("error msg")) | 	l.Log(ctx, logger.ErrorLevel, "message", errors.New("error msg")) | ||||||
| 	if !bytes.Contains(buf.Bytes(), []byte(`"!BADKEY":"`)) { |  | ||||||
| 		t.Fatalf("logger BADKEY not works, buf contains: %s", buf.Bytes()) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	l.Log(ctx, logger.ErrorLevel, "", errors.New("error msg")) | 	l.Log(ctx, logger.ErrorLevel, "", errors.New("error msg")) | ||||||
| 	if !bytes.Contains(buf.Bytes(), []byte(`"error":"error msg"`)) { | 	if !bytes.Contains(buf.Bytes(), []byte(`"error":"error msg"`)) { | ||||||
| @@ -236,5 +234,4 @@ func Test_WithContextAttrFunc(t *testing.T) { | |||||||
| 	if !(bytes.Contains(buf.Bytes(), []byte(`"source-service":"Test-System"`))) { | 	if !(bytes.Contains(buf.Bytes(), []byte(`"source-service":"Test-System"`))) { | ||||||
| 		t.Fatalf("logger info, buf %s", buf.Bytes()) | 		t.Fatalf("logger info, buf %s", buf.Bytes()) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user