eris

package module
v0.5.4 Latest Latest
Warning

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

Go to latest
Published: Apr 27, 2022 License: MIT Imports: 5 Imported by: 654

README

GoDoc Build GoReport Coverage Status

Package eris is an error handling library with readable stack traces and JSON formatting support.

go get github.com/rotisserie/eris

Why you should switch to eris

This package was inspired by a simple question: what if you could fix a bug without wasting time replicating the issue or digging through the code? With that in mind, this package is designed to give you more control over error handling via error wrapping, stack tracing, and output formatting.

The example that generated the output below simulates a realistic error handling scenario and demonstrates how to wrap and log errors with minimal effort. This specific error occurred because a user tried to access a file that can't be located, and the output shows a clear path from the top of the call stack to the source.

{
  "error":{
    "root":{
      "message":"error internal server",
      "stack":[
        "main.main:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:143",
        "main.ProcessResource:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:85",
        "main.ProcessResource:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:82",
        "main.GetRelPath:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:61"
      ]
    },
    "wrap":[
      {
        "message":"failed to get relative path for resource 'res2'",
        "stack":"main.ProcessResource:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:85"
      },
      {
        "message":"Rel: can't make ./some/malformed/absolute/path/data.json relative to /Users/roti/",
        "stack":"main.GetRelPath:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:61"
      }
    ]
  },
  "level":"error",
  "method":"ProcessResource",
  "msg":"method completed with error",
  "time":"2020-01-16T11:20:01-05:00"
}

Many of the methods in this package will look familiar if you've used pkg/errors or xerrors, but eris employs some additional tricks during error wrapping and unwrapping that greatly improve the readability of the stack trace. This package also takes a unique approach to formatting errors that allows you to write custom formats that conform to your error or log aggregator of choice. You can find more information on the differences between eris and pkg/errors here.

Using eris

Creating errors

Creating errors is simple via eris.New.

var (
  // global error values can be useful when wrapping errors or inspecting error types
  ErrInternalServer = eris.New("error internal server")
)

func (req *Request) Validate() error {
  if req.ID == "" {
    // or return a new error at the source if you prefer
    return eris.New("error bad request")
  }
  return nil
}
Wrapping errors

eris.Wrap adds context to an error while preserving the original error.

relPath, err := GetRelPath("/Users/roti/", resource.AbsPath)
if err != nil {
  // wrap the error if you want to add more context
  return nil, eris.Wrapf(err, "failed to get relative path for resource '%v'", resource.ID)
}
Formatting and logging errors

eris.ToString and eris.ToJSON should be used to log errors with the default format (shown above). The JSON method returns a map[string]interface{} type for compatibility with Go's encoding/json package and many common JSON loggers (e.g. logrus).

// format the error to JSON with the default format and stack traces enabled
formattedJSON := eris.ToJSON(err, true)
fmt.Println(json.Marshal(formattedJSON)) // marshal to JSON and print
logger.WithField("error", formattedJSON).Error() // or ideally, pass it directly to a logger

// format the error to a string and print it
formattedStr := eris.ToString(err, true)
fmt.Println(formattedStr)

eris also enables control over the default format's separators and allows advanced users to write their own custom output format.

Interpreting eris stack traces

Errors created with this package contain stack traces that are managed automatically. They're currently mandatory when creating and wrapping errors but optional when printing or logging. By default, the stack trace and all wrapped layers follow the opposite order of Go's runtime package, which means that the original calling method is shown first and the root cause of the error is shown last.

{
  "root":{
    "message":"error bad request", // root cause
    "stack":[
      "main.main:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:143", // original calling method
      "main.ProcessResource:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:71",
      "main.(*Request).Validate:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:29", // location of Wrap call
      "main.(*Request).Validate:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:28" // location of the root
    ]
  },
  "wrap":[
    {
      "message":"received a request with no ID", // additional context
      "stack":"main.(*Request).Validate:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:29" // location of Wrap call
    }
  ]
}
Inverting the stack trace and error output

If you prefer some other order than the default, eris supports inverting both the stack trace and the entire error output. When both are inverted, the root error is shown first and the original calling method is shown last.

// create a default format with error and stack inversion options
format := eris.NewDefaultStringFormat(eris.FormatOptions{
  InvertOutput: true, // flag that inverts the error output (wrap errors shown first)
  WithTrace: true,    // flag that enables stack trace output
  InvertTrace: true,  // flag that inverts the stack trace output (top of call stack shown first)
})

