Documentation
¶
Overview ¶
Package errors prefixes the calling functions name to errors for simpler, smaller traces. This package tries to split the difference between github.com/pkg/errors and Go stdlib errors, with first class support for log/slog.
Example ¶
// This is just setup code that makes slog's output deterministic so the example output is stable.
DefaultFileSlogKey = "file"
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
ReplaceAttr: func(_ []string, a slog.Attr) slog.Attr {
if a.Key == slog.TimeKey {
return slog.Attr{}
}
return a
},
})))
// This example shows how to use WrapMeta() to attach metadata to errors.
err := dontHurtMe()
if err != nil {
// include some metadata about this failure
err = WrapMeta(err, slog.String("baby", "don't"), slog.String("hurt", "me"))
}
// Typically this error would then bubble up through a few more function calls.
// Could be wrapped many more times, but eventually something handles this error.
// For exanple, it can be logged
if err != nil {
slog.Warn("what is love", "err", err)
}
// Pulling out metadata from a context is also possible, useful for attaching something like request IDs to any error from a request handler.
ctx := AddMetaToCtx(context.Background(), slog.Uint64("req_id", 42))
// Another easy way of wrapping errors with metadata known at the start of the function is to defer WrapMeta.
// This is possible since WrapMeta returns nil if the error is nil.
err = func(id uint64, parseMe string) (err error) {
defer func() { err = WrapMetaCtx(ctx, err, slog.Uint64("id", id)) }()
_, err = strconv.Atoi(parseMe)
if err != nil {
return Wrap(err)
}
return nil
}(0451, "trust me i'm numerical")
if err != nil {
slog.LogAttrs(context.TODO(), slog.LevelWarn, "parse failure", slog.Any("err", err))
}
// printing the error with something like fmt.Println won't include the metadata in the output.
fmt.Println(err)
err = Wrapf(err, "doubleWrap")
// unless you use %+v
fmt.Printf("%+v", err)
Output: level=WARN msg="what is love" err.baby=don't err.hurt=me err.file=/home/dan/go/src/github.com/danlock/pkg/errors/meta_test.go:16 err.msg="errors.dontHurtMe no more" level=WARN msg="parse failure" err.id=297 err.req_id=42 err.file=/home/dan/go/src/github.com/danlock/pkg/errors/meta_test.go:51 err.msg="errors.Example.func2 strconv.Atoi: parsing \"trust me i'm numerical\": invalid syntax" errors.Example.func2 strconv.Atoi: parsing "trust me i'm numerical": invalid syntax errors.Example doubleWrap errors.Example.func2 strconv.Atoi: parsing "trust me i'm numerical": invalid syntax {id=297,req_id=42,file=/home/dan/go/src/github.com/danlock/pkg/errors/meta_test.go:51}
Index ¶
- Variables
- func AddMetaToCtx(ctx context.Context, meta ...slog.Attr) context.Context
- func As(err error, target any) bool
- func Errorf(format string, a ...any) error
- func ErrorfWithSkip(skip int, format string, a ...any) error
- func Into[T error](err error) (val T, ok bool)
- func Is(err error, target error) bool
- func Join(errs ...error) error
- func Must[T any](val T, err error) T
- func New(text string) error
- func Unwrap(err error) error
- func UnwrapMeta(err error) (meta []slog.Attr)
- func UnwrapMetaMap(err error) map[string]slog.Value
- func Wrap(err error) error
- func WrapAndPass[T any](val T, err error) (T, error)
- func WrapMeta(err error, meta ...slog.Attr) error
- func WrapMetaCtx(ctx context.Context, err error, meta ...slog.Attr) error
- func Wrapf(err error, format string, a ...any) error
- func WrapfAndPass[T any](val T, err error, format string, a ...any) (T, error)
- func WrapfWithSkip(err error, skip int, format string, a ...any) error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var DefaultFileSlogKey = "file"
DefaultFileSlogKey is the default slog.Attr key used for file:line information when an error is printed via log/slog. If DefaultFileSlogKey is set to "", file:line metadata will not be included in errors.
var ErrUnsupported = errors.ErrUnsupported
ErrUnsupported indicates that a requested operation cannot be performed, because it is unsupported
Functions ¶
func AddMetaToCtx ¶
AddMetaToCtx adds metadata to the context that will be added to the error once WrapMetaCtx is called.
func As ¶
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 Errorf ¶
Errorf is like fmt.Errorf with the "package.func" of it's caller prepended. It also includes the file and line info of it's caller.
func ErrorfWithSkip ¶
ErrorfWithSkip is like fmt.Errorf with the "package.func" of the desired caller prepended. It also includes the file and line info of it's caller.
func Into ¶
Into finds the first error in err's chain that matches target type T, and if so, returns it. Into is a type-safe alternative to As.
func Must ¶
Must is a generic helper, like template.Must, that wraps a call to a function returning (T, error) and panics if the error is non-nil.
func New ¶
New creates a new error with the package.func of it's caller prepended. It also includes the file and line info of it's caller.
func Unwrap ¶
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 UnwrapMeta ¶
UnwrapMeta pulls metadata from every error in the chain for structured logging purposes. Errors in this package implement slog.LogValuer and automatically include the metadata when used with slog.Log. This function is mainly exposed for use with other loggers that don't support structured logging from the stdlib.
func UnwrapMetaMap ¶
UnwrapMetaMap returns a map around an error's metadata. If the error lacks metadata an empty map is returned.
Structured errors can be introspected and handled differently as needed. As this is a map, duplicate keys across the error chain are not allowed. If that is an issue for you, use UnwrapMeta instead.
Seriously consider a sentinel error or custom error type before reaching for this. For example open source libraries would be better off publicly exposing custom error types for type safety.
Using const keys is strongly recommended to avoid typos.
func Wrap ¶
Wrap wraps an error with the caller's package.func prepended. Similar to github.com/pkg/errors.Wrap and unlike fmt.Errorf it returns nil if err is nil. If not wrapping an error from this Go package it also includes the file and line info of it's caller.
func WrapAndPass ¶
WrapAndPass wraps a typical error func with Wrap and passes the value through unchanged.
func WrapMetaCtx ¶
WrapMetaCtx wraps an error with metadata for structured logging. Similar to github.com/pkg/errors.Wrap and unlike fmt.Errorf it returns nil if err is nil. If not wrapping an error from this Go package it also includes the file and line info of it's caller. Metadata from the ctx added via CtxWithMeta will also be added to the error, if the context is set.
func Wrapf ¶
Wrapf wraps an error with the caller's package.func prepended. Similar to github.com/pkg/errors.Wrapf and unlike fmt.Errorf it returns nil if err is nil. If not wrapping an error from this Go package it also includes the file and line info of it's caller.
func WrapfAndPass ¶
WrapfAndPass wraps a typical error func with Wrapf and passes the value through unchanged.
func WrapfWithSkip ¶
WrapfWithSkip wraps an error with the caller's package.func prepended. Similar to github.com/pkg/errors.Wrapf and unlike fmt.Errorf it returns nil if err is nil. If not wrapping an error from this Go package it also includes the file and line info of it's caller. skip is the number of stack frames to skip before recording the function info from runtime.Callers.
Types ¶
This section is empty.