logger: improvements #270
@@ -1,5 +1,5 @@
 | 
				
			|||||||
// Package logger provides a log interface
 | 
					// Package logger provides a log interface
 | 
				
			||||||
package logger // import "go.unistack.org/micro/v4/logger"
 | 
					package logger
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
@@ -8,19 +8,22 @@ import (
 | 
				
			|||||||
	"go.unistack.org/micro/v4/options"
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ContextAttrFunc func(ctx context.Context) []interface{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var DefaultContextAttrFuncs []ContextAttrFunc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	// DefaultLogger variable
 | 
						// DefaultLogger variable
 | 
				
			||||||
	DefaultLogger = NewLogger(WithLevel(ParseLevel(os.Getenv("MICRO_LOG_LEVEL"))))
 | 
						DefaultLogger = NewLogger(
 | 
				
			||||||
 | 
							WithLevel(ParseLevel(os.Getenv("MICRO_LOG_LEVEL"))),
 | 
				
			||||||
 | 
							WithContextAttrFuncs(DefaultContextAttrFuncs...),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
	// DefaultLevel used by logger
 | 
						// DefaultLevel used by logger
 | 
				
			||||||
	DefaultLevel = InfoLevel
 | 
						DefaultLevel = InfoLevel
 | 
				
			||||||
	// DefaultCallerSkipCount used by logger
 | 
						// DefaultCallerSkipCount used by logger
 | 
				
			||||||
	DefaultCallerSkipCount = 2
 | 
						DefaultCallerSkipCount = 2
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ContextAttrFunc func(ctx context.Context) []interface{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var DefaultContextAttrFuncs []ContextAttrFunc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Logger is a generic logging interface
 | 
					// Logger is a generic logging interface
 | 
				
			||||||
type Logger interface {
 | 
					type Logger interface {
 | 
				
			||||||
	// Init initialises options
 | 
						// Init initialises options
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,12 +2,14 @@ package logger
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v4/options"
 | 
						"go.unistack.org/micro/v4/options"
 | 
				
			||||||
	rutil "go.unistack.org/micro/v4/util/reflect"
 | 
						rutil "go.unistack.org/micro/v4/util/reflect"
 | 
				
			||||||
 | 
						"golang.org/x/exp/slog"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Options holds logger options
 | 
					// Options holds logger options
 | 
				
			||||||
@@ -26,6 +28,14 @@ type Options struct {
 | 
				
			|||||||
	CallerSkipCount int
 | 
						CallerSkipCount int
 | 
				
			||||||
	// ContextAttrFuncs contains funcs that executed before log func on context
 | 
						// ContextAttrFuncs contains funcs that executed before log func on context
 | 
				
			||||||
	ContextAttrFuncs []ContextAttrFunc
 | 
						ContextAttrFuncs []ContextAttrFunc
 | 
				
			||||||
 | 
						// TimeKey is the key used for the time of the log call
 | 
				
			||||||
 | 
						TimeKey string
 | 
				
			||||||
 | 
						// LevelKey is the key used for the level of the log call
 | 
				
			||||||
 | 
						LevelKey string
 | 
				
			||||||
 | 
						// MessageKey is the key used for the message of the log call
 | 
				
			||||||
 | 
						MessageKey string
 | 
				
			||||||
 | 
						// SourceKey is the key used for the source file and line of the log call
 | 
				
			||||||
 | 
						SourceKey string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewOptions creates new options struct
 | 
					// NewOptions creates new options struct
 | 
				
			||||||
@@ -38,6 +48,9 @@ func NewOptions(opts ...options.Option) Options {
 | 
				
			|||||||
		Context:          context.Background(),
 | 
							Context:          context.Background(),
 | 
				
			||||||
		ContextAttrFuncs: DefaultContextAttrFuncs,
 | 
							ContextAttrFuncs: DefaultContextAttrFuncs,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						WithMicroKeys()(&options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
		o(&options)
 | 
							o(&options)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -45,18 +58,19 @@ func NewOptions(opts ...options.Option) Options {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WithContextAttrFuncs appends default funcs for the context arrts filler
 | 
					// WithContextAttrFuncs appends default funcs for the context arrts filler
 | 
				
			||||||
func WithContextAttrFuncs(attrs ...interface{}) options.Option {
 | 
					func WithContextAttrFuncs(fncs ...ContextAttrFunc) options.Option {
 | 
				
			||||||
	return func(src interface{}) error {
 | 
						return func(src interface{}) error {
 | 
				
			||||||
		v, err := options.Get(src, ".ContextAttrFuncs")
 | 
							v, err := options.Get(src, ".ContextAttrFuncs")
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		} else if rutil.IsZero(v) {
 | 
							} else if rutil.IsZero(v) {
 | 
				
			||||||
			v = reflect.MakeSlice(reflect.TypeOf(v), 0, len(attrs)).Interface()
 | 
								v = reflect.MakeSlice(reflect.TypeOf(v), 0, len(fncs)).Interface()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		cv := reflect.ValueOf(v)
 | 
							cv := reflect.ValueOf(v)
 | 
				
			||||||
		for _, l := range attrs {
 | 
							for _, l := range fncs {
 | 
				
			||||||
			cv = reflect.Append(cv, reflect.ValueOf(l))
 | 
								cv = reflect.Append(cv, reflect.ValueOf(l))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							fmt.Printf("EEEE %#+v\n", cv.Interface())
 | 
				
			||||||
		return options.Set(src, cv.Interface(), ".ContextAttrFuncs")
 | 
							return options.Set(src, cv.Interface(), ".ContextAttrFuncs")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -88,3 +102,79 @@ func WithCallerSkipCount(c int) options.Option {
 | 
				
			|||||||
		return options.Set(src, c, ".CallerSkipCount")
 | 
							return options.Set(src, c, ".CallerSkipCount")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WithZapKeys() options.Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							var err error
 | 
				
			||||||
 | 
							if err = options.Set(src, "@timestamp", ".TimeKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = options.Set(src, "level", ".LevelKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = options.Set(src, "msg", ".MessageKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = options.Set(src, "caller", ".SourceKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WithZerologKeys() options.Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							var err error
 | 
				
			||||||
 | 
							if err = options.Set(src, "time", ".TimeKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = options.Set(src, "level", ".LevelKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = options.Set(src, "message", ".MessageKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = options.Set(src, "caller", ".SourceKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WithSlogKeys() options.Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							var err error
 | 
				
			||||||
 | 
							if err = options.Set(src, slog.TimeKey, ".TimeKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = options.Set(src, slog.LevelKey, ".LevelKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = options.Set(src, slog.MessageKey, ".MessageKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = options.Set(src, slog.SourceKey, ".SourceKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WithMicroKeys() options.Option {
 | 
				
			||||||
 | 
						return func(src interface{}) error {
 | 
				
			||||||
 | 
							var err error
 | 
				
			||||||
 | 
							if err = options.Set(src, "timestamp", ".TimeKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = options.Set(src, "level", ".LevelKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = options.Set(src, "msg", ".MessageKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = options.Set(src, "caller", ".SourceKey"); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -117,12 +117,14 @@ func (s *slogLogger) Attrs(attrs ...interface{}) Logger {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *slogLogger) Init(opts ...options.Option) error {
 | 
					func (s *slogLogger) Init(opts ...options.Option) error {
 | 
				
			||||||
 | 
						if len(s.opts.ContextAttrFuncs) == 0 {
 | 
				
			||||||
 | 
							s.opts.ContextAttrFuncs = DefaultContextAttrFuncs
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	for _, o := range opts {
 | 
						for _, o := range opts {
 | 
				
			||||||
		if err := o(&s.opts); err != nil {
 | 
							if err := o(&s.opts); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if slog, ok := s.opts.Context.Value(loggerKey{}).(*slog.Logger); ok {
 | 
						if slog, ok := s.opts.Context.Value(loggerKey{}).(*slog.Logger); ok {
 | 
				
			||||||
		s.slog = slog
 | 
							s.slog = slog
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
@@ -149,7 +151,7 @@ func (s *slogLogger) Log(ctx context.Context, lvl Level, msg string, attrs ...in
 | 
				
			|||||||
	runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
						runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
				
			||||||
	r := slog.NewRecord(time.Now(), loggerToSlogLevel(lvl), msg, pcs[0])
 | 
						r := slog.NewRecord(time.Now(), loggerToSlogLevel(lvl), msg, pcs[0])
 | 
				
			||||||
	for _, fn := range s.opts.ContextAttrFuncs {
 | 
						for _, fn := range s.opts.ContextAttrFuncs {
 | 
				
			||||||
		attrs = append(attrs, fn(ctx))
 | 
							attrs = append(attrs, fn(ctx)...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	r.Add(attrs...)
 | 
						r.Add(attrs...)
 | 
				
			||||||
	_ = s.slog.Handler().Handle(ctx, r)
 | 
						_ = s.slog.Handler().Handle(ctx, r)
 | 
				
			||||||
@@ -163,7 +165,7 @@ func (s *slogLogger) Info(ctx context.Context, msg string, attrs ...interface{})
 | 
				
			|||||||
	runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
						runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
				
			||||||
	r := slog.NewRecord(time.Now(), slog.LevelInfo, msg, pcs[0])
 | 
						r := slog.NewRecord(time.Now(), slog.LevelInfo, msg, pcs[0])
 | 
				
			||||||
	for _, fn := range s.opts.ContextAttrFuncs {
 | 
						for _, fn := range s.opts.ContextAttrFuncs {
 | 
				
			||||||
		attrs = append(attrs, fn(ctx))
 | 
							attrs = append(attrs, fn(ctx)...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	r.Add(attrs...)
 | 
						r.Add(attrs...)
 | 
				
			||||||
	_ = s.slog.Handler().Handle(ctx, r)
 | 
						_ = s.slog.Handler().Handle(ctx, r)
 | 
				
			||||||
@@ -177,7 +179,7 @@ func (s *slogLogger) Debug(ctx context.Context, msg string, attrs ...interface{}
 | 
				
			|||||||
	runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
						runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
				
			||||||
	r := slog.NewRecord(time.Now(), slog.LevelDebug, msg, pcs[0])
 | 
						r := slog.NewRecord(time.Now(), slog.LevelDebug, msg, pcs[0])
 | 
				
			||||||
	for _, fn := range s.opts.ContextAttrFuncs {
 | 
						for _, fn := range s.opts.ContextAttrFuncs {
 | 
				
			||||||
		attrs = append(attrs, fn(ctx))
 | 
							attrs = append(attrs, fn(ctx)...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	r.Add(attrs...)
 | 
						r.Add(attrs...)
 | 
				
			||||||
	_ = s.slog.Handler().Handle(ctx, r)
 | 
						_ = s.slog.Handler().Handle(ctx, r)
 | 
				
			||||||
@@ -191,7 +193,7 @@ func (s *slogLogger) Trace(ctx context.Context, msg string, attrs ...interface{}
 | 
				
			|||||||
	runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
						runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
				
			||||||
	r := slog.NewRecord(time.Now(), slog.LevelDebug-1, msg, pcs[0])
 | 
						r := slog.NewRecord(time.Now(), slog.LevelDebug-1, msg, pcs[0])
 | 
				
			||||||
	for _, fn := range s.opts.ContextAttrFuncs {
 | 
						for _, fn := range s.opts.ContextAttrFuncs {
 | 
				
			||||||
		attrs = append(attrs, fn(ctx))
 | 
							attrs = append(attrs, fn(ctx)...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	r.Add(attrs...)
 | 
						r.Add(attrs...)
 | 
				
			||||||
	_ = s.slog.Handler().Handle(ctx, r)
 | 
						_ = s.slog.Handler().Handle(ctx, r)
 | 
				
			||||||
@@ -205,7 +207,7 @@ func (s *slogLogger) Error(ctx context.Context, msg string, attrs ...interface{}
 | 
				
			|||||||
	runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
						runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
				
			||||||
	r := slog.NewRecord(time.Now(), slog.LevelError, msg, pcs[0])
 | 
						r := slog.NewRecord(time.Now(), slog.LevelError, msg, pcs[0])
 | 
				
			||||||
	for _, fn := range s.opts.ContextAttrFuncs {
 | 
						for _, fn := range s.opts.ContextAttrFuncs {
 | 
				
			||||||
		attrs = append(attrs, fn(ctx))
 | 
							attrs = append(attrs, fn(ctx)...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	r.Add(attrs...)
 | 
						r.Add(attrs...)
 | 
				
			||||||
	_ = s.slog.Handler().Handle(ctx, r)
 | 
						_ = s.slog.Handler().Handle(ctx, r)
 | 
				
			||||||
@@ -219,7 +221,7 @@ func (s *slogLogger) Fatal(ctx context.Context, msg string, attrs ...interface{}
 | 
				
			|||||||
	runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
						runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
				
			||||||
	r := slog.NewRecord(time.Now(), slog.LevelError+1, msg, pcs[0])
 | 
						r := slog.NewRecord(time.Now(), slog.LevelError+1, msg, pcs[0])
 | 
				
			||||||
	for _, fn := range s.opts.ContextAttrFuncs {
 | 
						for _, fn := range s.opts.ContextAttrFuncs {
 | 
				
			||||||
		attrs = append(attrs, fn(ctx))
 | 
							attrs = append(attrs, fn(ctx)...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	r.Add(attrs...)
 | 
						r.Add(attrs...)
 | 
				
			||||||
	_ = s.slog.Handler().Handle(ctx, r)
 | 
						_ = s.slog.Handler().Handle(ctx, r)
 | 
				
			||||||
@@ -234,7 +236,7 @@ func (s *slogLogger) Warn(ctx context.Context, msg string, attrs ...interface{})
 | 
				
			|||||||
	runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
						runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
 | 
				
			||||||
	r := slog.NewRecord(time.Now(), slog.LevelWarn, msg, pcs[0])
 | 
						r := slog.NewRecord(time.Now(), slog.LevelWarn, msg, pcs[0])
 | 
				
			||||||
	for _, fn := range s.opts.ContextAttrFuncs {
 | 
						for _, fn := range s.opts.ContextAttrFuncs {
 | 
				
			||||||
		attrs = append(attrs, fn(ctx))
 | 
							attrs = append(attrs, fn(ctx)...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	r.Add(attrs...)
 | 
						r.Add(attrs...)
 | 
				
			||||||
	_ = s.slog.Handler().Handle(ctx, r)
 | 
						_ = s.slog.Handler().Handle(ctx, r)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,8 +27,8 @@ func (t *noopTracer) Start(ctx context.Context, name string, opts ...options.Opt
 | 
				
			|||||||
		labels: options.Labels,
 | 
							labels: options.Labels,
 | 
				
			||||||
		kind:   options.Kind,
 | 
							kind:   options.Kind,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	span.spanID, _ = id.New()
 | 
						span.spanID.s, _ = id.New()
 | 
				
			||||||
	span.traceID, _ = id.New()
 | 
						span.traceID.s, _ = id.New()
 | 
				
			||||||
	if span.ctx == nil {
 | 
						if span.ctx == nil {
 | 
				
			||||||
		span.ctx = context.Background()
 | 
							span.ctx = context.Background()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -56,18 +56,26 @@ type noopEvent struct {
 | 
				
			|||||||
	labels []interface{}
 | 
						labels []interface{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type noopStringer struct {
 | 
				
			||||||
 | 
						s string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s noopStringer) String() string {
 | 
				
			||||||
 | 
						return s.s
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type noopSpan struct {
 | 
					type noopSpan struct {
 | 
				
			||||||
	ctx       context.Context
 | 
						ctx       context.Context
 | 
				
			||||||
	tracer    Tracer
 | 
						tracer    Tracer
 | 
				
			||||||
	name      string
 | 
						name      string
 | 
				
			||||||
	statusMsg string
 | 
						statusMsg string
 | 
				
			||||||
 | 
						traceID   noopStringer
 | 
				
			||||||
 | 
						spanID    noopStringer
 | 
				
			||||||
	events    []*noopEvent
 | 
						events    []*noopEvent
 | 
				
			||||||
	labels    []interface{}
 | 
						labels    []interface{}
 | 
				
			||||||
	logs      []interface{}
 | 
						logs      []interface{}
 | 
				
			||||||
	kind      SpanKind
 | 
						kind      SpanKind
 | 
				
			||||||
	status    SpanStatus
 | 
						status    SpanStatus
 | 
				
			||||||
	traceID   string
 | 
					 | 
				
			||||||
	spanID    string
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *noopSpan) Finish(opts ...options.Option) {
 | 
					func (s *noopSpan) Finish(opts ...options.Option) {
 | 
				
			||||||
@@ -103,11 +111,11 @@ func (s *noopSpan) Kind() SpanKind {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *noopSpan) TraceID() string {
 | 
					func (s *noopSpan) TraceID() string {
 | 
				
			||||||
	return s.traceID
 | 
						return s.traceID.String()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *noopSpan) SpanID() string {
 | 
					func (s *noopSpan) SpanID() string {
 | 
				
			||||||
	return s.spanID
 | 
						return s.spanID.String()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *noopSpan) Status() (SpanStatus, string) {
 | 
					func (s *noopSpan) Status() (SpanStatus, string) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								tracer/tracer_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								tracer/tracer_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					package tracer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v4/logger"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestLoggerWithTracer(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := context.TODO()
 | 
				
			||||||
 | 
						buf := bytes.NewBuffer(nil)
 | 
				
			||||||
 | 
						if err := logger.Init(logger.WithOutput(buf)); err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var span Span
 | 
				
			||||||
 | 
						ctx, span = DefaultTracer.Start(ctx, "test")
 | 
				
			||||||
 | 
						logger.Info(ctx, "msg")
 | 
				
			||||||
 | 
						if !strings.Contains(buf.String(), span.TraceID()) {
 | 
				
			||||||
 | 
							t.Fatalf("log does not contains tracer id")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user