Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle any type that implements error interface #51

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ const (
ansiBrightRedFaint = "\033[91;2m"
)

const errKey = "err"
const (
errKey = "err"
badKey = "!BADKEY"
)

var (
defaultLevel = slog.LevelInfo
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
}
12 changes: 8 additions & 4 deletions handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
}

Expand All @@ -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`,
},
Expand Down Expand Up @@ -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`,
},
Expand Down Expand Up @@ -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
}
Expand Down
Loading