[![Gitter chat](http://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/opentracing/public) [![Build Status](https://travis-ci.org/opentracing/opentracing-go.svg?branch=master)](https://travis-ci.org/opentracing/opentracing-go) [![GoDoc](https://godoc.org/github.com/opentracing/opentracing-go?status.svg)](http://godoc.org/github.com/opentracing/opentracing-go) [![Sourcegraph Badge](https://sourcegraph.com/github.com/opentracing/opentracing-go/-/badge.svg)](https://sourcegraph.com/github.com/opentracing/opentracing-go?badge) # OpenTracing API for Go This package is a Go platform API for OpenTracing. ## Required Reading In order to understand the Go platform API, one must first be familiar with the [OpenTracing project](https://opentracing.io) and [terminology](https://opentracing.io/specification/) more specifically. ## API overview for those adding instrumentation Everyday consumers of this `opentracing` package really only need to worry about a couple of key abstractions: the `StartSpan` function, the `Span` interface, and binding a `Tracer` at `main()`-time. Here are code snippets demonstrating some important use cases. #### Singleton initialization The simplest starting point is `./default_tracer.go`. As early as possible, call ```go import "github.com/opentracing/opentracing-go" import ".../some_tracing_impl" func main() { opentracing.SetGlobalTracer( // tracing impl specific: some_tracing_impl.New(...), ) ... } ``` #### Non-Singleton initialization If you prefer direct control to singletons, manage ownership of the `opentracing.Tracer` implementation explicitly. #### Creating a Span given an existing Go `context.Context` If you use `context.Context` in your application, OpenTracing's Go library will happily rely on it for `Span` propagation. To start a new (blocking child) `Span`, you can use `StartSpanFromContext`. ```go func xyz(ctx context.Context, ...) { ... span, ctx := opentracing.StartSpanFromContext(ctx, "operation_name") defer span.Finish() span.LogFields( log.String("event", "soft error"), log.String("type", "cache timeout"), log.Int("waited.millis", 1500)) ... } ``` #### Starting an empty trace by creating a "root span" It's always possible to create a "root" `Span` with no parent or other causal reference. ```go func xyz() { ... sp := opentracing.StartSpan("operation_name") defer sp.Finish() ... } ``` #### Creating a (child) Span given an existing (parent) Span ```go func xyz(parentSpan opentracing.Span, ...) { ... sp := opentracing.StartSpan( "operation_name", opentracing.ChildOf(parentSpan.Context())) defer sp.Finish() ... } ``` #### Serializing to the wire ```go func makeSomeRequest(ctx context.Context) ... { if span := opentracing.SpanFromContext(ctx); span != nil { httpClient := &http.Client{} httpReq, _ := http.NewRequest("GET", "http://myservice/", nil) // Transmit the span's TraceContext as HTTP headers on our // outbound request. opentracing.GlobalTracer().Inject( span.Context(), opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(httpReq.Header)) resp, err := httpClient.Do(httpReq) ... } ... } ``` #### Deserializing from the wire ```go http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { var serverSpan opentracing.Span appSpecificOperationName := ... wireContext, err := opentracing.GlobalTracer().Extract( opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header)) if err != nil { // Optionally record something about err here } // Create the span referring to the RPC client if available. // If wireContext == nil, a root span will be created. serverSpan = opentracing.StartSpan( appSpecificOperationName, ext.RPCServerOption(wireContext)) defer serverSpan.Finish() ctx := opentracing.ContextWithSpan(context.Background(), serverSpan) ... } ``` #### Conditionally capture a field using `log.Noop` In some situations, you may want to dynamically decide whether or not to log a field. For example, you may want to capture additional data, such as a customer ID, in non-production environments: ```go func Customer(order *Order) log.Field { if os.Getenv("ENVIRONMENT") == "dev" { return log.String("customer", order.Customer.ID) } return log.Noop() } ``` #### Goroutine-safety The entire public API is goroutine-safe and does not require external synchronization. ## API pointers for those implementing a tracing system Tracing system implementors may be able to reuse or copy-paste-modify the `basictracer` package, found [here](https://github.com/opentracing/basictracer-go). In particular, see `basictracer.New(...)`. ## API compatibility For the time being, "mild" backwards-incompatible changes may be made without changing the major version number. As OpenTracing and `opentracing-go` mature, backwards compatibility will become more of a priority. ## Tracer test suite A test suite is available in the [harness](https://godoc.org/github.com/opentracing/opentracing-go/harness) package that can assist Tracer implementors to assert that their Tracer is working correctly. ## Licensing [Apache 2.0 License](./LICENSE).