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(err error) error
- func Details(err error) string
- func GetMaxStackDepth() int
- func HTTPCode(err error) int
- func Is(e error, originals ...error) bool
- func Location(err error) (file string, line int)
- func Message(err error) string
- func RegisterDetail(label string, key interface{})
- func RegisteredDetails(err error) map[string]interface{}
- func RootCause(err error) error
- func SetMaxStackDepth(depth int)
- func SetStackCaptureEnabled(enabled bool)
- func SetVerboseDefault(bool)
- func SourceLine(err error) string
- func Stack(err error) []uintptr
- func StackCaptureEnabled() bool
- func Stacktrace(err error) string
- func Unwrap(e error) error
- func UserMessage(err error) string
- func Value(err error, key interface{}) interface{}
- func Values(err error) map[interface{}]interface{}
- func VerboseDefault() bool
- type Error
- func Append(err error, msg string) Error
- func Appendf(err error, format string, args ...interface{}) Error
- func Errorf(format string, args ...interface{}) Error
- func Here(err error) Error
- func HereSkipping(err error, skip int) Error
- func New(msg string, wrappers ...v2.Wrapper) Error
- func Prepend(err error, msg string) Error
- func Prependf(err error, format string, args ...interface{}) Error
- func UserError(msg string) Error
- func UserErrorf(format string, args ...interface{}) Error
- func WithCause(err error, cause error) Error
- func WithHTTPCode(e error, code int) Error
- func WithMessage(err error, msg string) Error
- func WithMessagef(err error, format string, args ...interface{}) Error
- func WithUserMessage(err error, msg string) Error
- func WithUserMessagef(err error, format string, args ...interface{}) Error
- func WithValue(err error, key, value interface{}) Error
- func Wrap(err error, wrappers ...v2.Wrapper) Error
- func WrapSkipping(err error, skip int, wrappers ...v2.Wrapper) Error
Constants ¶
This section is empty.
Variables ¶
var MaxStackDepth = 50
MaxStackDepth is no longer used. It remains here for backward compatibility. deprecated: See Set/GetMaxStackDepth.
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 Details ¶
Details returns e.Error(), e's stacktrace, and any additional details which have be registered with RegisterDetail. User message and HTTP code are already registered.
The details of each error in e's cause chain will also be printed.
func GetMaxStackDepth ¶ added in v1.6.0
func GetMaxStackDepth() int
GetMaxStackDepth returns the number of frames captured in stacks.
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 is equivalent to errors.Is, but tests against multiple targets.
merry.Is(err1, err2, err3) == errors.Is(err1, err2) || errors.Is(err1, err3)
func RegisterDetail ¶ added in v1.3.0
func RegisterDetail(label string, key interface{})
RegisterDetail registers an error property key in a global registry, with a label. The registry is used by the Details() function. Registered error properties will be included in Details() output, if the value of that error property is not nil. For example:
err := New("boom") err = err.WithValue(colorKey, "red") fmt.Println(Details(err)) // Output: // boom // // <stacktrace> RegisterDetail("Color", colorKey) fmt.Println(Details(err)) // Output: // boom // Color: red // // <stacktrace>
Error property keys are typically not exported by the packages which define them. Packages instead export functions which let callers access that property. It's therefore up to the package to register those properties which would make sense to include in the Details() output. In other words, it's up to the author of the package which generates the errors to publish printable error details, not the callers of the package.
func RegisteredDetails ¶ added in v1.6.0
RegisteredDetails extracts details registered with RegisterDetailFunc from an error, and returns them as a map. Values may be nil.
If err is nil or there are no registered details, nil is returned.
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 SetMaxStackDepth ¶ added in v1.6.0
func SetMaxStackDepth(depth int)
SetMaxStackDepth sets the MaxStackDepth.
func SetStackCaptureEnabled ¶
func SetStackCaptureEnabled(enabled bool)
SetStackCaptureEnabled sets stack capturing globally. Disabling stack capture can increase performance
func SetVerboseDefault ¶
func SetVerboseDefault(bool)
SetVerboseDefault used to control the behavior of the Error() function on errors processed by this package. Error() now always just returns the error's message. This setting no longer has any effect. deprecated: To print the details of an error, use Details(err), or format the error with the verbose flag: fmt.Sprintf("%+v", err)
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. This just calls errors.Unwrap() until if finds the deepest error. It isn't very useful, and only remains for historical purposes
deprecated: use errors.Is() or errors.As() instead.
func UserMessage ¶
UserMessage returns the end-user safe message. Returns empty if not set. If e is nil, returns "".
func Value ¶
func Value(err 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(err 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 no longer has any effect. deprecated: see SetVerboseDefault
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(). args can be format args, or v2 wrappers which will be applied to the error.
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 New ¶
New creates a new error, with a stack attached. The equivalent of golang's errors.New(). Accepts v2 wrappers to apply to the error.
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 WithCause ¶ added in v1.2.0
WithCause returns an error based on the first argument, with the cause set to the second argument. If e is nil, returns nil.
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()`)