Documentation
¶
Overview ¶
Package errtrace provides the ability to track a return trace for errors. This differs from a stack trace in that it is not a snapshot of the call stack at the time of the error, but rather a trace of the path taken by the error as it was returned until it was finally handled.
Wrapping errors ¶
Use the Wrap function at a return site to annotate it with the position of the return.
// Before if err != nil { return err } // After if err != nil { return errtrace.Wrap(err) }
Formatting return traces ¶
errtrace provides the Format and FormatString functions to obtain the return trace of an error.
errtrace.Format(os.Stderr, err)
See Format for details of the output format.
Additionally, errors returned by errtrace will also print a trace if formatted with the %+v verb when used with a Printf-style function.
log.Printf("error: %+v", err)
See also ¶
https://github.com/bracesdev/errtrace.
Example (Http) ¶
package main import ( "fmt" "io" "net" "net/http" "strings" "braces.dev/errtrace" "braces.dev/errtrace/internal/tracetest" ) func main() { tp := &http.Transport{Dial: rateLimitDialer} client := &http.Client{Transport: tp} ps := &PackageStore{ client: client, } _, err := ps.Get() fmt.Printf("Error fetching packages: %+v\n", tracetest.MustClean(errtrace.FormatString(err))) } type PackageStore struct { client *http.Client packagesCached []string } func (ps *PackageStore) Get() ([]string, error) { if ps.packagesCached != nil { return ps.packagesCached, nil } packages, err := ps.updateIndex() if err != nil { return nil, errtrace.Wrap(err) } ps.packagesCached = packages return packages, nil } func (ps *PackageStore) updateIndex() ([]string, error) { resp, err := ps.client.Get("http://example.com/packages.index") if err != nil { return nil, errtrace.Wrap(err) } contents, err := io.ReadAll(resp.Body) if err != nil { return nil, errtrace.Wrap(err) } return strings.Split(string(contents), ","), nil } func rateLimitDialer(network, addr string) (net.Conn, error) { // for testing, always return an error. return nil, errtrace.New("connect rate limited") }
Output: Error fetching packages: Get "http://example.com/packages.index": connect rate limited braces.dev/errtrace_test.rateLimitDialer /path/to/errtrace/example_http_test.go:3 braces.dev/errtrace_test.(*PackageStore).updateIndex /path/to/errtrace/example_http_test.go:2 braces.dev/errtrace_test.(*PackageStore).Get /path/to/errtrace/example_http_test.go:1
Example (Trace) ¶
package main import ( "fmt" "braces.dev/errtrace" "braces.dev/errtrace/internal/tracetest" ) func f1() error { return errtrace.Wrap(f2()) } func f2() error { return errtrace.Wrap(f3()) } func f3() error { return errtrace.New("failed") } func main() { got := errtrace.FormatString(f1()) // make trace agnostic to environment-specific location // and less sensitive to line number changes. fmt.Println(tracetest.MustClean(got)) }
Output: failed braces.dev/errtrace_test.f3 /path/to/errtrace/example_trace_test.go:3 braces.dev/errtrace_test.f2 /path/to/errtrace/example_trace_test.go:2 braces.dev/errtrace_test.f1 /path/to/errtrace/example_trace_test.go:1
Example (Tree) ¶
package main import ( "errors" "fmt" "strings" "braces.dev/errtrace" "braces.dev/errtrace/internal/tracetest" ) func normalErr(i int) error { return fmt.Errorf("std err %v", i) } func wrapNormalErr(i int) error { return errtrace.Wrap(normalErr(i)) } func nestedErrorList(i int) error { return errors.Join( normalErr(i), wrapNormalErr(i+1), ) } func main() { errs := errtrace.Wrap(errors.Join( normalErr(1), wrapNormalErr(2), nestedErrorList(3), )) got := errtrace.FormatString(errs) // make trace agnostic to environment-specific location // and less sensitive to line number changes. fmt.Println(trimTrailingSpaces(tracetest.MustClean(got))) } func trimTrailingSpaces(s string) string { lines := strings.Split(s, "\n") for i := range lines { lines[i] = strings.TrimRight(lines[i], " \t") } return strings.Join(lines, "\n") }
Output: +- std err 1 | +- std err 2 | | braces.dev/errtrace_test.wrapNormalErr | /path/to/errtrace/example_tree_test.go:1 | | +- std err 3 | | | +- std err 4 | | | | braces.dev/errtrace_test.wrapNormalErr | | /path/to/errtrace/example_tree_test.go:1 | | +- std err 3 | std err 4 | std err 1 std err 2 std err 3 std err 4 braces.dev/errtrace_test.Example_tree /path/to/errtrace/example_tree_test.go:2
Index ¶
- func Errorf(format string, args ...any) error
- func Format(w io.Writer, target error) (err error)
- func FormatString(target error) string
- func New(text string) error
- func Wrap(err error) error
- func Wrap2[T any](t T, err error) (T, error)
- func Wrap3[T1, T2 any](t1 T1, t2 T2, err error) (T1, T2, error)
- func Wrap4[T1, T2, T3 any](t1 T1, t2 T2, t3 T3, err error) (T1, T2, T3, error)
- func Wrap5[T1, T2, T3, T4 any](t1 T1, t2 T2, t3 T3, t4 T4, err error) (T1, T2, T3, T4, error)
- func Wrap6[T1, T2, T3, T4, T5 any](t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, err error) (T1, T2, T3, T4, T5, error)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Errorf ¶
Errorf creates an error message according to a format specifier and returns the string as a value that satisfies error.
It's equivalent to fmt.Errorf followed by Wrap to add caller information.
func Format ¶
Format writes the return trace for given error to the writer. The output takes a fromat similar to the following:
<error message> <function> <file>:<line> <caller of function> <file>:<line> [...]
If the error doesn't have a return trace attached to it, only the error message is reported. If the error is comprised of multiple errors (e.g. with errors.Join), the return trace of each error is reported as a tree.
Returns an error if the writer fails.
func FormatString ¶
FormatString writes the return trace for err to a string. See Format for details of the output format.
func New ¶
New returns an error with the supplied text.
It's equivalent to errors.New followed by Wrap to add caller information.
func Wrap ¶
Wrap adds information about the program counter of the caller to the error. This is intended to be used at all return points in a function. If err is nil, Wrap returns nil.
Types ¶
This section is empty.
Directories
¶
Path | Synopsis |
---|---|
cmd
|
|
errtrace
errtrace instruments Go code with error return tracing.
|
errtrace instruments Go code with error return tracing. |
internal
|
|
diff
Package diff provides utilities for comparing strings and slices to produce a readable diff output for tests.
|
Package diff provides utilities for comparing strings and slices to produce a readable diff output for tests. |
pc
Package pc provides access to the program counter to determine the caller of a function.
|
Package pc provides access to the program counter to determine the caller of a function. |
tracetest
Package tracetest provides utilities for errtrace to test error trace output conveniently.
|
Package tracetest provides utilities for errtrace to test error trace output conveniently. |