// format the error to a string and print it
formattedStr := eris.ToCustomString(err, format)
fmt.Println(formattedStr)

// example output:
// error not found
//   main.GetResource:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:52
//   main.ProcessResource:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:76
//   main.main:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:143
// failed to get resource 'res1'
//   main.GetResource:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:52
Inspecting errors

The eris package provides a couple ways to inspect and compare error types. eris.Is returns true if a particular error appears anywhere in the error chain. Currently, it works simply by comparing error messages with each other. If an error contains a particular message (e.g. "error not found") anywhere in its chain, it's defined to be that error type.

ErrNotFound := eris.New("error not found")
_, err := db.Get(id)
// check if the resource was not found
if eris.Is(err, ErrNotFound) {
  // return the error with some useful context
  return eris.Wrapf(err, "error getting resource '%v'", id)
}

eris.As finds the first error in a chain that matches a given target. If there's a match, it sets the target to that error value and returns true.

var target *NotFoundError
_, err := db.Get(id)
// check if the error is a NotFoundError type
if errors.As(err, &target) {
    // err is a *NotFoundError and target is set to the error's value
    return target
}

eris.Cause unwraps an error until it reaches the cause, which is defined as the first (i.e. root) error in the chain.

ErrNotFound := eris.New("error not found")
_, err := db.Get(id)
// compare the cause to some sentinel value
if eris.Cause(err) == ErrNotFound {
  // return the error with some useful context
  return eris.Wrapf(err, "error getting resource '%v'", id)
}
Formatting with custom separators

For users who need more control over the error output, eris allows for some control over the separators between each piece of the output via the eris.Format type. If this isn't flexible enough for your needs, see the custom output format section below. To format errors with custom separators, you can define and pass a format object to eris.ToCustomString or eris.ToCustomJSON.

// format the error to a string with custom separators
formattedStr := eris.ToCustomString(err, Format{
  FormatOptions: eris.FormatOptions{
    WithTrace: true,   // flag that enables stack trace output
  },
  MsgStackSep: "\n",   // separator between error messages and stack frame data
  PreStackSep: "\t",   // separator at the beginning of each stack frame
  StackElemSep: " | ", // separator between elements of each stack frame
  ErrorSep: "\n",      // separator between each error in the chain
})
fmt.Println(formattedStr)

// example output:
// error reading file 'example.json'
//   main.readFile | .../example/main.go | 6
// unexpected EOF
//   main.main | .../example/main.go | 20
//   main.parseFile | .../example/main.go | 12
//   main.readFile | .../example/main.go | 6
Writing a custom output format

eris also allows advanced users to construct custom error strings or objects in case the default error doesn't fit their requirements. The UnpackedError object provides a convenient and developer friendly way to store and access existing error traces. The ErrRoot and ErrChain fields correspond to the root error and wrap error chain, respectively. If a root error wraps an external error, that error will be default formatted and assigned to the ErrExternal field. If any other error type is unpacked, it will appear in the ErrExternal field. You can access all of the information contained in an error via eris.Unpack.

// get the unpacked error object
uErr := eris.Unpack(err)
// send only the root error message to a logging server instead of the complete error trace
sentry.CaptureMessage(uErr.ErrRoot.Msg)
Sending error traces to Sentry

eris supports sending your error traces to Sentry using the Sentry Go client SDK. You can run the example that generated the following output on Sentry UI using the command go run examples/sentry/example.go -dsn=<DSN>.

*eris.wrapError: test: wrap 1: wrap 2: wrap 3
  File "main.go", line 19, in Example
    return eris.New("test")
  File "main.go", line 23, in WrapExample
    err := Example()
  File "main.go", line 25, in WrapExample
    return eris.Wrap(err, "wrap 1")
  File "main.go", line 31, in WrapSecondExample
    err := WrapExample()
  File "main.go", line 33, in WrapSecondExample
    return eris.Wrap(err, "wrap 2")
  File "main.go", line 44, in main
    err := WrapSecondExample()
  File "main.go", line 45, in main
    err = eris.Wrap(err, "wrap 3")

Comparison to other packages (e.g. pkg/errors)

Error formatting and stack traces

Readability is a major design requirement for eris. In addition to the JSON output shown above, eris also supports formatting errors to a simple string.

failed to get resource 'res1'
  main.GetResource:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:52
