From f8121b8ada05b3ef7ad18ab444bb30f8ef56d17b Mon Sep 17 00:00:00 2001 From: Jan Tytgat Date: Tue, 29 Apr 2025 22:26:20 +0200 Subject: [PATCH] Add slogd package back into repository Signed-off-by: Jan Tytgat --- go.mod | 5 +- go.sum | 2 - slogd/disabledHandler.go | 32 +++++++++ slogd/jsonHandler.go | 10 +++ slogd/level.go | 56 +++++++++++++++ slogd/slogd.go | 148 +++++++++++++++++++++++++++++++++++++++ slogd/textHandler.go | 10 +++ 7 files changed, 258 insertions(+), 5 deletions(-) create mode 100644 slogd/disabledHandler.go create mode 100644 slogd/jsonHandler.go create mode 100644 slogd/level.go create mode 100644 slogd/slogd.go create mode 100644 slogd/textHandler.go diff --git a/go.mod b/go.mod index 4a28426..861c3a5 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,8 @@ module git.flexabyte.io/flexabyte/go-kit go 1.24.2 require ( - git.flexabyte.io/flexabyte/go-slogd v0.0.0-20250428200220-8e65f81d9450 + github.com/samber/slog-formatter v1.2.0 + github.com/samber/slog-multi v1.4.0 github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 ) @@ -11,7 +12,5 @@ require ( require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/samber/lo v1.50.0 // indirect - github.com/samber/slog-formatter v1.2.0 // indirect - github.com/samber/slog-multi v1.4.0 // indirect golang.org/x/text v0.24.0 // indirect ) diff --git a/go.sum b/go.sum index 3dcb49c..a2fc126 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -git.flexabyte.io/flexabyte/go-slogd v0.0.0-20250428200220-8e65f81d9450 h1:VCstITW9pMgR5EnSLU83UiK7llLOguFLAo26VOOnzrI= -git.flexabyte.io/flexabyte/go-slogd v0.0.0-20250428200220-8e65f81d9450/go.mod h1:rL08OHw4aycfjkZOS8pBfLapeG3IZHxIInW29hVVSrI= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/slogd/disabledHandler.go b/slogd/disabledHandler.go new file mode 100644 index 0000000..9e62c8e --- /dev/null +++ b/slogd/disabledHandler.go @@ -0,0 +1,32 @@ +package slogd + +import ( + "context" + "log/slog" +) + +func newDisabledHandler() slog.Handler { + return &disabledHandler{} +} + +func registerDisabledHandler(activate bool) { + RegisterSink(handlerDisabled, newDisabledHandler(), activate) +} + +type disabledHandler struct{} + +func (h *disabledHandler) Handle(ctx context.Context, r slog.Record) error { + return nil +} + +func (h *disabledHandler) Enabled(ctx context.Context, level slog.Level) bool { + return false +} + +func (h *disabledHandler) WithAttrs(attrs []slog.Attr) slog.Handler { + return h +} + +func (h *disabledHandler) WithGroup(group string) slog.Handler { + return h +} diff --git a/slogd/jsonHandler.go b/slogd/jsonHandler.go new file mode 100644 index 0000000..0688cc3 --- /dev/null +++ b/slogd/jsonHandler.go @@ -0,0 +1,10 @@ +package slogd + +import ( + "io" + "log/slog" +) + +func RegisterJSONHandler(w io.Writer, activate bool) { + RegisterSink(HandlerJSON, slog.NewJSONHandler(w, HandlerOptions()), activate) +} diff --git a/slogd/level.go b/slogd/level.go new file mode 100644 index 0000000..ac1352e --- /dev/null +++ b/slogd/level.go @@ -0,0 +1,56 @@ +package slogd + +import ( + "log/slog" + "strings" +) + +const ( + LevelTrace = slog.Level(-8) + LevelDebug = slog.LevelDebug + LevelInfo = slog.LevelInfo + LevelNotice = slog.Level(2) + LevelWarn = slog.LevelWarn + LevelError = slog.LevelError + LevelFatal = slog.Level(12) + LevelDefault = LevelInfo +) + +var levelNames = map[slog.Leveler]string{ + LevelTrace: "TRACE", + LevelDebug: "DEBUG", + LevelInfo: "INFO", + LevelNotice: "NOTICE", + LevelWarn: "WARN", + LevelError: "ERROR", + LevelFatal: "FATAL", +} + +func ReplaceAttrs(groups []string, a slog.Attr) slog.Attr { + if a.Key == slog.LevelKey { + a.Value = slog.StringValue(LevelName(a.Value.Any().(slog.Level))) + } + return a +} + +func Level(l string) slog.Level { + mux.Lock() + defer mux.Unlock() + for k, v := range levelNames { + if strings.ToUpper(l) == v { + return k.Level() + } + } + return LevelDefault +} + +func LevelName(l slog.Level) string { + mux.Lock() + defer mux.Unlock() + for k, v := range levelNames { + if k == l { + return v + } + } + return levelNames[LevelDefault] +} diff --git a/slogd/slogd.go b/slogd/slogd.go new file mode 100644 index 0000000..a13370f --- /dev/null +++ b/slogd/slogd.go @@ -0,0 +1,148 @@ +package slogd + +import ( + "context" + "log/slog" + "sync" + + slogformatter "github.com/samber/slog-formatter" + slogmulti "github.com/samber/slog-multi" +) + +const ( + HandlerText string = "text" + HandlerJSON string = "json" + handlerDisabled string = "disabled" +) + +const ( + FlowFanOut Flow = iota + FlowPipeline + FlowRouting + FlowFailOver + FlowLoadBalancing +) + +type Flow int + +var ( + ctxKey = contextKey{} +) +var ( + handlers = make(map[string]slog.Handler) + activeHandler string + level = new(slog.LevelVar) + formatters []slogformatter.Formatter + middlewares []slogmulti.Middleware + source bool + logger *slog.Logger + mux = &sync.Mutex{} +) + +func ActiveHandler() string { + mux.Lock() + defer mux.Unlock() + return activeHandler +} + +func key() contextKey { + return ctxKey +} + +func Disable() { + UseHandler(handlerDisabled) +} + +func FromContext(ctx context.Context) *slog.Logger { + if l, ok := ctx.Value(key()).(*slog.Logger); ok { + return l + } + return Logger() +} + +func GetLevel() slog.Level { + return level.Level() +} + +func GetLevelString() string { + return level.String() +} + +func HandlerOptions() *slog.HandlerOptions { + return &slog.HandlerOptions{ + AddSource: source, + Level: level, + ReplaceAttr: ReplaceAttrs, + } +} + +func Init(l slog.Level, addSource bool) { + level.Set(l) + source = addSource +} + +func Logger() *slog.Logger { + mux.Lock() + defer mux.Unlock() + + if logger == nil { + logger = slog.New(handlers[handlerDisabled]) + } + return logger +} + +func SetLevel(l slog.Level) { + mux.Lock() + defer mux.Unlock() + level.Set(l) +} + +func RegisterFormatter(f slogformatter.Formatter) { + mux.Lock() + defer mux.Unlock() + formatters = append(formatters, f) +} + +func RegisterMiddleware(h slogmulti.Middleware) { + mux.Lock() + defer mux.Unlock() + middlewares = append(middlewares, h) +} + +func RegisterSink(name string, h slog.Handler, activate bool) { + mux.Lock() + handlers[name] = h + mux.Unlock() + + if activate { + UseHandler(name) + } +} + +func UseHandler(name string) { + mux.Lock() + defer mux.Unlock() + if _, ok := handlers[name]; !ok { + Logger().LogAttrs(context.Background(), LevelError, "could not find handler", slog.String("name", name)) + return + } + + formatterPipe := slogformatter.NewFormatterMiddleware(formatters...) + pipe := slogmulti.Pipe(middlewares...).Pipe(formatterPipe) + handler := slogmulti.Fanout(handlers[name]) + + logger = slog.New(pipe.Handler(handler)) + activeHandler = name +} + +func WithContext(ctx context.Context) context.Context { + return context.WithValue(ctx, key(), Logger()) +} + +func init() { + // RegisterFormatter(LevelFormatter()) + // RegisterMiddleware(NewLevelMiddleware()) + registerDisabledHandler(true) +} + +type contextKey struct{} diff --git a/slogd/textHandler.go b/slogd/textHandler.go new file mode 100644 index 0000000..0ce0631 --- /dev/null +++ b/slogd/textHandler.go @@ -0,0 +1,10 @@ +package slogd + +import ( + "io" + "log/slog" +) + +func RegisterTextHandler(w io.Writer, activate bool) { + RegisterSink(HandlerText, slog.NewTextHandler(w, HandlerOptions()), activate) +}