5.6 KiB
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 and terminology 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
import "github.com/opentracing/opentracing-go"
import ".../some_tracing_impl"
func main() {
.SetGlobalTracer(
opentracing// tracing impl specific:
.New(...),
some_tracing_impl)
...
}
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, ...) {
...
, ctx := opentracing.StartSpanFromContext(ctx, "operation_name")
spandefer span.Finish()
.LogFields(
span.String("event", "soft error"),
log.String("type", "cache timeout"),
log.Int("waited.millis", 1500))
log...
}
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() {
...
:= opentracing.StartSpan("operation_name")
sp defer sp.Finish()
...
}
Creating a (child) Span given an existing (parent) Span
func xyz(parentSpan opentracing.Span, ...) {
...
:= opentracing.StartSpan(
sp "operation_name",
.ChildOf(parentSpan.Context()))
opentracingdefer sp.Finish()
...
}
Serializing to the wire
func makeSomeRequest(ctx context.Context) ... {
if span := opentracing.SpanFromContext(ctx); span != nil {
:= &http.Client{}
httpClient , _ := http.NewRequest("GET", "http://myservice/", nil)
httpReq
// Transmit the span's TraceContext as HTTP headers on our
// outbound request.
.GlobalTracer().Inject(
opentracing.Context(),
span.HTTPHeaders,
opentracing.HTTPHeadersCarrier(httpReq.Header))
opentracing
, err := httpClient.Do(httpReq)
resp...
}
...
}
Deserializing from the wire
.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
httpvar serverSpan opentracing.Span
:= ...
appSpecificOperationName , err := opentracing.GlobalTracer().Extract(
wireContext.HTTPHeaders,
opentracing.HTTPHeadersCarrier(req.Header))
opentracingif 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.
= opentracing.StartSpan(
serverSpan ,
appSpecificOperationName.RPCServerOption(wireContext))
ext
defer serverSpan.Finish()
:= opentracing.ContextWithSpan(context.Background(), serverSpan)
ctx ...
}
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()
}
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. 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 package that can assist Tracer implementors to assert that their Tracer is working correctly.