cluerr

package
v0.0.0-...-ce9259a Latest Latest
Warning

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

Go to latest
Published: Dec 21, 2024 License: MIT Imports: 9 Imported by: 1

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CluesIn

func CluesIn(err error) *node.Node

CluesIn returns the structured data in the error. Each error in the stack is unwrapped and all maps are unioned. In case of collision, lower level error data take least priority.

func Comments

func Comments(err error) node.CommentHistory

Comments retrieves all comments in the error.

func HasLabel

func HasLabel(err error, label string) bool

func Labels

func Labels(err error) map[string]struct{}

Types

type Err

type Err struct {
	// contains filtered or unexported fields
}

Err augments an error with labels (a categorization system) and data (a map of contextual data used to record the state of the process at the time the error occurred, primarily for use in upstream logging and other telemetry),

func Label

func Label(err error, label string) *Err

func New

func New(msg string) *Err

New creates an *Err with the provided Msg.

If you have a `ctx` containing other clues data, it is recommended that you call `NewWC(ctx, msg)` to ensure that data gets added to the error.

The returned *Err is an error-compliant builder that can aggregate additional data using funcs like With(...) or Label(...).

func NewWC

func NewWC(ctx context.Context, msg string) *Err

NewWC creates an *Err with the provided Msg, and additionally extracts all of the clues data in the context into the error.

NewWC is equivalent to clues.New("msg").WithClues(ctx).

The returned *Err is an error-compliant builder that can aggregate additional data using funcs like With(...) or Label(...).

func SkipCaller

func SkipCaller(err error, depth int) *Err

SkipCaller skips <depth> callers when constructing the error trace stack. The caller is the file, line, and func where the *clues.Err was generated.

A depth of 0 performs no skips, and returns the same caller info as if SkipCaller was not called. 1 skips the immediate parent, etc.

Error traces are already generated for the location where clues.Wrap or clues.Stack was called. This func is for cases where Wrap or Stack calls are handled in a helper func and are not reporting the actual error origin.

If err is not an *Err intance, returns the error wrapped into an *Err struct.

func Stack

func Stack(errs ...error) *Err

Stack composes a stack of one or more errors. The first message in the parameters is considered the "most recent". Ex: a construction like clues.Stack(errFoo, io.EOF, errSmarf), the resulting Error message would be "foo: end-of-file: smarf".

Unwrapping a Stack follows the same order. This allows callers to inject sentinel errors into error chains (ex: clues.Stack(io.EOF, myErr)) without losing errors.Is or errors.As checks on lower errors.

If given a single error, Stack acts as a thin wrapper around the error to provide an *Err, giving the caller access to all the builder funcs and error tracing. It is always recommended that callers `return clues.Stack(err)` instead of the plain `return err`.

The returned *Err is an error-compliant builder that can aggregate additional data using funcs like With(...) or Label(...).

Stack can be given one or more `nil` error values. Nil errors will be automatically filtered from the retained stack of errors. Ex: clues.Stack(errFoo, nil, errSmarf) == clues.Stack(errFoo, errSmarf). If all input errors are nil, stack will return nil. To avoid golang footguns when returning nil structs as interfaces (such as error), callers should always return Stack().OrNil() in cases where the input error could be nil.

func StackWC

func StackWC(ctx context.Context, errs ...error) *Err

StackWC composes a stack of one or more errors. The first message in the parameters is considered the "most recent". Ex: a construction like clues.StackWC(errFoo, io.EOF, errSmarf), the resulting Error message would be "foo: end-of-file: smarf".

Unwrapping a Stack follows the same order. This allows callers to inject sentinel errors into error chains (ex: clues.StackWC(io.EOF, myErr)) without losing errors.Is or errors.As checks on lower errors.

If given a single error, Stack acts as a thin wrapper around the error to provide an *Err, giving the caller access to all the builder funcs and error tracing. It is always recommended that callers `return clues.StackWC(err)` instead of the plain `return err`.

StackWC is equivalent to clues.Stack(errs...).WithClues(ctx)

The returned *Err is an error-compliant builder that can aggregate additional data using funcs like With(...) or Label(...).

Stack can be given one or more `nil` error values. Nil errors will be automatically filtered from the retained stack of errors. Ex: clues.StackWC(ctx, errFoo, nil, errSmarf) == clues.StackWC(ctx, errFoo, errSmarf). If all input errors are nil, stack will return nil. To avoid golang footguns when returning nil structs as interfaces (such as error), callers should always return StackWC().OrNil() in cases where the input error could be nil.

func StackWrap