error not found
  main.main:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:143
  main.ProcessResource:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:76
  main.GetResource:/Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:52

The eris error stack is designed to be easier to interpret than other error handling packages, and it achieves this by omitting extraneous information and avoiding unnecessary repetition. The stack trace above omits calls from Go's runtime package and includes just a single frame for wrapped layers which are inserted into the root error stack trace in the correct order. eris also correctly handles and updates stack traces for global error values in a transparent way.

The output of pkg/errors for the same error is shown below. In this case, the root error stack trace is incorrect because it was declared as a global value, and it includes several extraneous lines from the runtime package. The output is also much more difficult to read and does not allow for custom formatting.

error not found
main.init
  /Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:18
runtime.doInit
  /usr/local/Cellar/go/1.13.6/libexec/src/runtime/proc.go:5222
runtime.main
  /usr/local/Cellar/go/1.13.6/libexec/src/runtime/proc.go:190
runtime.goexit
  /usr/local/Cellar/go/1.13.6/libexec/src/runtime/asm_amd64.s:1357
failed to get resource 'res1'
main.GetResource
  /Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:52
main.ProcessResource
  /Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:76
main.main
  /Users/roti/go/src/github.com/rotisserie/eris/examples/logging/example.go:143
runtime.main
  /usr/local/Cellar/go/1.13.6/libexec/src/runtime/proc.go:203
runtime.goexit
  /usr/local/Cellar/go/1.13.6/libexec/src/runtime/asm_amd64.s:1357

Migrating to eris

Migrating to eris should be a very simple process. If it doesn't offer something that you currently use from existing error packages, feel free to submit an issue to us. If you don't want to refactor all of your error handling yet, eris should work relatively seamlessly with your existing error types. Please submit an issue if this isn't the case for some reason.

Many of your dependencies will likely still use pkg/errors for error handling. When external error types are wrapped with additional context, eris creates a new root error that wraps the original external error. Because of this, error inspection should work seamlessly with other error libraries.

Contributing

If you'd like to contribute to eris, we'd love your input! Please submit an issue first so we can discuss your proposal.


Released under the MIT License.

Documentation

Overview

Package eris provides a better way to handle, trace, and log errors in Go.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func As added in v0.5.0

func As(err error, target interface{}) bool

As finds the first error in err's chain that matches target. If there's a match, it sets target to that error value and returns true. Otherwise, it returns false.

The chain consists of err itself followed by the sequence of errors obtained by repeatedly calling Unwrap.

An error matches target if the error's concrete value is assignable to the value pointed to by target, or if the error has a method As(interface{}) bool such that As(target) returns true.

func Cause

func Cause(err error) error

Cause returns the root cause of the error, which is defined as the first error in the chain. The original error is returned if it does not implement `Unwrap() error` and nil is returned if the error is nil.

func Errorf

func Errorf(format string, args ...interface{}) error

Errorf creates a new root error with a formatted message.

func Is

func Is(err, target error) bool

Is reports whether any error in err's chain matches target.

The chain consists of err itself followed by the sequence of errors obtained by repeatedly calling Unwrap.

An error is considered to match a target if it is equal to that target or if it implements a method Is(error) bool such that Is(target) returns true.

func New

func New(msg string) error

New creates a new root error with a static message.

func StackFrames added in v0.2.0

func StackFrames(err error) []uintptr

StackFrames returns the trace of an error in the form of a program counter slice. Use this method if you want to pass the eris stack trace to some other error tracing library.

func ToCustomJSON added in v0.2.0

func ToCustomJSON(err error, format JSONFormat) map[string]interface{}

ToCustomJSON returns a JSON formatted map for a given error.

To declare custom format, the Format object has to be passed as an argument. An error without trace will be formatted as follows:

{
  "root": {
    "message": "Root error msg",
  },
  "wrap": [
    {
      "message": "Wrap error msg'",
    }
  ]
}

An error with trace will be formatted as follows:

{
  "root": {
    "message": "Root error msg",
    "stack": [
      "<Method2>[Format.StackElemSep]<File2>[Format.StackElemSep]<Line2>",
      "<Method1>[Format.StackElemSep]<File1>[Format.StackElemSep]<Line1>"
    ]
  }
  "wrap": [
    {
      "message": "Wrap error msg",
      "stack": "<Method2>[Format.StackElemSep]<File2>[Format.StackElemSep]<Line2>"
    }
  ]
}

