errors

package module
v0.0.0-...-fdda488 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 31, 2016 License: NCSA, MIT Imports: 10 Imported by: 1

README

merry Build Status

Make your golang errors merry, with stacktraces, inheritance, and arbitrary additional context.

The package is largely based on http://github.com/go-errors/errors, with additional inspiration from https://github.com/go-errgo/errgo and https://github.com/amattn/deeperror.

Installation

go get github.com/ansel1/merry

Features

Merry errors work a lot like google's golang.org/x/net/context package. Merry errors wrap normal errors with a context of key/value pairs. Like contexts, merry errors are immutable: adding a key/value to an error always creates a new error which wraps the original.

merry comes with built-in support for adding information to errors:

  • stacktraces
  • overriding the error message
  • HTTP status codes
  • End user error messages

You can also add your own additional information.

Details

  • New errors have a stacktrace captured where they are created

  • Add a stacktrace to existing errors (captured where they are wrapped)

    err := lib.Read()
    return merry.Wrap(err)  // no-op if err is already merry
    
  • Allow golang idiom of comparing an err value to an exported value, using Is()

    var ParseError = merry.New("Parse error")
    
    func Parse() error {
        err := ParseError.Here() // captures a stacktrace here
        merry.Is(err, ParseError)  // instead of err == ParseError
    }
    
  • Change the message on an error, while still using Is() to compare to the original error

    err := merry.WithMessage(ParseError, "Bad input")
    merry.Is(err, ParseError) // yes it is
    
  • Is() supports hierarchies of errors

    var ParseError = merry.New("Parse error")
    var InvalidCharSet = merry.WithMessage(ParseError, "Invalid char set")
    var InvalidSyntax = merry.WithMessage(ParseError, "Invalid syntax")
    
    func Parse(s string) error {
        // use chainable methods to add context
        return InvalidCharSet.Here().WithMessagef("Invalid char set: %s", "UTF-8")
        // or functions
        // return merry.WithMessagef(merry.Here(InvalidCharSet), "Invalid char set: %s", "UTF-8")
    }
    
    func Check() {
        err := Parse("fields")
        merry.Is(err, ParseError) // yup
        merry.Is(err, InvalidCharSet) // yup
        merry.Is(err, InvalidSyntax) // nope
    }
    
  • Add an HTTP status code

    merry.HTTPCode(errors.New("regular error")) // 500
    merry.HTTPCode(merry.New("merry error").WithHTTPCode(404)) // 404
    
  • Set an alternate error message for end users

    e := merry.New("crash").WithUserMessage("nothing to see here")
    merry.UserMessage(e)  // returns "nothing to see here"
    
  • Functions for printing error details

    err := merry.New("boom")
    m := merry.Stacktrace(err) // just the stacktrace
    m = merry.Details(err) // error message and stacktrace
    
  • Add you're own context info

    err := merry.New("boom").WithValue("explosive", "black powder")
    

Basic Usage

The package contains functions for creating new errors with stacks, or adding a stack to error instances. Functions with add context (e.g. WithValue()) work on any error, and will automatically convert them to merry errors (with a stack) if necessary.

Functions which get context values from errors also accept error, and will return default values if the error is not merry, or doesn't have that key attached.

All the functions which create or attach context return concrete instances of *Error. *Error implements methods to add context to the error (they mirror the functions and do the same thing). They allow for a chainable syntax for adding context.

Example:

package main

import (
    "github.com/ansel1/merry"
    "errors"
)

var InvalidInputs = errors.New("Input is invalid")

func main() {
    // create a new error, with a stacktrace attached
    err := merry.New("bad stuff happened")
    
    // create a new error with format string, like fmt.Errorf
    err = merry.Errorf("bad input: %v", os.Args)
    
    // capture a fresh stacktrace from this callsite
    err = merry.Here(InvalidInputs)
    
    // Make err merry if it wasn't already.  The stacktrace will be captured here if the
    // error didn't already have one.  Also useful to cast to *Error 
    err = merry.Wrap(err, 0)

    // override the original error's message
    err.WithMessagef("Input is invalid: %v", os.Args)
    
    // Use Is to compare errors against values, which is a common golang idiom
    merry.Is(err, InvalidInputs) // will be true
    
    // associated an http code
    err.WithHTTPCode(400)
    
    perr := parser.Parse("blah")
    err = Wrap(perr, 0)
    // Get the original error back
    merry.Unwrap(err) == perr  // will be true
    
    // Print the error to a string, with the stacktrace, if it has one
    s := merry.Details(err)
    
    // Just print the stacktrace (empty string if err is not a RichError)
    s := merry.Stacktrace(err)

    // Get the location of the error (the first line in the stacktrace)
    file, line := merry.Location(err)
    
    // Get an HTTP status code for an error.  Defaults to 500.
    code := merry.HTTPCode(err)
    
}

See inline docs for more details.

License

This package is licensed under the MIT license, see LICENSE.MIT for details.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var MaxStackDepth = 50

The maximum number of stackframes on any error.

Functions

func Details

func Details(e error) string

Returns e.Error() and e's stacktrace and user message, if set.

func HTTPCode

func HTTPCode(e error) int

Convert an error to an http status code. All errors map to 500, unless the error has an http code attached.

