diff --git a/hooks/slog/slog.go b/hooks/slog/slog.go index 4c8aac5..3cc584a 100644 --- a/hooks/slog/slog.go +++ b/hooks/slog/slog.go @@ -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..., ) diff --git a/hooks/slog/slog_test.go b/hooks/slog/slog_test.go index 71219fa..ed56cee 100644 --- a/hooks/slog/slog_test.go +++ b/hooks/slog/slog_test.go @@ -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) {