logger/slog: add ability to pass func that creates slog.Handler compatible interface

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
Василий Толстов 2024-12-07 16:16:45 +03:00
parent 0e66688f8f
commit 286430991e
2 changed files with 35 additions and 0 deletions

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"log/slog" "log/slog"
"os" "os"
"reflect"
"regexp" "regexp"
"runtime" "runtime"
"strconv" "strconv"
@ -177,6 +178,16 @@ func (s *slogLogger) Init(opts ...logger.Option) error {
if v, ok := s.opts.Context.Value(handlerKey{}).(slog.Handler); ok && v != nil { if v, ok := s.opts.Context.Value(handlerKey{}).(slog.Handler); ok && v != nil {
h = v h = v
} }
if fn := s.opts.Context.Value(handlerFnKey{}); fn != nil {
if rfn := reflect.ValueOf(fn); rfn.Kind() == reflect.Func {
if ret := rfn.Call([]reflect.Value{reflect.ValueOf(s.opts.Out), reflect.ValueOf(handleOpt)}); len(ret) == 1 {
if iface, ok := ret[0].Interface().(slog.Handler); ok && iface != nil {
h = iface
}
}
}
}
} }
if h == nil { if h == nil {
@ -347,3 +358,9 @@ type handlerKey struct{}
func WithHandler(h slog.Handler) logger.Option { func WithHandler(h slog.Handler) logger.Option {
return logger.SetOption(handlerKey{}, h) return logger.SetOption(handlerKey{}, h)
} }
type handlerFnKey struct{}
func WithHandlerFunc(fn any) logger.Option {
return logger.SetOption(handlerFnKey{}, fn)
}

View File

@ -6,6 +6,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"log" "log"
"log/slog"
"strings" "strings"
"testing" "testing"
@ -15,6 +16,23 @@ import (
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
) )
func TestWithHandlerFunc(t *testing.T) {
ctx := context.TODO()
buf := bytes.NewBuffer(nil)
l := NewLogger(logger.WithLevel(logger.InfoLevel), logger.WithOutput(buf),
WithHandlerFunc(slog.NewTextHandler),
)
if err := l.Init(); err != nil {
t.Fatal(err)
}
l.Info(ctx, "msg1")
if !bytes.Contains(buf.Bytes(), []byte(`msg=msg1`)) {
t.Fatalf("logger error not works, buf contains: %s", buf.Bytes())
}
}
func TestWithAddFields(t *testing.T) { func TestWithAddFields(t *testing.T) {
ctx := context.TODO() ctx := context.TODO()
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)