func StackWrap(sentinel, wrapped error, msg string) *Err

StackWrap is a quality-of-life shorthand for a common usage of clues errors: clues.Stack(sentinel, clues.Wrap(myErr, "my message")). The result follows all standard behavior of stacked and wrapped errors.

The returned *Err is an error-compliant builder that can aggregate additional data using funcs like With(...) or Label(...).

StackWrap can be given one or more `nil` error values. Nil errors will be automatically filtered from the retained stack of errors. Ex: clues.StackWrap(errFoo, nil, "msg") == clues.Wrap(errFoo, "msg"). If both input errors are nil, StackWrap will return nil. To avoid golang footguns when returning nil structs as interfaces (such as error), callers should always return StackWrap().OrNil() in cases where the input errors could be nil.

func StackWrapWC

func StackWrapWC(
	ctx context.Context,
	sentinel, wrapped error,
	msg string,
) *Err

StackWrapWC is a quality-of-life shorthand for a common usage of clues errors: clues.Stack(sentinel, clues.Wrap(myErr, "my message")).WithClues(ctx). The result follows all standard behavior of stacked and wrapped errors.

The returned *Err is an error-compliant builder that can aggregate additional data using funcs like With(...) or Label(...).

StackWrapWC can be given one or more `nil` error values. Nil errors will be automatically filtered from the retained stack of errors. Ex: clues.StackWrapWC(ctx, errFoo, nil, "msg") == clues.WrapWC(ctx, errFoo, "msg"). If both input errors are nil, StackWrap will return nil. To avoid golang footguns when returning nil structs as interfaces (such as error), callers should always return StackWrap().OrNil() in cases where the input errors could be nil.

func Wrap

func Wrap(err error, msg string) *Err

Wrap extends an error with the provided message. It is a replacement for `errors.Wrap`, and complies with all golang unwrapping behavior.

If you have a `ctx` containing other clues data, it is recommended that you call `WrapWC(ctx, err, msg)` to ensure that data gets added to the error.

The returned *Err is an error-compliant builder that can aggregate additional data using funcs like With(...) or Label(...). There is no Wrapf func in clues; we prefer that callers use Wrap().With() instead.

Wrap can be given a `nil` error value, and will return a nil *Err. To avoid golang footguns when returning nil structs as interfaces (such as error), callers should always return Wrap().OrNil() in cases where the input error could be nil.

func WrapWC

func WrapWC(ctx context.Context, err error, msg string) *Err

WrapWC extends an error with the provided message. It is a replacement for `errors.Wrap`, and complies with all golang unwrapping behavior.

WrapWC is equivalent to clues.Wrap(err, "msg").WithClues(ctx).

If you have a `ctx` containing other clues data, it is recommended that you call `WrapWC(ctx, err, msg)` to ensure that data gets added to the error.

The returned *Err is an error-compliant builder that can aggregate additional data using funcs like With(...) or Label(...). There is no WrapWCf func in clues; we prefer that callers use WrapWC().With() instead.

Wrap can be given a `nil` error value, and will return a nil *Err. To avoid golang footguns when returning nil structs as interfaces (such as error), callers should always return WrapWC().OrNil() in cases where the input error could be nil.

func (*Err) As

func (err *Err) As(target any) bool

As overrides the standard As check for Err.e, allowing us to check the conditional for both Err.e and Err.stack. This allows clues to Stack() multiple error pointers without failing the otherwise linear errors.As check.

func (*Err) Comment

func (err *Err) Comment(msg string, vs ...any) *Err

Comment is a special case additions to the error. They're here to, well, let you add comments! Why? Because sometimes it's not sufficient to have an error message describe what that error really means. Even a bunch of clues to describe system state may not be enough. Sometimes what you need in order to debug the situation is a long-form explanation (you do already add that to your code, don't you?). Or, even better, a linear history of long-form explanations, each one building on the prior (which you can't easily do in code).

Unlike other additions, which are added as top-level key:value pairs to the context, the whole history of comments gets retained, persisted in order of appearance and prefixed by the file and line in which they appeared. This means comments are always added to the error and never clobber each other, regardless of their location.

func (*Err) Comments

func (err *Err) Comments() node.CommentHistory

Comments retrieves all comments in the error.

func (*Err) Core

func (err *Err) Core() *ErrCore

Core transforms the error into an ErrCore. ErrCore is a minimized version of an Err{}. It produces a concrete, storable version of the clues error data. Rather than expose the underlying error structure that's used for building metadata, an error core synthesizes the hierarchical storage of errors and data nodes into a flat, easily consumed set of properties.

func (*Err) Error

