diff --git a/handler.go b/handler.go index 0cc3190..2c78302 100644 --- a/handler.go +++ b/handler.go @@ -77,7 +77,10 @@ const ( ansiBrightRedFaint = "\033[91;2m" ) -const errKey = "err" +const ( + errKey = "err" + badKey = "!BADKEY" +) var ( defaultLevel = slog.LevelInfo @@ -345,7 +348,7 @@ func (h *handler) appendAttr(buf *buffer, attr slog.Attr, groupsPrefix string, g } } else if err, ok := attr.Value.Any().(tintError); ok { // append tintError - h.appendTintError(buf, err, groupsPrefix) + h.appendTintError(buf, err, attr.Key, groupsPrefix) buf.WriteByte(' ') } else { h.appendKey(buf, attr.Key, groupsPrefix) @@ -395,9 +398,12 @@ func (h *handler) appendValue(buf *buffer, v slog.Value, quote bool) { } } -func (h *handler) appendTintError(buf *buffer, err error, groupsPrefix string) { +func (h *handler) appendTintError(buf *buffer, err error, key string, groupsPrefix string) { + if key == badKey { + key = errKey + } buf.WriteStringIf(!h.noColor, ansiBrightRedFaint) - appendString(buf, groupsPrefix+errKey, true) + appendString(buf, groupsPrefix+key, true) buf.WriteByte('=') buf.WriteStringIf(!h.noColor, ansiResetFaint) appendString(buf, err.Error(), true) @@ -424,15 +430,12 @@ func needsQuoting(s string) bool { return false } -type tintError struct{ error } +type tintError interface{ Error() string } // Err returns a tinted (colorized) [slog.Attr] that will be written in red color // by the [tint.Handler]. When used with any other [slog.Handler], it behaves as // // slog.Any("err", err) func Err(err error) slog.Attr { - if err != nil { - err = tintError{err} - } return slog.Any(errKey, err) } diff --git a/handler_test.go b/handler_test.go index 5000e4a..06e3240 100644 --- a/handler_test.go +++ b/handler_test.go @@ -27,7 +27,7 @@ func Example() { slog.Info("Starting server", "addr", ":8080", "env", "production") slog.Debug("Connected to DB", "db", "myapp", "host", "localhost:5432") slog.Warn("Slow request", "method", "GET", "path", "/users", "duration", 497*time.Millisecond) - slog.Error("DB connection lost", tint.Err(errors.New("connection reset")), "db", "myapp") + slog.Error("DB connection lost", errors.New("connection reset"), "db", "myapp") // Output: } @@ -52,13 +52,13 @@ func TestHandler(t *testing.T) { }, { F: func(l *slog.Logger) { - l.Error("test", tint.Err(errors.New("fail"))) + l.Error("test", errors.New("fail")) }, Want: `Nov 10 23:00:00.000 ERR test err=fail`, }, { F: func(l *slog.Logger) { - l.Info("test", slog.Group("group", slog.String("key", "val"), tint.Err(errors.New("fail")))) + l.Info("test", slog.Group("group", slog.String("key", "val"), errors.New("fail"))) }, Want: `Nov 10 23:00:00.000 INF test group.key=val group.err=fail`, }, @@ -331,7 +331,7 @@ func TestHandler(t *testing.T) { { // https://github.com/lmittmann/tint/issues/44 F: func(l *slog.Logger) { l = l.WithGroup("group") - l.Error("test", tint.Err(errTest)) + l.Error("test", errTest) }, Want: `Nov 10 23:00:00.000 ERR test group.err=fail`, }, @@ -401,6 +401,10 @@ func TestReplaceAttr(t *testing.T) { replaceAttrRecorder := func(record *[]replaceAttrParams) func([]string, slog.Attr) slog.Attr { return func(groups []string, a slog.Attr) slog.Attr { + // Ignore time since it will be necessarily different when logged at different times + if a.Key == "time" { + return slog.Attr{} + } *record = append(*record, replaceAttrParams{groups, a}) return a }