Go: Error handling and tracing with OpenCensus supported platforms
Tags: go, opencensus, jaeger, stackdriver
Published: 2019-07-15 07:58:41

---
title: Go: Error handling and tracing with OpenCensus supported platforms
published: true
description: My Go package for handling and tracing errors
tags: go, opencensus, jaeger, stackdriver
---

[![GoDoc](https://godoc.org/github.com/bzon/errors?status.svg)](http://godoc.org/github.com/bzon/errors)

# 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.

* https://cloud.google.com/trace/docs/viewing-details
* https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry
* https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogEntrySourceLocation

## Goals

Add OpenCensus trace attributes when creating a new error.

## Basic Usage

Drop-in replacement. Creating an error.

```golang
err := errors.New("msg") // Wrap .. Wrapf .. Errof ..
```

Creating an error with context useful for monitoring.

```golang
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)
	}
}
```

Output

```txt
main.main
/Users/jb/Golang/src/github.com/bzon/errors/examples/main.go
15
d2d2b126d0474947821106525e32b6e0
1644b4b9be26c929
```

## How I use it

```go
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
}
```

You can also see the source code of the example server in [github](https://github.com/bzon/errors/blob/master/examples/main.go).


Useful for logging error with tracing context.

```console
$ 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"
}
```

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

![img](https://github.com/bzon/errors/raw/master/jaeger-error-trace.png)