func ToCustomString added in v0.2.0

func ToCustomString(err error, format StringFormat) string

ToCustomString returns a custom formatted string for a given error.

To declare custom format, the Format object has to be passed as an argument. An error without trace will be formatted as follows:

<Wrap error msg>[Format.ErrorSep]<Root error msg>

An error with trace will be formatted as follows:

<Wrap error msg>[Format.MsgStackSep]
[Format.PreStackSep]<Method2>[Format.StackElemSep]<File2>[Format.StackElemSep]<Line2>[Format.ErrorSep]
<Root error msg>[Format.MsgStackSep]
[Format.PreStackSep]<Method2>[Format.StackElemSep]<File2>[Format.StackElemSep]<Line2>[Format.ErrorSep]
[Format.PreStackSep]<Method1>[Format.StackElemSep]<File1>[Format.StackElemSep]<Line1>[Format.ErrorSep]

func ToJSON added in v0.2.0

func ToJSON(err error, withTrace bool) map[string]interface{}

ToJSON returns a JSON formatted map for a given error.

An error without trace will be formatted as follows:

{
  "root": [
    {
      "message": "Root error msg"
    }
  ],
  "wrap": {
    "message": "Wrap error msg"
  }
}

An error with trace will be formatted as follows:

{
  "root": [
    {
      "message": "Root error msg",
      "stack": [
        "<Method2>:<File2>:<Line2>",
        "<Method1>:<File1>:<Line1>"
      ]
    }
  ],
  "wrap": {
    "message": "Wrap error msg",
    "stack": "<Method2>:<File2>:<Line2>"
  }
}
Example (External)

Demonstrates JSON formatting of wrapped errors that originate from external (non-eris) error types.

package main

import (
	"encoding/json"
	"fmt"
	"io"

	"github.com/rotisserie/eris"
)

func main() {
	// example func that returns an IO error
	readFile := func(fname string) error {
		return io.ErrUnexpectedEOF
	}

	// unpack and print the error
	err := readFile("example.json")
	u, _ := json.Marshal(eris.ToJSON(err, false)) // false: omit stack trace
	fmt.Println(string(u))

	// example output:
	// {
	//   "external":"unexpected EOF"
	// }
}
Output:

Example (Global)

Demonstrates JSON formatting of wrapped errors that originate from global root errors.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/rotisserie/eris"
)

var ErrUnexpectedEOF = eris.New("unexpected EOF")

func main() {
	// example func that wraps a global error value
	readFile := func(fname string) error {
		return eris.Wrapf(ErrUnexpectedEOF, "error reading file '%v'", fname) // line 6
	}

	// example func that catches and returns an error without modification
	parseFile := func(fname string) error {
		// read the file
		err := readFile(fname) // line 12
		if err != nil {
			return err
		}
		return nil
	}

	// unpack and print the error via uerr.ToJSON(...)
	err := parseFile("example.json")                             // line 20
	u, _ := json.MarshalIndent(eris.ToJSON(err, true), "", "\t") // true: include stack trace
	fmt.Printf("%v\n", string(u))

	// example output:
	// {
	//   "root": {
	//     "message": "unexpected EOF",
	//     "stack": [
	//       "main.main:.../example/main.go:20",
	//       "main.parseFile:.../example/main.go:12",
	//       "main.readFile:.../example/main.go:6"
	//     ]
	//   },
	//   "wrap": [
	//     {
	//       "message": "error reading file 'example.json'",
	//       "stack": "main.readFile:.../example/main.go:6"
	//     }
	//   ]
	// }
}
Output:

Example (Local)

Demonstrates JSON formatting of wrapped errors that originate from local root errors (created at the source of the error via eris.New).

package main

import (
	"encoding/json"
	"fmt"

	"github.com/rotisserie/eris"
)

