Skip to content
/ xtrace Public

A simple library to extract traces from golang's xerrors

License

Notifications You must be signed in to change notification settings

ollien/xtrace

Repository files navigation

xtrace

Build Status

xerrors is pretty awesome. It allows you to wrap your errors and provide more context. Sadly, one of the features of it that isn't really available until Go 1.13 is the ability to print out a stack trace. No longer!

Installation

go get -u github.com/ollien/xtrace

Basic Usage

The following example will print a trace of all of the wrapped errors to stderr.

package main

import (
	"errors"

	"github.com/ollien/xtrace"
	"golang.org/x/xerrors"
)

func main() {
	baseErr := errors.New("aw shucks, something broke")
	err2 := xerrors.Errorf("things went wrong!: %w", baseErr)

	traceErr := xtrace.Trace(err2)
	if traceErr != nil {
		panic("can not trace")
	}
	// aw shucks, something broke
	// things went wrong!
	// github.com/ollien/xtrace.ExampleTracer_Format
	//    /home/nick/Documents/code/xtrace/example.go:12
}

If more customization is desired, one can use a Tracer. One of Tracer's key features is its compatibility with fmt.

// ...
tracer, err := xtrace.NewTracer(err2)
if err != nil {
	panic("can not make tracer")
}

fmt.Printf("%v", tracer)
// aw shucks, something broke
// things went wrong!

That's nice, and we can see a trace of all of our errors, but xerrors provides much more for information for us. To get this information, all we have to do is change our format string to %+v.

// ... (repeated from above)

fmt.Printf("%+v", tracer)
// aw shucks, something broke
// things went wrong!
// github.com/ollien/xtrace.ExampleTracer_Format
//    /home/nick/Documents/code/xtrace/example.go:18

If you don't want to use fmt and just want to get this trace as a string, you can simply use ReadNext to get the next error in the trace. (Tracer also implements io.Reader if you prefer to use that.)

// ... (repeated from above)

output, err := tracer.ReadNext()
if err != nil {
	panic("can not read from tracer")
}

fmt.Println(output)
// aw shucks, something broke

See the docs for more usages.

Customization

Output customization is one of the explicit goals of xtrace. For instance, if you wish to flip the output of your trace so that the newest errors are on top (i.e. with the root cause at the bottom), all you have to do is the following.

tracer, err := NewTracer(err, Ordering(NewestFirstOrdering))

You can also set up custom formatters for your traces. There are several included (such as NestedMessageFormatter and NilFormatter). If you want, you can also write your own formatter by simply implementing the TraceFormatter interface. For instance, if you wanted to make sure that everyone hears your errors, you can make all of them capitalized.

type capsFormatter struct{}

func (formatter capsFormatter) FormatTrace(previous []string, message string) string {
	return strings.ToUpper(message)
}

You can then set a Tracer's formatter by doing

tracer, err := NewTracer(err, Formatter(capsFormatter{}))

If you wish to combine your loud errors with newest-first ordering you can pass them both as arguments to NewTracer.

tracer, err := NewTracer(err, Ordering(NewestFirstOrdering), Formatter(capsFormatter{}))

See the docs for more details.

A note about Go 1.13+

This package does work on Go 1.13+ with the new errors package. However, the solidified version of the new errors does not include the Formatter interface that xerrors did. While it is still possible for this package to work without it, the traces will contain the full contents of the error, including the wrapped content and notably, line numbers do not work. For instance

package main

import (
	"fmt"
	"errors"

	"github.com/ollien/xtrace"
)

func main() {
	baseErr := errors.New("aw shucks, something broke")
	err2 := fmt.Errorf("things went wrong!: %w", baseErr)

	traceErr := xtrace.Trace(err2)
	if traceErr != nil {
		panic("can not trace")
	}
	// aw shucks, something broke
	// things went wrong!: aw shucks, something broke
}

This makes the traces a bit redundant, and a bit more useless as they do not contain line numbers. This is certainly unfortunate, as one of the design goals of this package was to not need to use this package to wrap your errors, much like https://github.com/pkg/errors.

Again, this package will still work with the new errors package, but it cannot work as it once was intended to. A shame, truly. You can always still use xerrors if you're so inclined, though.

About

A simple library to extract traces from golang's xerrors

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages