Skip to content

Commit

Permalink
feat: add handler for log/slog in go1.21 (#548)
Browse files Browse the repository at this point in the history
  • Loading branch information
MarvinJWendt committed Aug 27, 2023
1 parent e376aa8 commit 7fea5c7
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
18 changes: 18 additions & 0 deletions _examples/slog/demo/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import (
"github.com/pterm/pterm"
"log/slog"
)

func main() {
handler := pterm.NewSlogHandler(&pterm.DefaultLogger)
logger := slog.New(handler)

logger.Debug("This is a debug message that won't show")
pterm.DefaultLogger.Level = pterm.LogLevelDebug // Enable debug messages
logger.Debug("This is a debug message", "changedLevel", true)
logger.Info("This is an info message")
logger.Warn("This is a warning message")
logger.Error("This is an error message")
}
82 changes: 82 additions & 0 deletions slog_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package pterm

import (
"context"
"log/slog"
)

type SlogHandler struct {
logger *Logger
attrs []slog.Attr
}

// Enabled returns true if the given level is enabled.
func (s *SlogHandler) Enabled(ctx context.Context, level slog.Level) bool {
switch level {
case slog.LevelDebug:
return s.logger.CanPrint(LogLevelDebug)
case slog.LevelInfo:
return s.logger.CanPrint(LogLevelInfo)
case slog.LevelWarn:
return s.logger.CanPrint(LogLevelWarn)
case slog.LevelError:
return s.logger.CanPrint(LogLevelError)
}
return false
}

// Handle handles the given record.
func (s *SlogHandler) Handle(ctx context.Context, record slog.Record) error {
level := record.Level
message := record.Message

// Convert slog Attrs to a map.
keyValsMap := make(map[string]interface{})

record.Attrs(func(attr slog.Attr) bool {
keyValsMap[attr.Key] = attr.Value
return true
})

for _, attr := range s.attrs {
keyValsMap[attr.Key] = attr.Value
}

args := s.logger.ArgsFromMap(keyValsMap)

// Wrapping args inside another slice to match [][]LoggerArgument
argsWrapped := [][]LoggerArgument{args}

switch level {
case slog.LevelDebug:
s.logger.Debug(message, argsWrapped...)
case slog.LevelInfo:
s.logger.Info(message, argsWrapped...)
case slog.LevelWarn:
s.logger.Warn(message, argsWrapped...)
case slog.LevelError:
s.logger.Error(message, argsWrapped...)
default:
s.logger.Print(message, argsWrapped...)
}

return nil
}

// WithAttrs returns a new handler with the given attributes.
func (s *SlogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
newS := *s
newS.attrs = attrs
return &newS
}

// WithGroup is not yet supported.
func (s *SlogHandler) WithGroup(name string) slog.Handler {
// Grouping is not yet supported by pterm.
return s
}

// NewSlogHandler returns a new logging handler that can be intrgrated with log/slog.
func NewSlogHandler(logger *Logger) *SlogHandler {
return &SlogHandler{logger: logger}
}

0 comments on commit 7fea5c7

Please sign in to comment.