Go
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
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.
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.
func xyz() {...sp := opentracing.StartSpan("operation_name")defer sp.Finish()...}
Creating a (child) Span given an existing (parent) Span
func xyz(parentSpan opentracing.Span, ...) {...sp := opentracing.StartSpan("operation_name",opentracing.ChildOf(parentSpan.Context()))defer sp.Finish()...}
Serializing to the wire
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
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {var serverSpan opentracing.SpanappSpecificOperationName := ...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:
func Customer(order *Order) log.Field {if os.Getenv("ENVIRONMENT") == "dev" {return log.String("customer", order.Customer.ID)}return log.Noop()}
