All Projects → jjeffery → errors

jjeffery / errors

Licence: MIT License
Simple error handling primitives that work well with structured logging

Programming Languages

go
31211 projects - #10 most used programming language

Projects that are alternatives of or similar to errors

blindsight
Blindsight is a Scala logging API with DSL based structured logging, fluent logging, semantic logging, flow logging, and context aware logging.
Stars: ✭ 70 (+150%)
Mutual labels:  structured-logging
timber-ruby
🌲 Great Ruby logging made easy.
Stars: ✭ 155 (+453.57%)
Mutual labels:  structured-logging
raygun4ruby
The Ruby & Ruby on Rails provider for Raygun
Stars: ✭ 37 (+32.14%)
Mutual labels:  error-handling
fejl
Error-making utility for Node apps.
Stars: ✭ 30 (+7.14%)
Mutual labels:  error-handling
dx
JavaScript without `try...catch`.
Stars: ✭ 26 (-7.14%)
Mutual labels:  error-handling
rescue
🚒✨ Rescue: better errors through types (a more type directed MonadThrow/MonadCatch)
Stars: ✭ 18 (-35.71%)
Mutual labels:  error-handling
failure
An error handling package for Go.
Stars: ✭ 24 (-14.29%)
Mutual labels:  error-handling
ErrorHandler
This is a library for Google Apps Script projects. It provides methods to perform an Exponential backoff logic whenever it is needed and rewrite error objects before sending them to Stackdriver Logging.
Stars: ✭ 14 (-50%)
Mutual labels:  error-handling
belay
Robust error-handling for Kotlin and Android
Stars: ✭ 35 (+25%)
Mutual labels:  error-handling
moko-errors
Automated exceptions handler for mobile (android & ios) Kotlin Multiplatform development.
Stars: ✭ 45 (+60.71%)
Mutual labels:  error-handling
merr
🔥 Minimal and good enough error handling library for Clojure/ClojureScript
Stars: ✭ 25 (-10.71%)
Mutual labels:  error-handling
sentry-testkit
A Sentry plugin to allow Sentry report interception and further inspection of the data being sent
Stars: ✭ 78 (+178.57%)
Mutual labels:  error-handling
apollo-error-converter
Global Apollo Server Error handling made easy. Remove verbose and repetitive resolver / data source Error handling. Automatic Error catching, logging, and conversion to ApolloErrors.
Stars: ✭ 16 (-42.86%)
Mutual labels:  error-handling
miette
Fancy upgrade to std::error::Error.
Stars: ✭ 945 (+3275%)
Mutual labels:  error-handling
ErrorLayout
Simple layout to show custom error toast with animation
Stars: ✭ 13 (-53.57%)
Mutual labels:  error-handling
progress-bar-log
A component to display a progress bar and last X logs at the same time.
Stars: ✭ 44 (+57.14%)
Mutual labels:  error-handling
gommon
A collection of common util libraries for Go
Stars: ✭ 26 (-7.14%)
Mutual labels:  error-handling
scope
Logging scopes for slog-rs
Stars: ✭ 12 (-57.14%)
Mutual labels:  structured-logging
jsonerror
Makes Go error-handling a breeze!
Stars: ✭ 28 (+0%)
Mutual labels:  error-handling
whoops
It makes simple create qualified errors.
Stars: ✭ 28 (+0%)
Mutual labels:  error-handling

errors GoDoc License Build Status Coverage Status GoReportCard

Package errors provides simple error handling primitives that work well with structured logging.

This package is deprecated. Use the kv package instead. It provides support for creating errors with key/value pairs. The idea of having a drop-in replacement for the standard library errors package was based on the fact that errors only exported one simple function. The Go 2 draft proposes additional functions and types for the standard library errors package, and any attempts to use the new standard library package with this package will be annoying.

Acknowledgement

This package is inspired by the excellent github.com/pkg/errors package. A significant amount of code and documentation in this package has been adapted from that source.

A key difference between this package and github.com/pkg/errors is that this package has been designed to suit programs that make use of structured logging. Some of the ideas in this package were proposed for package github.com/pkg/errors, but after a reasonable amount of consideration, were ultimately not included in that package.