func main() {
	// example func that returns an eris error
	readFile := func(fname string) error {
		return eris.New("unexpected EOF") // line 3
	}

	// example func that catches an error and wraps it with additional context
	parseFile := func(fname string) error {
		// read the file
		err := readFile(fname) // line 9
		if err != nil {
			return eris.Wrapf(err, "error reading file '%v'", fname) // line 11
		}
		return nil
	}

	// example func that just catches and returns an error
	processFile := func(fname string) error {
		// parse the file
		err := parseFile(fname) // line 19
		if err != nil {
			return err
		}
		return nil
	}

	// another example func that catches and wraps an error
	printFile := func(fname string) error {
		// process the file
		err := processFile(fname) // line 29
		if err != nil {
			return eris.Wrapf(err, "error printing file '%v'", fname) // line 31
		}
		return nil
	}

	// unpack and print the raw error
	err := printFile("example.json") // line 37
	u, _ := json.MarshalIndent(eris.ToJSON(err, true), "", "\t")
	fmt.Printf("%v\n", string(u))

	// example output:
	// {
	//   "root": {
	//     "message": "unexpected EOF",
	//     "stack": [
	//       "main.main:.../example/main.go:37",
	//       "main.printFile:.../example/main.go:31",
	//       "main.printFile:.../example/main.go:29",
	//       "main.processFile:.../example/main.go:19",
	//       "main.parseFile:.../example/main.go:11",
	//       "main.parseFile:.../example/main.go:9",
	//       "main.readFile:.../example/main.go:3"
	//     ]
	//   },
	//   "wrap": [
	//     {
	//       "message": "error printing file 'example.json'",
	//       "stack": "main.printFile:.../example/main.go:31"
	//     },
	//     {
	//       "message": "error reading file 'example.json'",
	//       "stack": "main.parseFile: .../example/main.go: 11"
	//     }
	//   ]
	// }
}
Output:

func ToString added in v0.2.0

func ToString(err error, withTrace bool) string

ToString returns a default formatted string for a given error.

An error without trace will be formatted as follows:

<Wrap error msg>: <Root error msg>

An error with trace will be formatted as follows:

<Wrap error msg>
  <Method2>:<File2>:<Line2>
<Root error msg>
  <Method2>:<File2>:<Line2>
  <Method1>:<File1>:<Line1>
Example (External)

Demonstrates string formatting of wrapped errors that originate from external (non-eris) error types.

package main

import (
	"fmt"
	"io"

	"github.com/rotisserie/eris"
)

func main() {
	// example func that returns an IO error
	readFile := func(fname string) error {
		return io.ErrUnexpectedEOF
	}

	// unpack and print the error
	err := readFile("example.json")
	fmt.Println(eris.ToString(err, false)) // false: omit stack trace

	// example output:
	// unexpected EOF
}
Output:

Example (Global)

Demonstrates string formatting of wrapped errors that originate from global root errors.

package main

import (
	"fmt"

	"github.com/rotisserie/eris"
)

var FormattedErrUnexpectedEOF = eris.Errorf("unexpected %v", "EOF")

func main() {
	// example func that wraps a global error value
	readFile := func(fname string) error {
		return eris.Wrapf(FormattedErrUnexpectedEOF, "error reading file '%v'", fname) // line 6
	}

	// example func that catches and returns an error without modification
	parseFile := func(fname string) error {
		// read the file
		err := readFile(fname) // line 12
		if err != nil {
			return err
		}
		return nil
	}

	// example func that just catches and returns an error
	processFile := func(fname string) error {
		// parse the file
		err := parseFile(fname) // line 22
		if err != nil {
			return eris.Wrapf(err, "error processing file '%v'", fname) // line 24
		}
		return nil
	}

	// call processFile and catch the error
	err := processFile("example.json") // line 30

	// print the error via fmt.Printf
	fmt.Printf("%v\n", err) // %v: omit stack trace

	// example output:
	// unexpected EOF: error reading file 'example.json'

	// unpack and print the error via uerr.ToString(...)
	fmt.Printf("%v\n", eris.ToString(err, true)) // true: include stack trace

	// example output:
	// error reading file 'example.json'
	//   main.readFile:.../example/main.go:6
	// unexpected EOF
	//   main.main:.../example/main.go:30
	//   main.processFile:.../example/main.go:24
	//   main.processFile:.../example/main.go:22
	//   main.parseFile:.../example/main.go:12
	//   main.readFile:.../example/main.go:6
}
Output:

Example (Local)

Demonstrates string formatting of wrapped errors that originate from local root errors (created at the source of the error via eris.New).

package main

import (
	"fmt"

	"github.com/rotisserie/eris"
)

