Documentation
¶
Overview ¶
Package merry provides enriched golang errors, with stacktraces
merry creates errors with stacktraces, and can augment those errors with additional information.
When you create a new merry error, or wrap an existing error in a merry error, merry attaches a stacktrace to the error:
err := merry.New("an error occurred")
err has a stacktrace attached. Alternately, you can wrap existing errors. merry will attach a stacktrace at the point of wrapping:
_, err := ioutil.ReadAll(r)
if err != nil {
return merry.Wrap(err)
}
Capturing the stack can be globally disabled with `SetStackCaptureEnabled(false)`. Wrapping is idempotent: Wrap will only attach a stacktrace if the error doesn't already have one.
Wrap() is the simplest way to attach a stacktrace to an error, but other functions can be used instead, with both add a stacktrace, and augment or modify the error. For example, Prepend() modifies the error's message (and also attaches a stacktrace):
_, err := ioutil.ReadAll(r)
if err != nil {
return merry.Prepend(err, "reading from conn failed")
// err.Error() would read something like "reading from conn failed: timeout"
}
See the other package functions for other ways to augment or modify errors, such as Append, WithUserMessage, WithHTTPCode, WithValue, etc. These functions all return a merry.Error interface, which has methods which mirror the package level functions, to allow simple chaining:
return merry.New("object not found").WithHTTPCode(404)
Here ¶
Wrap will not take a new stacktrace if an error already has one attached. Here will create a new error which replaces the stacktrace with a new one:
var ErrOverflow = merry.New("overflowed")
func Read() error {
// ...
return merry.Here(ErrOverflow)
}
Is ¶
The go idiom of exporting package-level error variables for comparison to errors returned by the package is broken by merry. For example:
_, err := io.ReadAll(r)
if err == io.EOF {
// ...
}
If the error returned was a merry error, the equality comparison would always fail, because merry augments errors by wrapping them in layers. To compensate for this, merry has the Is() function.
if merry.Is(err, io.EOF) {
Is() will unwrap the err and compare each layer to the second argument.
Cause ¶
You can add a cause to an error:
if err == io.EOF {
err = merry.New("reading failed"), err)
fmt.Println(err.Error()) // reading failed: EOF
}
Cause(error) will return the cause of the argument. RootCause(error) returns the innermost cause. Is(err1, err2) is cause aware, and will return true if err2 is a cause (anywhere in the causal change) of err1.
Formatting and printing ¶
To obtain an error's stacktrace, call Stack(). To get other information about the site of the error, or print the error's stacktrace, see Location(), SourceLine(), Stacktrace(), and Details().
merry errors also implement the fmt.Formatter interface. errors support the following fmt flags:
%+v print the equivalent of Details(err), which includes the user message, full stacktrace,
and recursively prints the details of the cause chain.
Index ¶
- Variables
- func Cause(e error) error
- func Details(e error) string
- func HTTPCode(e error) int
- func Is(e error, originals ...error) bool
- func Location(e error) (file string, line int)
- func Message(e error) string
- func RootCause(e error) error
- func SetStackCaptureEnabled(enabled bool)
- func SetVerboseDefault(b bool)
- func SourceLine(e error) string
- func Stack(e error) []uintptr
- func StackCaptureEnabled() bool
- func Stacktrace(e error) string
- func Unwrap(e error) error
- func UserMessage(e error) string
- func Value(e error, key interface{}) interface{}
- func Values(e error) map[interface{}]interface{}
- func VerboseDefault() bool
- func WithCause(e error, cause error) error
- type Error
- func Append(e error, msg string) Error
- func Appendf(e error, format string, args ...interface{}) Error
- func Errorf(format string, a ...interface{}) Error
- func Here(e error) Error
- func HereSkipping(e error, skip int) Error
- func New(msg string) Error
- func Prepend(e error, msg string) Error
- func Prependf(e error, format string, args ...interface{}) Error
- func UserError(msg string) Error
- func UserErrorf(format string, a ...interface{}) Error
- func WithHTTPCode(e error, code int) Error
- func WithMessage(e error, msg string) Error
- func WithMessagef(e error, format string, a ...interface{}) Error
- func WithUserMessage(e error, msg string) Error
- func WithUserMessagef(e error, format string, args ...interface{}) Error
- func WithValue(e error, key, value interface{}) Error
- func Wrap(e error) Error
- func WrapSkipping(e error, skip int) Error
Constants ¶
This section is empty.
Variables ¶
var MaxStackDepth = 50
MaxStackDepth is the maximum number of stackframes on any error.
Functions ¶
func Cause ¶ added in v1.2.0
Cause returns the cause of the argument. If e is nil, or has no cause, nil is returned.
func HTTPCode ¶
HTTPCode converts an error to an http status code. All errors map to 500, unless the error has an http code attached. If e is nil, returns 200.
func Is ¶
Is checks whether e is equal to or wraps the original, at any depth. If e == nil, return false. This is useful if your package uses the common golang pattern of exported error constants. If your package exports an ErrEOF constant, which is initialized like this:
var ErrEOF = errors.New("End of file error")
...and your user wants to compare an error returned by your package with ErrEOF:
err := urpack.Read()
if err == urpack.ErrEOF {
...the comparison will fail if the error has been wrapped by merry at some point. Replace the comparison with:
if merry.Is(err, urpack.ErrEOF) {
Causes ¶
Is will also return true if any of the originals is in the cause chain of e. For example:
e1 := merry.New("base error")
e2 := merry.New("library error")
// e2 was caused by e1
e3 := merry.WithCause(e1, e2)
merry.Is(e3, e2) // yes it is, because e3 is based on e2
merry.Is(e3, e1) // yes it is, because e1 was a cause of e3
func Message ¶
Message returns just the error message. It is equivalent to Error() when Verbose is false. The behavior of Error() is (pseudo-code):
if verbose Details(e) else Message(e) || UserMessage(e)
If e is nil, returns "".
func RootCause ¶ added in v1.2.0
RootCause returns the innermost cause of the argument (i.e. the last error in the cause chain)
func SetStackCaptureEnabled ¶
func SetStackCaptureEnabled(enabled bool)
SetStackCaptureEnabled sets stack capturing globally. Disabling stack capture can increase performance
func SetVerboseDefault ¶
func SetVerboseDefault(b bool)
SetVerboseDefault sets the global default for verbose mode. When true, e.Error() == Details(e) When false, e.Error() == Message(e)
func SourceLine ¶
SourceLine returns the string representation of Location's result or an empty string if there's no stracktrace.
func Stack ¶
Stack returns the stack attached to an error, or nil if one is not attached If e is nil, returns nil.
func StackCaptureEnabled ¶
func StackCaptureEnabled() bool
StackCaptureEnabled returns whether stack capturing is enabled
func Stacktrace ¶
Stacktrace returns the error's stacktrace as a string formatted the same way as golangs runtime package. If e has no stacktrace, returns an empty string.
func Unwrap ¶
Unwrap returns the innermost underlying error. Only useful in advanced cases, like if you need to cast the underlying error to some type to get additional information from it. If e == nil, return nil.
func UserMessage ¶
UserMessage returns the end-user safe message. Returns empty if not set. If e is nil, returns "".
func Value ¶
func Value(e error, key interface{}) interface{}
Value returns the value for key, or nil if not set. If e is nil, returns nil.
func Values ¶
func Values(e error) map[interface{}]interface{}
Values returns a map of all values attached to the error If a key has been attached multiple times, the map will contain the last value mapped If e is nil, returns nil.
func VerboseDefault ¶
func VerboseDefault() bool
VerboseDefault returns the global default for verbose mode. When true, e.Error() == Details(e) When false, e.Error() == Message(e)
Types ¶
type Error ¶
type Error interface {
error
Appendf(format string, args ...interface{}) Error
Append(msg string) Error
Prepend(msg string) Error
Prependf(format string, args ...interface{}) Error
WithMessage(msg string) Error
WithMessagef(format string, args ...interface{}) Error
WithUserMessage(msg string) Error
WithUserMessagef(format string, args ...interface{}) Error
WithValue(key, value interface{}) Error
Here() Error
WithStackSkipping(skip int) Error
WithHTTPCode(code int) Error
WithCause(err error) Error
Cause() error
fmt.Formatter
}
Error extends the standard golang `error` interface with functions for attachment additional data to the error
func Append ¶
Append a message after the current error message, in the format "original: new". If e == nil, return nil.
func Errorf ¶
Errorf creates a new error with a formatted message and a stack. The equivalent of golang's fmt.Errorf()
func Here ¶
Here returns an error with a new stacktrace, at the call site of Here(). Useful when returning copies of exported package errors. If e is nil, returns nil.
func HereSkipping ¶ added in v1.1.0
HereSkipping returns an error with a new stacktrace, at the call site of HereSkipping() - skip frames.
func Prepend ¶
Prepend a message before the current error message, in the format "new: original". If e == nil, return nil.
func UserErrorf ¶
UserErrorf is like UserError, but uses fmt.Sprintf()
func WithHTTPCode ¶
WithHTTPCode returns an error with an http code attached. If e is nil, returns nil.
func WithMessage ¶
WithMessage returns an error with a new message. The resulting error's Error() method will return the new message. If e is nil, returns nil.
func WithMessagef ¶
WithMessagef is the same as WithMessage(), using fmt.Sprintf().
func WithUserMessage ¶
WithUserMessage adds a message which is suitable for end users to see. If e is nil, returns nil.
func WithUserMessagef ¶
WithUserMessagef is the same as WithMessage(), using fmt.Sprintf()
func WithValue ¶
WithValue adds a context an error. If the key was already set on e, the new value will take precedence. If e is nil, returns nil.
func Wrap ¶
Wrap turns the argument into a merry.Error. If the argument already is a merry.Error, this is a no-op. If e == nil, return nil
func WrapSkipping ¶
WrapSkipping turns the error arg into a merry.Error if the arg is not already a merry.Error. If e is nil, return nil. If a merry.Error is created by this call, the stack captured will skip `skip` frames (0 is the call site of `WrapSkipping()`)
