errors

package module
v0.0.0-...-6e9a809 Latest Latest
Warning

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

Go to latest
Published: Feb 6, 2024 License: Apache-2.0 Imports: 5 Imported by: 4

README

errors

Provides error enrichment utilities to store and retrieve additional context within errors as well as other general error handling utilities.

go get github.com/kubespress/errors

Use cases

Getting the error cause

The library mirrors the errors.Is and errors.As methods presented in the standard library, this allows for the original cause of an error to be determined and decisions to be taken based on this. All methods that mutate the errors in this package preserve the error chain, keeping this information.

    if errors.Is(err, os.ErrNotExist) {
        fmt.Println("file missing")
    }
Adding context to errors

For example to add a "user facing message" to errors you can use the errors.Set method:

    return errors.Enrich(err,
        errors.Set[UserFacingMessage]("Invalid details entered")
    )

This context can be retrieved later:

    fmt.Println(
        errors.Get[UserFacingMessage](err, "Internal error" /* default value*/)
    )

By using generics, types can be defined to hold specific context. Some examples include a ErrorCode or UserFacingMessage that can be presented to a user, while logging the original message. Context that is used internally can also be added, for example:

    return errors.Enrich(err,
        errors.Set[IsTemporary](true)
    )
    for {
        // Perform an action
        err := someFn()

        // If the error is temporary retry the action
        if errors.Check[IsTemporary](err) {
            continue
        }

        // Return the error (or nil)
        return err
    }
Adding a call stack to an error

If you wish errors to include a call stack then this can be added using the errors.Enrich method. For example:

    return errors.Enrich(err, errors.WithStack())

This call stack will be printed when the error is formatted with %+v.

Filtering errors

There are some cases where depending on the error itself, you may want to ignore it. For example if you are writing a Kubernetes operator you often see this bit of code:

    if err := r.Get(ctx, req.NamespacedName, &object); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }

This library allows the error to be enriched and for unwanted errors to be dropped in a single call, for example:

    if err := r.Get(ctx, req.NamespacedName, &object); err != nil {
        return ctrl.Result{}, errors.Enrich(err, 
            client.IgnoreNotFound
            errors.Wrapf("failed to get %s", req.NamespacedName),
            errors.WithStack(),
        )
    }
Aggregating errors

This allows multiple errors to be aggregated into a single error, while not breaking errors.Is, errors.As, errors.Check and errors.Get, for example:

func Example(fns []func()error) error {
    var errs errors.ErrorList

    for _, fn := range fns {
        if err := fn(); err != nil {
            errs = append(errs, err)
        }
    }

    return errs.Error()
}

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Aggregate

func Aggregate(errs ...error) error

Aggregate returns an error wrapping multiple other errors. If no other errors are passed in this method returns nil.

func All

func All[T any](err error) (results []T)

All returns the enriched context if it exists in the error. As opposed to Get this function returns all the enriched values instead of stopping at the first one.

func As

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

As finds the first error in err's tree that matches target, and if one is found, sets target to that error value and returns true. Otherwise, it returns false.

func Check

func Check[T ~bool](err error) bool

Check returns true if the error contains the specified context and it is true.

Example
// Temporary indicates the error is Temporary
type Temporary bool

// Call function returning error
err := functionReturningError()
if err != nil {
	// If the error is Temporary then do nothing
	if errors.Check[Temporary](err) {
		return
	}

	// Print the error message
	fmt.Println(err)
}

func Enrich

func Enrich(err error, enrichments ...Enricher) error

Enrich adds additional context to an error using the provided enrichment functions

func Errorf

func Errorf(msg string, args ...any) error

Errorf creates a new error using string formatting.

func Get

func Get[T any](err error, def T) T

Get returns the enriched context if it exists in the error, otherwise it returns the provided default value.

Example
// UserFacingMessage is a type containing a user facing message
type UserFacingMessage string

// Call function returning error
err := functionReturningError()
if err != nil {
	// Get the user facing message
	msg := errors.Get[UserFacingMessage](err, "Internal server error")

	// Print the error message
	fmt.Println(msg)
}
Output:
Internal server error

func Is

func Is(err error, target error) bool

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

func New

func New(msg string) error

New creates a new error

func Visit

func Visit(err error, fn func(error) bool)

Visit will unwrap the error recursively, calling the provided function for each error.

Types

type Enricher

type Enricher func(error) error

Enricher is an error enrichment, it adds additional context to the provided error.

func Set

func Set[T any](value T) Enricher

Set enriches an error with a specific type.

Example
// UserFacingMessage is a type containing a user facing message
type UserFacingMessage string

// Enrich error using Set method
err := errors.Enrich(functionReturningError(), errors.Set[UserFacingMessage]("Well this sucks."))

// Print the error
fmt.Println(errors.Get[UserFacingMessage](err, "Internal server error"))
Output:
Well this sucks.

func WithStack

func WithStack() Enricher

WithStack will enrich the message with a stacktrace

func WithStackN

func WithStackN(skip int) Enricher

WithStackN will enrich the message with a stacktrace, skipping a specified number of calls.

func Wrap

func Wrap(msg string) Enricher

Wrap returns an enricher that prefixes an error message with a provided string for additional context

func Wrapf

func Wrapf(msg string, args ...interface{}) Enricher

Wrapf returns an enricher that prefixes an error message with a provided string for additional context

type ErrorCollector

type ErrorCollector struct {
	ErrorList
}

ErrorCollector is a wrapper for ErrorList that provides methods for adding errors if they are not nil

func NewErrorCollector

func NewErrorCollector() *ErrorCollector

func (*ErrorCollector) AppendErrorIfNotNil

func (e *ErrorCollector) AppendErrorIfNotNil(err error)

AppendErrorIfNotNil will append the error to the ErrorList if it is not nil, it is designed to allow for a pattern where function call is passed right into the method, for example:

collection.AppendErrorIfNotNil(someFunctionThatMayError())

type ErrorList

type ErrorList []error

ErrorList is a list of errors, it can be used as a utility to aggregate errors by appending to the slice

func (ErrorList) Error

func (err ErrorList) Error() error

Error returns the aggregated error, if the list is empty, nil is returned

type TypedErrorCollector

type TypedErrorCollector[T any] struct {
	// contains filtered or unexported fields
}

TypedErrorCollector that allows you to pass through return values while keeping error

func ErrorCollectorForType

func ErrorCollectorForType[T any](collector *ErrorCollector) TypedErrorCollector[T]

ErrorCollectorForType returns a TypedErrorCollector that will collect errors onto a given ErrorCollector

func (TypedErrorCollector[T]) AppendErrorIfNotNil

func (e TypedErrorCollector[T]) AppendErrorIfNotNil(result T, err error) T

AppendErrorIfNotNil will append the error to the ErrorList if it is not nil and return the specified value. It is designed to allow for a pattern where function call is passed right into the method, for example:

value := collection.AppendErrorIfNotNil(someFunctionThatMayError())

Jump to

Keyboard shortcuts

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