func Is

func Is(e error, originals ...error) bool

Check whether e is equal to or wraps the original, at any depth

func Location

func Location(e error) (file string, line int)

Returns zero values if e has no stacktrace

func Marshal

func Marshal(err error) ([]byte, error)

func SourceLine

func SourceLine(e error) string

SourceLine returns the string representation of Location's result or an empty string if there's no stracktrace.

func Stack

func Stack(e error) []uintptr

Return the stack attached to an error, or nil if one is not attached

func Stacktrace

func Stacktrace(e error) string

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 ToModel

func ToModel(err error) *models.Error

func Unwrap

func Unwrap(e error) error

Return 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.

func UserMessage

func UserMessage(e error) string

Return the end-user safe message. Returns empty if not set

func Value

func Value(e error, key interface{}) interface{}

Return the value for key, or nil if not set

func Values

func Values(e error) map[interface{}]interface{}

Return 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

Types

type Err

type Err struct {
	Err   error       `json:"error"`
	Key   interface{} `json:"key"`
	Value interface{} `json:"value"`
}

func (*Err) Append

func (e *Err) Append(msg string) Error

Append a message after the current error message, in the format "original: new"

func (*Err) Appendf

func (e *Err) Appendf(format string, args ...interface{}) Error

Append a message after the current error message, in the format "original: new"

func (*Err) Error

func (e *Err) Error() string

implements golang's error interface returns the message value if set, otherwise delegates to inner error

func (*Err) Here

func (e *Err) Here() Error

Shorthand for capturing a new stack trace

func (*Err) Marshal

func (e *Err) Marshal() ([]byte, error)

Returns e.Error() and e's stacktrace and user message, if set.

func (*Err) Prepend

func (e *Err) Prepend(msg string) Error

Prepend a message after the current error message, in the format "new: original"

func (*Err) Prependf

func (e *Err) Prependf(format string, args ...interface{}) Error

Prepend a message after the current error message, in the format "new: original"

func (*Err) WithField

func (e *Err) WithField(key, value interface{}) Error

return a new error with additional context

func (*Err) WithHTTPCode

func (e *Err) WithHTTPCode(code int) Error

return a new error with an http status code attached

func (*Err) WithMessage

func (e *Err) WithMessage(msg string) Error

return a new error with a new message

func (*Err) WithMessagef

func (e *Err) WithMessagef(format string, a ...interface{}) Error

return a new error with a new formatted message

func (*Err) WithStackSkipping

func (e *Err) WithStackSkipping(skip int) Error

return a new error with a new stack capture

func (*Err) WithUserMessage

func (e *Err) WithUserMessage(msg string) Error

Add a message which is suitable for end users to see

func (*Err) WithUserMessagef

func (e *Err) WithUserMessagef(format string, args ...interface{}) Error

Add a message which is suitable for end users to see

func (*Err) WithValue

func (e *Err) WithValue(key, value interface{}) Error

return a new error with additional context

func (*Err) Wrap

func (e *Err) Wrap(err error) Error

Shorthand for capturing a new stack trace

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
	WithField(key, value interface{}) Error
	Here() Error
	Wrap(error) Error
	WithStackSkipping(skip int) Error
	WithHTTPCode(code int) Error
}

func Append

func Append(e error, msg string) Error

Append a message after the current error message, in the format "original: new"

func Appendf

func Appendf(e error, format string, args ...interface{}) Error

Append a message after the current error message, in the format "original: new"

func Errorf

func Errorf(format string, a ...interface{}) Error

Create a new error with a formatted message and a stack. The equivalent of golang's fmt.Errorf()

func Here

func Here(e error) Error

Attach a new stack to the error, at the call site of Here(). Useful when returning copies of exported package errors

func New

func New(cat string, msgi ...interface{}) Error

Create a new error, with a stack attached. The equivalent of golang's errors.New()

func Prepend

func Prepend(e error, msg string) Error

Prepend a message after the current error message, in the format "new: original"

func Prependf

func Prependf(e error, format string, args ...interface{}) Error

Prepend a message after the current error message, in the format "new: original"

func WithField

func WithField(e error, key, value interface{}) Error

Add a context an error. If the key was already set on e, the new value will take precedence.

func WithHTTPCode

func WithHTTPCode(e error, code int) Error

Return an error with an http code attached.

func WithMessage

func WithMessage(e error, msg string) Error

Override the message of error. The resulting error's Error() method will return the new message

func WithMessagef

func WithMessagef(e error, format string, a ...interface{}) Error

Same as WithMessage(), using fmt.Sprint()

func WithUserMessage

func WithUserMessage(e error, msg string) Error

Add a message which is suitable for end users to see

func WithUserMessagef

func WithUserMessagef(e error, format string, args ...interface{}) Error

Add a message which is suitable for end users to see

func WithValue

func WithValue(e error, key, value interface{}) Error

Add a context an error. If the key was already set on e, the new value will take precedence.

func Wrap

func Wrap(e error) Error

Cast e to *Error, or wrap e in a new *Error with stack

func WrapSkipping

func WrapSkipping(e error, skip int) Error

Cast e to *Error, or wrap e in a new *Error with stack Skip `skip` frames (0 is the call site of `WrapSkipping()`)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL