-
Notifications
You must be signed in to change notification settings - Fork 11
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
Add slog compatibility, move to Go 1.21 #97
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Steve Coffman <steve@khanacademy.org>
Hey, @StevenACoffman! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prior comment notwithstanding, I think we can do this without bumping the Go version and just moving the two new functions into a Go 1.21 tagged file.
errtrace.go
Outdated
func ErrAttr(err error) slog.Attr { | ||
return slog.Any("error", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking out loud:
The number of times "err" appears in this expression is quite high:
errtrace.ErrAttr(err)
What if we named this LogAttr?
slog.Default().Error("great sadness", errtrace.LogAttr(err))
@@ -54,7 +56,7 @@ func wrap(err error, callerPC uintptr) error { | |||
} | |||
|
|||
// Format writes the return trace for given error to the writer. | |||
// The output takes a fromat similar to the following: | |||
// The output takes a format similar to the following: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
errtrace.go
Outdated
// | ||
// slog.Default().Error("msg here", errtrace.ErrAttr(err)) | ||
func ErrAttr(err error) slog.Attr { | ||
return slog.Any("error", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The convention on log/slog seems to be to use "err" as the key for errors, not "error". This matches what Zap and Zerolog do as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, Zap uses "error" as the key: https://github.com/uber-go/zap/blob/master/error.go#L34
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation also shows that "error" is the key in Zerolog https://github.com/rs/zerolog?tab=readme-ov-file#error-logging
package main
import (
"errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func main() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
err := errors.New("seems we have an error here")
log.Error().Err(err).Msg("")
}
// Output: {"level":"error","error":"seems we have an error here","time":1609085256}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In slog, the various proposals (and usage by the primary author jba) show using "error" as the key: golang/go#59364
func ErrAttr(err error) slog.Attr {
return slog.Any("error", err)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, Zap uses "error" as the key: https://github.com/uber-go/zap/blob/master/error.go#L34
Well, that's embarrassing for me. 😆
I don't know why I assumed "err". Will revert that change.
This matches the convention used by Zap, Zerolog, etc.
I've renamed the field and the function just to see how it looks. |
I would rather not use "err" as the key, but I don't feel strongly, and otherwise looks good to me! Thanks for a wonderful library. Zap uses "error" as the key: https://github.com/uber-go/zap/blob/master/error.go#L34 // Error is shorthand for the common idiom NamedError("error", err).
func Error(err error) Field {
return NamedError("error", err)
} Zerolog has documentation that also shows that "error" is the key in Zerolog https://github.com/rs/zerolog?tab=readme-ov-file#error-logging package main
import (
"errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func main() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
err := errors.New("seems we have an error here")
log.Error().Err(err).Msg("")
}
// Output: {"level":"error","error":"seems we have an error here","time":1609085256} In slog, the various proposals (and usage by the primary author jba) show using "error" as the key: golang/go#59364
Maybe there is some other examples that you have seen where that is not the case? |
Signed-off-by: Steve Coffman <steve@khanacademy.org>
Oops. Yeah, "error" is good. |
@abhinav is there anything remaining to get this merged? |
Hey @StevenACoffman, apologies, I had an update typed out but I never sent it. After mulling it over a bit, I don't think that the value should be structured: the majority use case will want to consume a string. For cases where folks want a structured object logged for errors, the logger APIs should provide enough control/overrides for how specific values are encoded—e.g. "encode errors using this function instead." But I want to confirm my thinking with others—you, @prashantv, @akshayjshah. Outside of that, if we agree on the approach, what remains before merging this PR is:
|
+1 on using string. Should we do something similar to zap here, |
I think not. In hindsight, that wasn't the most ideal choice we could've made there. |
Flexibility (at the logger level) is probably the right answer, but I've found the message-only errors useful when dealing with logs in aggregate (e.g., looking at a distribution of errors across log messages in a timeframe) where additional stacks/traces get quite noisy. On the flip side, once I've drilled into a specific log, then I find the additional information useful to understand where it came from. |
Go 1.21 adds the
log/slog
package and this PR adds convenience and compatibility with that package. Merging this PR would require dropping Go 1.20 support, which may not (yet!) be desired. If so, this PR can wait until that is desired.Each major Go release is supported until there are two newer major releases. Go 1.22 was released on February 6, 2024
so Go 1.20 is no longer supported.