func main() {
	// example func that returns an eris error
	readFile := func(fname string) error {
		return eris.New("unexpected EOF") // line 3
	}

	// example func that catches an error and wraps it with additional context
	parseFile := func(fname string) error {
		// read the file
		err := readFile(fname) // line 9
		if err != nil {
			return eris.Wrapf(err, "error reading file '%v'", fname) // line 11
		}
		return nil
	}

	// call parseFile and catch the error
	err := parseFile("example.json") // line 17

	// print the error via fmt.Printf
	fmt.Printf("%v\n", err) // %v: omit stack trace

	// example output:
	// unexpected EOF: error reading file 'example.json'

	// unpack and print the error via uerr.ToString(...)
	fmt.Println(eris.ToString(err, true)) // true: include stack trace

	// example output:
	// error reading file 'example.json'
	//   main.parseFile:.../example/main.go:11
	// unexpected EOF
	//   main.main:.../example/main.go:17
	//   main.parseFile:.../example/main.go:11
	//   main.parseFile:.../example/main.go:9
	//   main.readFile:.../example/main.go:3
}
Output:

func Unwrap

func Unwrap(err error) error

Unwrap returns the result of calling the Unwrap method on err, if err's type contains an Unwrap method returning error. Otherwise, Unwrap returns nil.

func Wrap

func Wrap(err error, msg string) error

Wrap adds additional context to all error types while maintaining the type of the original error.

This method behaves differently for each error type. For root errors, the stack trace is reset to the current callers which ensures traces are correct when using global/sentinel error values. Wrapped error types are simply wrapped with the new context. For external types (i.e. something other than root or wrap errors), this method attempts to unwrap them while building a new error chain. If an external type does not implement the unwrap interface, it flattens the error and creates a new root error from it before wrapping with the additional context.

func Wrapf

func Wrapf(err error, format string, args ...interface{}) error

Wrapf adds additional context to all error types while maintaining the type of the original error.

This is a convenience method for wrapping errors with formatted messages and is otherwise the same as Wrap.

Types

type ErrLink struct {
	Msg   string
	Frame StackFrame
}

ErrLink represents a single error frame and the accompanying message.

type ErrRoot

type ErrRoot struct {
	Msg   string
	Stack Stack
}

ErrRoot represents an error stack and the accompanying message.

type FormatOptions added in v0.3.0

type FormatOptions struct {
	InvertOutput bool // Flag that inverts the error output (wrap errors shown first).
	WithTrace    bool // Flag that enables stack trace output.
	InvertTrace  bool // Flag that inverts the stack trace output (top of call stack shown first).
	WithExternal bool // Flag that enables external error output.

}

FormatOptions defines output options like omitting stack traces and inverting the error or stack order.

type JSONFormat added in v0.3.0

type JSONFormat struct {
	Options FormatOptions // Format options (e.g. omitting stack trace or inverting the output order).
	// todo: maybe allow setting of wrap/root keys in the output map as well
	StackElemSep string // Separator between elements of each stack frame.
}

JSONFormat defines a JSON error format.

func NewDefaultJSONFormat added in v0.3.0

func NewDefaultJSONFormat(options FormatOptions) JSONFormat

NewDefaultJSONFormat returns a default JSON output format.

type Stack added in v0.2.0

type Stack []StackFrame

Stack is an array of stack frames stored in a human readable format.

type StackFrame

type StackFrame struct {
	Name string
	File string
	Line int
}

StackFrame stores a frame's runtime information in a human readable format.

type StringFormat added in v0.3.0

type StringFormat struct {
	Options      FormatOptions // Format options (e.g. omitting stack trace or inverting the output order).
	MsgStackSep  string        // Separator between error messages and stack frame data.
	PreStackSep  string        // Separator at the beginning of each stack frame.
	StackElemSep string        // Separator between elements of each stack frame.
	ErrorSep     string        // Separator between each error in the chain.
}

StringFormat defines a string error format.

func NewDefaultStringFormat added in v0.3.0

func NewDefaultStringFormat(options FormatOptions) StringFormat

NewDefaultStringFormat returns a default string output format.

type UnpackedError

type UnpackedError struct {
	ErrExternal error
	ErrRoot     ErrRoot
	ErrChain    []ErrLink
}

UnpackedError represents complete information about an error.

This type can be used for custom error logging and parsing. Use `eris.Unpack` to build an UnpackedError from any error type. The ErrChain and ErrRoot fields correspond to `wrapError` and `rootError` types, respectively. If any other error type is unpacked, it will appear in the ExternalErr field.

func Unpack

func Unpack(err error) UnpackedError

Unpack returns a human-readable UnpackedError type for a given error.

Directories

Path Synopsis
examples module

Jump to

Keyboard shortcuts

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