From ac0f02ebb6a82a430167e3abedd0869d866f0c26 Mon Sep 17 00:00:00 2001 From: Eser Ozvataf Date: Sun, 18 Aug 2024 06:28:30 +0300 Subject: [PATCH] feat(logfx): add PrettyMode to Config and implement new log handler - Added PrettyMode field to Config struct with default true. - Created new Handler struct in handler.go for flexible logging. - Implemented NewHandler function. - Modified RegisterLogger to use NewHandler. - Updated replacerGenerator to conditionally handle prettyMode. --- pkg/bliss/logfx/config.go | 5 ++- pkg/bliss/logfx/handler.go | 76 +++++++++++++++++++++++++++++++++++++ pkg/bliss/logfx/mod.go | 10 +---- pkg/bliss/logfx/replacer.go | 25 +++++++----- 4 files changed, 95 insertions(+), 21 deletions(-) create mode 100644 pkg/bliss/logfx/handler.go diff --git a/pkg/bliss/logfx/config.go b/pkg/bliss/logfx/config.go index 270cd24..22d9ba3 100644 --- a/pkg/bliss/logfx/config.go +++ b/pkg/bliss/logfx/config.go @@ -1,6 +1,7 @@ package logfx type Config struct { - Level string `conf:"LEVEL" default:"INFO"` - AddSource bool `conf:"ADD_SOURCE" default:"false"` + Level string `conf:"LEVEL" default:"INFO"` + PrettyMode bool `conf:"PRETTY" default:"true"` + AddSource bool `conf:"ADD_SOURCE" default:"false"` } diff --git a/pkg/bliss/logfx/handler.go b/pkg/bliss/logfx/handler.go new file mode 100644 index 0000000..2feb249 --- /dev/null +++ b/pkg/bliss/logfx/handler.go @@ -0,0 +1,76 @@ +package logfx + +import ( + "context" + "fmt" + "io" + "log/slog" + "strings" +) + +type Handler struct { + InnerHandler slog.Handler + + writer io.Writer + config *Config +} + +func NewHandler(w io.Writer, config *Config) (*Handler, error) { + var level slog.Level + + err := level.UnmarshalText([]byte(config.Level)) + if err != nil { + return nil, fmt.Errorf("failed to parse log level: %w", err) + } + + opts := &slog.HandlerOptions{ + Level: level, + ReplaceAttr: replacerGenerator(config.PrettyMode), + AddSource: config.AddSource, + } + + innerHandler := slog.NewJSONHandler(w, opts) + + return &Handler{ + InnerHandler: innerHandler, + + writer: w, + config: config, + }, nil +} + +func (h *Handler) Enabled(ctx context.Context, level slog.Level) bool { + return h.InnerHandler.Enabled(ctx, level) +} + +func (h *Handler) Handle(ctx context.Context, rec slog.Record) error { + if h.config.PrettyMode { + out := strings.Builder{} + + out.WriteString(rec.Time.Format("2006-01-02 15:04:05")) + out.WriteRune(' ') + out.WriteString(rec.Level.String()) + out.WriteRune(' ') + out.WriteString(rec.Message) + out.WriteRune(' ') + + _, err := io.WriteString(h.writer, out.String()) + if err != nil { + return fmt.Errorf("failed to write log: %w", err) + } + } + + return h.InnerHandler.Handle(ctx, rec) +} + +func (h *Handler) WithAttrs(attrs []slog.Attr) slog.Handler { + return &Handler{ + InnerHandler: h.InnerHandler.WithAttrs(attrs), + } +} + +func (h *Handler) WithGroup(name string) slog.Handler { + return &Handler{ + InnerHandler: h.InnerHandler.WithGroup(name), + } +} diff --git a/pkg/bliss/logfx/mod.go b/pkg/bliss/logfx/mod.go index e34dd60..de09787 100644 --- a/pkg/bliss/logfx/mod.go +++ b/pkg/bliss/logfx/mod.go @@ -16,19 +16,11 @@ var Module = fx.Module( ) func RegisterLogger(config *Config) (*slog.Logger, error) { - var level slog.Level - - err := level.UnmarshalText([]byte(config.Level)) + handler, err := NewHandler(os.Stderr, config) if err != nil { return nil, err } - handler := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{ - Level: level, - ReplaceAttr: replaceAttr, - AddSource: config.AddSource, - }) - logger := slog.New(handler) slog.SetDefault(logger) diff --git a/pkg/bliss/logfx/replacer.go b/pkg/bliss/logfx/replacer.go index aec44c1..9339c12 100644 --- a/pkg/bliss/logfx/replacer.go +++ b/pkg/bliss/logfx/replacer.go @@ -15,18 +15,23 @@ type ( } ) -func replaceAttr(groups []string, attr slog.Attr) slog.Attr { - switch attr.Value.Kind() { //nolint:gocritic,wsl,exhaustive - // other cases - - case slog.KindAny: - switch v := attr.Value.Any().(type) { //nolint:gocritic - case error: - attr.Value = fmtErr(v) +func replacerGenerator(prettyMode bool) func([]string, slog.Attr) slog.Attr { + return func(groups []string, attr slog.Attr) slog.Attr { + if prettyMode { + if attr.Key == slog.TimeKey || attr.Key == slog.LevelKey || attr.Key == slog.MessageKey { + return slog.Attr{} //nolint:exhaustruct + } + } + + if attr.Value.Kind() == slog.KindAny { + switch v := attr.Value.Any().(type) { //nolint:gocritic + case error: + attr.Value = fmtErr(v) + } } - } - return attr + return attr + } } // fmtErr returns a slog.GroupValue with keys "msg" and "trace". If the error