Skip to content

Commit

Permalink
added level handler to slog
Browse files Browse the repository at this point in the history
  • Loading branch information
samlaf committed Feb 24, 2024
1 parent 4d7d39f commit 4c03592
Showing 1 changed file with 52 additions and 6 deletions.
58 changes: 52 additions & 6 deletions logging/slog_logger.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package logging

import (
"context"
"fmt"
"log/slog"
"os"
Expand All @@ -14,16 +15,16 @@ var _ Logger = (*SLogger)(nil)

func NewSlogLogger(env LogLevel) Logger {
if env == Production {
logHandler := slog.NewJSONHandler(os.Stdout, nil).WithAttrs([]slog.Attr{slog.String("env", string(env))})
logger := slog.New(logHandler)
jsonHandler := slog.NewJSONHandler(os.Stdout, nil).WithAttrs([]slog.Attr{slog.String("env", string(env))})
levelHandler := NewLevelHandler(slog.LevelInfo, jsonHandler) // production logs only info and above
logger := slog.New(levelHandler)
return &SLogger{
logger: logger,
}
} else if env == Development {
// Even though code is same for both environments, we are keeping it separate to show that we can have different
// implementations for different environments. For example, we can have log levels set differently
logHandler := slog.NewJSONHandler(os.Stdout, nil).WithAttrs([]slog.Attr{slog.String("env", string(env))})
logger := slog.New(logHandler)
jsonHandler := slog.NewJSONHandler(os.Stdout, nil).WithAttrs([]slog.Attr{slog.String("env", string(env))})
levelHandler := NewLevelHandler(slog.LevelDebug, jsonHandler) // development logs everything
logger := slog.New(levelHandler)
return &SLogger{
logger: logger,
}
Expand Down Expand Up @@ -73,3 +74,48 @@ func (s SLogger) Fatalf(template string, args ...interface{}) {
s.logger.Error(fmt.Sprintf(template, args...))
os.Exit(1)
}

// Taken from https://pkg.go.dev/log/slog@master#example-Handler-LevelHandler
// A LevelHandler wraps a Handler with an Enabled method
// that returns false for levels below a minimum.
// This permits our logger to only log messages of a certain level or higher
type LevelHandler struct {
level slog.Leveler
handler slog.Handler
}

// NewLevelHandler returns a LevelHandler with the given level.
// All methods except Enabled delegate to h.
func NewLevelHandler(level slog.Leveler, h slog.Handler) *LevelHandler {
// Optimization: avoid chains of LevelHandlers.
if lh, ok := h.(*LevelHandler); ok {
h = lh.Handler()
}
return &LevelHandler{level, h}
}

// Enabled implements Handler.Enabled by reporting whether
// level is at least as large as h's level.
func (h *LevelHandler) Enabled(_ context.Context, level slog.Level) bool {
return level >= h.level.Level()
}

// Handle implements Handler.Handle.
func (h *LevelHandler) Handle(ctx context.Context, r slog.Record) error {
return h.handler.Handle(ctx, r)
}

// WithAttrs implements Handler.WithAttrs.
func (h *LevelHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
return NewLevelHandler(h.level, h.handler.WithAttrs(attrs))
}

// WithGroup implements Handler.WithGroup.
func (h *LevelHandler) WithGroup(name string) slog.Handler {
return NewLevelHandler(h.level, h.handler.WithGroup(name))
}

// Handler returns the Handler wrapped by h.
func (h *LevelHandler) Handler() slog.Handler {
return h.handler
}

0 comments on commit 4c03592

Please sign in to comment.