DEV Community

Bryan Sazon
Bryan Sazon

Posted on

Go: Error handling and tracing with OpenCensus supported platforms

GoDoc

errors

I want to share my drop-in replacement for github.com/pkg/errors.

I created this package to help my current team view the details of my Stackdriver traces with Stackdriver logs.

Goals

Add OpenCensus trace attributes when creating a new error.

Basic Usage

Drop-in replacement. Creating an error.

err := errors.New("msg") // Wrap .. Wrapf .. Errof .. 
Enter fullscreen mode Exit fullscreen mode

Creating an error with context useful for monitoring.

func main() { _, span := trace.StartSpan(context.Background(), "ExampleNewT") defer span.End() err := errors.NewT(span, "error") fmt.Println(err) if erctx, ok := err.(errors.Error); ok { fmt.Println(erctx.SourceLocation().Function) fmt.Println(erctx.SourceLocation().File) fmt.Println(erctx.SourceLocation().Line) fmt.Println(erctx.TraceContext().TraceID) fmt.Println(erctx.TraceContext().SpanID) } } 
Enter fullscreen mode Exit fullscreen mode

Output

main.main /Users/jb/Golang/src/github.com/bzon/errors/examples/main.go 15 d2d2b126d0474947821106525e32b6e0 1644b4b9be26c929 
Enter fullscreen mode Exit fullscreen mode

How I use it

package main import ( "context" "flag" "fmt" "os" "time" "contrib.go.opencensus.io/exporter/jaeger" "contrib.go.opencensus.io/exporter/stackdriver" "github.com/bzon/errors" "github.com/go-kit/kit/log" "go.opencensus.io/trace" ) func main() { var useStackDriver = flag.Bool("stack-driver", false, "Use stackdriver instead of jaeger.") flag.Parse() // logging var logger log.Logger { logger = log.NewJSONLogger(log.NewSyncWriter(os.Stdout)) logger = log.With(logger, "ts", log.DefaultTimestamp, "caller", log.DefaultCaller) } // tracing switch { case *useStackDriver: // stackdriver sd, err := stackdriver.NewExporter(stackdriver.Options{ ProjectID: os.Getenv("GCP_PROJECT"), }) if err != nil { panic(fmt.Sprintf("Failed to create the stackdriver exporter: %v", err)) } defer sd.Flush() trace.RegisterExporter(sd) default: je, err := jaeger.NewExporter(jaeger.Options{ AgentEndpoint: "localhost:6831", CollectorEndpoint: "http://localhost:14268/api/traces", ServiceName: "erroring-service", }) if err != nil { panic(fmt.Sprintf("Failed to create the Jaeger exporter: %v", err)) } trace.RegisterExporter(je) } trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) for { workerr := work(context.Background(), logger) if ec, ok := workerr.(errors.Error); ok { logger.Log( "message", ec.Error(), "logging.googleapis.com/spanId", ec.TraceContext().SpanID, "logging.googleapis.com/trace", ec.TraceContext().TraceID, "logging.googleapis.com/sourceLocation", ec.SourceLocation(), ) } time.Sleep(3 * time.Second) } } func work(ctx context.Context, logger log.Logger) error { _, span := trace.StartSpan(ctx, "work") defer span.End() // error with context err := errors.NewT(span, "error") return err } 
Enter fullscreen mode Exit fullscreen mode

You can also see the source code of the example server in github.

Useful for logging error with tracing context.

$ go run main.go | jq '.'  { "caller": "main.go:38", "logging.googleapis.com/sourceLocation": { "function": "main.work", "file": "/Users/jb/Golang/src/github.com/bzon/errors/examples/main.go", "line": 55 }, "logging.googleapis.com/spanId": "1eb9494ab1a7831c", "logging.googleapis.com/trace": "e97499da53ef2a8fdf9681beddbe3d64", "message": "error", "ts": "2019-07-15T09:37:06.885078+02:00" } 
Enter fullscreen mode Exit fullscreen mode

Automatic annotations will be applied in supported tracing platform for OpenCensus.

img

Top comments (0)