Open Dragomir-Ivanov opened 4 years ago
We could maybe change the conversion of errors to rest.Error
to rely on errors.As
(new in Go 1.13).
Then you can implement your own error types as needed, and implement the following method to asign itself to a rest.Error
:
func (err MyError) As(target interface{}) bool {
v, ok := target.(*http.Error)
if !ok { return false }
// set v. values
return true
}
We could for conveniences provide something like this in the rest
package:
type codeError struct{
code int
err error
}
func StatusError(code int, err error) error {
return codeError{code: code, err: err}
}
func (err codeError) Unwrap() error {
return err.err
}
func (err codeError) Error() string {
if err.err == nil {
return http.StatusText(err.code)
}
return err.Error()
}
func (err codeError) As(target interface{}) bool {
v, ok := target.(*http.Error)
if !ok { return false }
v.Code = err.Code()
v.Message = err.Error()
return true
If we do the conversion to rest.Error
in the error formatter, then your "original" error could be logged to sentry first.
There are other ways to do this, this is just one method.
Thank you @smyrman for the detailed response. Let me think about it a little.
Likewise we can match against errors from resource
. (e.g. resource.ErrNotFound
) using errors.Is
, so that we will match even when they are wrapped by other errors, and thus be able to get a rest.Error
instance with more context in the error message.
To wrap an error in the most plain way possible, you can use e.g. fmt.Errorf("prefix: %w", resource.ErrNotFound)
or fmt.Errorf("%w: suffix", resource.ErrNotFound)
in hooks etc.
Should change relevant places where errors are returned to return non-pointer errors.
Actually I am using another error package for hooks: github.com/rotisserie/eris
, which can record file:location
for each error invocation/wrap, thus getting exhaustive traces for debugging.
Maybe we can still migrate rest-later
to Go 1.13 errors
, on order to propagate errors from hooks.
Hi @smyrman , sorry for the big delay. Regarding this issue, can you take a look at this patch: https://github.com/Dragomir-Ivanov/rest-layer/commit/2e9eb16c7b0b390fa41baedb3c4da03073b8ca8c
It seems to work, without introducing new types. We can change the NewError
function name if you like.
Which issue does this patch solve? It seams to return exactly the same as before, excpet that the NewError function returns two values, where one is now a generic error
type?
There is an
rest.Error
type that captures all unrecognized errors from Hooks:However sometimes, enriched errors are used(preserving call-trace), that become useless once stringed through
err.Error()
. Can we preseve original error like this:So I can use the errors in
func (r ResponseFormatter) FormatError(
and send them to say Sentry or logs.This might be a breaking change if someone is not following
go vet
recommendations(like inrest-layer
source code :)