If you are not using structured logging in your application and have no intention of doing so, you will probably be better off using the github.com/pkg/errors package in preference to this one.

Background

The traditional error handling idiom in Go is roughly akin to

if err != nil {
        return err
}

which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error.

Creating errors

The errors package provides three operations which combine to form a simple yet powerful system for enhancing the value of returned errors:

Operation Description
New create a new error
Wrap wrap an existing error with an optional message
With attach key/value pairs to an error

New — create a new error

The New function is used to create an error. This function is compatible with the Go standard library errors package:

err := errors.New("emit macho dwarf: elf header corrupted")

Wrap — add a message to an error

The Wrap function returns an error that adds a message to the original error. This additional message can be useful for putting the original error in context. For example:

err := errors.New("permission denied")
fmt.Println(err)

err = errors.Wrap(err, "cannot list directory contents")
fmt.Println(err)

// Output:
// permission denied
// cannot list directory contents: permission denied

With — add key/value pairs to an error

The With function accepts a variadic list of alternating key/value pairs, and returns an error context that can be used to create a new error or wrap an existing error.

// create new error
err = errors.With("file", "testrun", "line", 101).New("file locked")
fmt.Println(err)

// wrap existing error
err = errors.With("attempt", 3).Wrap(err, "retry failed")
fmt.Println(err)

// Output:
// file locked file=testrun line=101
// retry failed attempt=3: file locked file=testrun line=101

One useful pattern is to create an error context that is used for an entire function scope:

func doSomethingWith(file string, line int) error {
	// set error context
	errors := errors.With("file", file, "line", line)
	
	if number <= 0 {
		// file and line will be attached to the error
		return errors.New("invalid number")
	}
	
	// ... later ...
	
	if err := doOneThing(); err != nil {
		// file and line will be attached to the error
		return errors.Wrap(err, "cannot do one thing")
	}
	
	// ... and so on until ...
	
	return nil
}

The errors returned by New and Wrap provide a With method that enables a fluent-style of error handling:

// create new error
err = errors.New("file locked").With(
    "file", "testrun", 
	"line", 101,
)
fmt.Println(err)

// wrap existing error
err = errors.Wrap(err, "retry failed").With("attempt", 3)
fmt.Println(err)

// Output:
// file locked file=testrun line=101
// retry failed attempt=3: file locked file=testrun line=101

(Dave Cheney has written up some good reasons to avoid a fluent API. Experience will show if this presents a problem, but to date it has felt like it leads to simpler, more readable code).

Retrieving the cause of an error

Using errors.Wrap constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by errors.Cause.

type causer interface {
        Cause() error
}

errors.Cause will recursively retrieve the topmost error which does not implement causer, which is assumed to be the original cause. For example:

switch err := errors.Cause(err).(type) {
case *MyError:
    // handle specifically
default:
    // unknown error
}

Retrieving key value pairs for structured logging

Errors created by errors.Wrap and errors.New implement the following interface.

type keyvalser interface {
	Keyvals() []interface{}
}

The Keyvals method returns an array of alternating keys and values. The first key will always be "msg" and its value will be a string containing the message associated with the wrapped error.

Example using go-kit logging:

// logError logs details of an error to a structured error log.
func logError(logger log.Logger, err error) {
	// start with timestamp and error level
	keyvals := []interface{}{
		"ts",    time.Now().Format(time.RFC3339Nano),
		"level", "error",
	}

	type keyvalser interface {
		Keyvals() []interface{}
	}
	if kv, ok := err.(keyvalser); ok {
		// error contains structured information, first key/value
		// pair will be "msg".
		keyvals = append(keyvals, kv.Keyvals()...)
	} else {
		// error does not contain structured information, use the
		// Error() string as the message.
		keyvals = append(keyvals, "msg", err.Error())
	}
	logger.Log(keyvals...)
}

GOOD ADVICE: Do not use the Keyvals method on an error to retrieve the individual key/value pairs associated with an error for processing by the calling program.

Read the package documentation for more information.

Licence

MIT

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].