func (err *Err) Error() string

Error allows Err to be used as a standard error interface.

func (*Err) Format

func (err *Err) Format(s fmt.State, verb rune)

Format ensures stack traces are printed appropariately.

%s    same as err.Error()
%v    equivalent to %s

Format accepts flags that alter the printing of some verbs, as follows:

%+v   Prints filename, function, and line number for each error in the stack.

func (*Err) HasLabel

func (err *Err) HasLabel(label string) bool

func (*Err) Is

func (err *Err) Is(target error) bool

Is overrides the standard Is check for Err.e, allowing us to check the conditional for both Err.e and Err.stack. This allows clues to Stack() multiple error pointers without failing the otherwise linear errors.Is check.

func (*Err) Label

func (err *Err) Label(labels ...string) *Err

func (*Err) Labels

func (err *Err) Labels() map[string]struct{}

func (*Err) NoTrace

func (err *Err) NoTrace() *Err

NoTrace prevents the error from appearing in the trace stack. This is particularly useful for global sentinels that get stacked or wrapped into other error cases.

func (*Err) Node

func (err *Err) Node() *node.Node

Node retrieves the node values from the error.

func (*Err) OrNil

func (err *Err) OrNil() error

OrNil is a workaround for golang's infamous "an interface holding a nil value is not nil" gotcha. You should use it to ensure the error value to produce is properly nil whenever your wrapped or stacked error values could also possibly be nil.

ie: ``` return clues.Stack(maybeNilErrValue).OrNil() // or return clues.Wrap(maybeNilErrValue, "msg").OrNil() ```

func (*Err) SkipCaller

func (err *Err) SkipCaller(depth int) *Err

SkipCaller skips <depth> callers when constructing the error trace stack. The caller is the file, line, and func where the *clues.Err was generated.

A depth of 0 performs no skips, and returns the same caller info as if SkipCaller was not called. 1 skips the immediate parent, etc.

Error traces are already generated for the location where clues.Wrap or clues.Stack was called. This func is for cases where Wrap or Stack calls are handled in a helper func and are not reporting the actual error origin.

func (*Err) Unwrap

func (err *Err) Unwrap() error

Unwrap provides compatibility for Go 1.13 error chains. Unwrap returns the Unwrap()ped base error, if it implements the unwrapper interface:

type unwrapper interface {
       Unwrap() error
}

If the error does not implement Unwrap, returns the base error.

func (*Err) Values

func (err *Err) Values() *node.Node

Values returns a copy of all of the contextual data in the error. Each error in the stack is unwrapped and all maps are unioned. In case of collision, lower level error data take least priority.

func (*Err) With

func (err *Err) With(kvs ...any) *Err

With adds every pair of values as a key,value pair to the Err's data map.

func (*Err) WithClues

func (err *Err) WithClues(ctx context.Context) *Err

WithClues is syntactical-sugar that assumes you're using the clues package to store structured data in the context. The values in the default namespace are retrieved and added to the error.

clues.Stack(err).WithClues(ctx) adds the same data as clues.Stack(err).WithMap(clues.Values(ctx)).

If the context contains a clues LabelCounter, that counter is passed to the error. WithClues must always be called first in order to count labels.

func (*Err) WithMap

func (err *Err) WithMap(m map[string]any) *Err

WithMap copies the map to the Err's data map.

type ErrCore

type ErrCore struct {
	Msg      string              `json:"msg"`
	Labels   map[string]struct{} `json:"labels"`
	Values   map[string]any      `json:"values"`
	Comments node.CommentHistory `json:"comments"`
}

ErrCore is a minimized version of an Err{}. It produces a concrete, storable version of the clues error data. Rather than expose the underlying error structure that's used for building metadata, an error core synthesizes the hierarchical storage of errors and data nodes into a flat, easily consumed set of properties.

func ToCore

func ToCore(err error) *ErrCore

ToCore transforms the error into an ErrCore. ErrCore is a minimized version of an Err{}. It produces a concrete, storable version of the clues error data. Rather than expose the underlying error structure that's used for building metadata, an error core synthesizes the hierarchical storage of errors and data nodes into a flat, easily consumed set of properties.

func (*ErrCore) Format

func (ec *ErrCore) Format(s fmt.State, verb rune)

Format provides cleaner printing of an ErrCore struct.

%s    only populated values are printed, without printing the property name.
%v    same as %s.

Format accepts flags that alter the printing of some verbs, as follows:

%+v    prints the full struct, including empty values and property names.

func (*ErrCore) String

func (ec *ErrCore) String() string

Jump to

Keyboard shortcuts

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