Compare commits
6 Commits
v4.0.13
...
79438f11e0
| Author | SHA1 | Date | |
|---|---|---|---|
| 79438f11e0 | |||
| 8d19abfebd | |||
| 77f3731329 | |||
| dbcf6bb74a | |||
| 17698440ed | |||
| eb8851ab58 |
@@ -17,7 +17,7 @@ func TestFSMStart(t *testing.T) {
|
||||
|
||||
wrapper := func(next StateFunc) StateFunc {
|
||||
return func(sctx context.Context, s State, opts ...StateOption) (State, error) {
|
||||
sctx = logger.NewContext(sctx, logger.Fields("state", s.Name()))
|
||||
sctx = logger.NewContext(sctx, logger.Attrs("state", s.Name()))
|
||||
return next(sctx, s, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
// Package logger provides a log interface
|
||||
package logger // import "go.unistack.org/micro/v4/logger"
|
||||
package logger
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"go.unistack.org/micro/v4/options"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultLogger variable
|
||||
DefaultLogger = NewLogger(WithLevel(ParseLevel(os.Getenv("MICRO_LOG_LEVEL"))))
|
||||
// DefaultLevel used by logger
|
||||
DefaultLevel = InfoLevel
|
||||
// DefaultCallerSkipCount used by logger
|
||||
DefaultCallerSkipCount = 2
|
||||
)
|
||||
|
||||
type ContextAttrFunc func(ctx context.Context) []interface{}
|
||||
|
||||
var DefaultContextAttrFuncs []ContextAttrFunc
|
||||
|
||||
var (
|
||||
// DefaultLogger variable
|
||||
DefaultLogger = NewLogger()
|
||||
// DefaultLevel used by logger
|
||||
DefaultLevel = InfoLevel
|
||||
// DefaultCallerSkipCount used by logger
|
||||
DefaultCallerSkipCount = 2
|
||||
)
|
||||
|
||||
// Logger is a generic logging interface
|
||||
type Logger interface {
|
||||
// Init initialises options
|
||||
|
||||
71
logger/noop.go
Normal file
71
logger/noop.go
Normal file
@@ -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{}) {
|
||||
}
|
||||
@@ -2,7 +2,9 @@ package logger
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
@@ -26,6 +28,14 @@ type Options struct {
|
||||
CallerSkipCount int
|
||||
// ContextAttrFuncs contains funcs that executed before log func on context
|
||||
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
|
||||
@@ -38,6 +48,9 @@ func NewOptions(opts ...options.Option) Options {
|
||||
Context: context.Background(),
|
||||
ContextAttrFuncs: DefaultContextAttrFuncs,
|
||||
}
|
||||
|
||||
WithMicroKeys()(&options)
|
||||
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
@@ -45,18 +58,19 @@ func NewOptions(opts ...options.Option) Options {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
v, err := options.Get(src, ".ContextAttrFuncs")
|
||||
if err != nil {
|
||||
return err
|
||||
} 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)
|
||||
for _, l := range attrs {
|
||||
for _, l := range fncs {
|
||||
cv = reflect.Append(cv, reflect.ValueOf(l))
|
||||
}
|
||||
fmt.Printf("EEEE %#+v\n", cv.Interface())
|
||||
return options.Set(src, cv.Interface(), ".ContextAttrFuncs")
|
||||
}
|
||||
}
|
||||
@@ -88,3 +102,79 @@ func WithCallerSkipCount(c int) options.Option {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
@@ -20,29 +22,32 @@ var (
|
||||
fatalValue = slog.StringValue("fatal")
|
||||
)
|
||||
|
||||
var renameAttr = func(_ []string, a slog.Attr) slog.Attr {
|
||||
func (s *slogLogger) renameAttr(_ []string, a slog.Attr) slog.Attr {
|
||||
switch a.Key {
|
||||
case slog.SourceKey:
|
||||
source := a.Value.Any().(*slog.Source)
|
||||
a.Value = slog.StringValue(source.File + ":" + strconv.Itoa(source.Line))
|
||||
a.Key = "caller"
|
||||
a.Key = s.opts.SourceKey
|
||||
case slog.TimeKey:
|
||||
a.Key = "timestamp"
|
||||
a.Key = s.opts.TimeKey
|
||||
case slog.MessageKey:
|
||||
a.Key = s.opts.MessageKey
|
||||
case slog.LevelKey:
|
||||
level := a.Value.Any().(slog.Level)
|
||||
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
|
||||
@@ -55,10 +60,10 @@ var renameAttr = func(_ []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 {
|
||||
@@ -69,14 +74,16 @@ 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{
|
||||
ReplaceAttr: renameAttr,
|
||||
ReplaceAttr: s.renameAttr,
|
||||
Level: l.leveler,
|
||||
AddSource: true,
|
||||
}
|
||||
@@ -87,25 +94,25 @@ 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())
|
||||
|
||||
handleOpt := &slog.HandlerOptions{
|
||||
ReplaceAttr: renameAttr,
|
||||
ReplaceAttr: nl.renameAttr,
|
||||
Level: s.leveler,
|
||||
AddSource: true,
|
||||
}
|
||||
@@ -117,20 +124,25 @@ func (s *slogLogger) Attrs(attrs ...interface{}) Logger {
|
||||
}
|
||||
|
||||
func (s *slogLogger) Init(opts ...options.Option) error {
|
||||
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
|
||||
}
|
||||
/*
|
||||
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: renameAttr,
|
||||
ReplaceAttr: s.renameAttr,
|
||||
Level: s.leveler,
|
||||
AddSource: true,
|
||||
}
|
||||
@@ -141,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
|
||||
}
|
||||
@@ -149,77 +161,86 @@ func (s *slogLogger) Log(ctx context.Context, lvl Level, msg string, attrs ...in
|
||||
runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
|
||||
r := slog.NewRecord(time.Now(), loggerToSlogLevel(lvl), msg, pcs[0])
|
||||
for _, fn := range s.opts.ContextAttrFuncs {
|
||||
attrs = append(attrs, fn(ctx))
|
||||
attrs = append(attrs, fn(ctx)...)
|
||||
}
|
||||
r.Add(attrs...)
|
||||
_ = s.slog.Handler().Handle(ctx, r)
|
||||
}
|
||||
|
||||
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
|
||||
runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
|
||||
r := slog.NewRecord(time.Now(), slog.LevelInfo, msg, pcs[0])
|
||||
for _, fn := range s.opts.ContextAttrFuncs {
|
||||
attrs = append(attrs, fn(ctx))
|
||||
attrs = append(attrs, fn(ctx)...)
|
||||
}
|
||||
r.Add(attrs...)
|
||||
_ = s.slog.Handler().Handle(ctx, r)
|
||||
}
|
||||
|
||||
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
|
||||
runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
|
||||
r := slog.NewRecord(time.Now(), slog.LevelDebug, msg, pcs[0])
|
||||
for _, fn := range s.opts.ContextAttrFuncs {
|
||||
attrs = append(attrs, fn(ctx))
|
||||
attrs = append(attrs, fn(ctx)...)
|
||||
}
|
||||
r.Add(attrs...)
|
||||
_ = s.slog.Handler().Handle(ctx, r)
|
||||
}
|
||||
|
||||
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
|
||||
runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
|
||||
r := slog.NewRecord(time.Now(), slog.LevelDebug-1, msg, pcs[0])
|
||||
for _, fn := range s.opts.ContextAttrFuncs {
|
||||
attrs = append(attrs, fn(ctx))
|
||||
attrs = append(attrs, fn(ctx)...)
|
||||
}
|
||||
r.Add(attrs...)
|
||||
_ = s.slog.Handler().Handle(ctx, r)
|
||||
}
|
||||
|
||||
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
|
||||
runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
|
||||
r := slog.NewRecord(time.Now(), slog.LevelError, msg, pcs[0])
|
||||
for _, fn := range s.opts.ContextAttrFuncs {
|
||||
attrs = append(attrs, fn(ctx))
|
||||
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
|
||||
runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
|
||||
r := slog.NewRecord(time.Now(), slog.LevelError+1, msg, pcs[0])
|
||||
for _, fn := range s.opts.ContextAttrFuncs {
|
||||
attrs = append(attrs, fn(ctx))
|
||||
attrs = append(attrs, fn(ctx)...)
|
||||
}
|
||||
r.Add(attrs...)
|
||||
_ = s.slog.Handler().Handle(ctx, r)
|
||||
@@ -227,14 +248,14 @@ 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
|
||||
runtime.Callers(s.opts.CallerSkipCount, pcs[:]) // skip [Callers, Infof]
|
||||
r := slog.NewRecord(time.Now(), slog.LevelWarn, msg, pcs[0])
|
||||
for _, fn := range s.opts.ContextAttrFuncs {
|
||||
attrs = append(attrs, fn(ctx))
|
||||
attrs = append(attrs, fn(ctx)...)
|
||||
}
|
||||
r.Add(attrs...)
|
||||
_ = s.slog.Handler().Handle(ctx, r)
|
||||
@@ -244,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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -27,8 +27,8 @@ func (t *noopTracer) Start(ctx context.Context, name string, opts ...options.Opt
|
||||
labels: options.Labels,
|
||||
kind: options.Kind,
|
||||
}
|
||||
span.spanID, _ = id.New()
|
||||
span.traceID, _ = id.New()
|
||||
span.spanID.s, _ = id.New()
|
||||
span.traceID.s, _ = id.New()
|
||||
if span.ctx == nil {
|
||||
span.ctx = context.Background()
|
||||
}
|
||||
@@ -56,18 +56,26 @@ type noopEvent struct {
|
||||
labels []interface{}
|
||||
}
|
||||
|
||||
type noopStringer struct {
|
||||
s string
|
||||
}
|
||||
|
||||
func (s noopStringer) String() string {
|
||||
return s.s
|
||||
}
|
||||
|
||||
type noopSpan struct {
|
||||
ctx context.Context
|
||||
tracer Tracer
|
||||
name string
|
||||
statusMsg string
|
||||
traceID noopStringer
|
||||
spanID noopStringer
|
||||
events []*noopEvent
|
||||
labels []interface{}
|
||||
logs []interface{}
|
||||
kind SpanKind
|
||||
status SpanStatus
|
||||
traceID string
|
||||
spanID string
|
||||
}
|
||||
|
||||
func (s *noopSpan) Finish(opts ...options.Option) {
|
||||
@@ -103,11 +111,11 @@ func (s *noopSpan) Kind() SpanKind {
|
||||
}
|
||||
|
||||
func (s *noopSpan) TraceID() string {
|
||||
return s.traceID
|
||||
return s.traceID.String()
|
||||
}
|
||||
|
||||
func (s *noopSpan) SpanID() string {
|
||||
return s.spanID
|
||||
return s.spanID.String()
|
||||
}
|
||||
|
||||
func (s *noopSpan) Status() (SpanStatus, string) {
|
||||
|
||||
28
tracer/tracer_test.go
Normal file
28
tracer/tracer_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package tracer_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"strings"
|
||||
"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)
|
||||
logger.DefaultLogger = slog.NewLogger(logger.WithOutput(buf))
|
||||
|
||||
if err := logger.Init(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
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")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user