DEV Community

Bryan Sazon
Bryan Sazon

Posted on

1

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

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay