Allow for custom level mapping between logrus and slog

This commit is contained in:
Jonathan Hall 2023-11-09 09:59:33 +01:00
parent e3f17e55eb
commit 486d0ecfdd
2 changed files with 34 additions and 7 deletions

View File

@ -9,9 +9,16 @@ import (
"github.com/sirupsen/logrus"
)
// LevelMapper maps a [github.com/sirupsen/logrus.Level] value to a
// [slog.Leveler] value. To change the default level mapping, for instance
// to allow mapping to custom or dynamic slog levels in your application, set
// [SlogHook.LevelMapper] to your own implementation of this function.
type LevelMapper func(logrus.Level) slog.Leveler
// SlogHook sends logs to slog.
type SlogHook struct {
logger *slog.Logger
logger *slog.Logger
LevelMapper LevelMapper
}
var _ logrus.Hook = (*SlogHook)(nil)
@ -31,7 +38,10 @@ func NewSlogHook(logger *slog.Logger) *SlogHook {
}
}
func (*SlogHook) toSlogLevel(level logrus.Level) slog.Level {
func (h *SlogHook) toSlogLevel(level logrus.Level) slog.Leveler {
if h.LevelMapper != nil {
return h.LevelMapper(level)
}
switch level {
case logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel:
return slog.LevelError
@ -62,7 +72,7 @@ func (h *SlogHook) Fire(entry *logrus.Entry) error {
}
h.logger.Log(
entry.Context,
h.toSlogLevel(entry.Level),
h.toSlogLevel(entry.Level).Level(),
entry.Message,
attrs...,
)

View File

@ -15,9 +15,10 @@ import (
func TestSlogHook(t *testing.T) {
tests := []struct {
name string
fn func(*logrus.Logger)
want []string
name string
mapper LevelMapper
fn func(*logrus.Logger)
want []string
}{
{
name: "defaults",
@ -39,6 +40,20 @@ func TestSlogHook(t *testing.T) {
"level=ERROR msg=error chicken=cluck",
},
},
{
name: "level mapper",
mapper: func(logrus.Level) slog.Leveler {
return slog.LevelInfo
},
fn: func(log *logrus.Logger) {
log.WithFields(logrus.Fields{
"chicken": "cluck",
}).Error("error")
},
want: []string{
"level=INFO msg=error chicken=cluck",
},
},
}
for _, tt := range tests {
@ -55,7 +70,9 @@ func TestSlogHook(t *testing.T) {
}))
log := logrus.New()
log.Out = io.Discard
log.AddHook(NewSlogHook(slogLogger))
hook := NewSlogHook(slogLogger)
hook.LevelMapper = tt.mapper
log.AddHook(hook)
tt.fn(log)
got := strings.Split(strings.TrimSpace(buf.String()), "\n")
if len(got) != len(tt.want) {