...
1[](https://gitter.im/opentracing/public) [](https://travis-ci.org/opentracing/opentracing-go) [](http://godoc.org/github.com/opentracing/opentracing-go)
2[](https://sourcegraph.com/github.com/opentracing/opentracing-go?badge)
3
4# OpenTracing API for Go
5
6This package is a Go platform API for OpenTracing.
7
8## Required Reading
9
10In order to understand the Go platform API, one must first be familiar with the
11[OpenTracing project](https://opentracing.io) and
12[terminology](https://opentracing.io/specification/) more specifically.
13
14## API overview for those adding instrumentation
15
16Everyday consumers of this `opentracing` package really only need to worry
17about a couple of key abstractions: the `StartSpan` function, the `Span`
18interface, and binding a `Tracer` at `main()`-time. Here are code snippets
19demonstrating some important use cases.
20
21#### Singleton initialization
22
23The simplest starting point is `./default_tracer.go`. As early as possible, call
24
25```go
26 import "github.com/opentracing/opentracing-go"
27 import ".../some_tracing_impl"
28
29 func main() {
30 opentracing.SetGlobalTracer(
31 // tracing impl specific:
32 some_tracing_impl.New(...),
33 )
34 ...
35 }
36```
37
38#### Non-Singleton initialization
39
40If you prefer direct control to singletons, manage ownership of the
41`opentracing.Tracer` implementation explicitly.
42
43#### Creating a Span given an existing Go `context.Context`
44
45If you use `context.Context` in your application, OpenTracing's Go library will
46happily rely on it for `Span` propagation. To start a new (blocking child)
47`Span`, you can use `StartSpanFromContext`.
48
49```go
50 func xyz(ctx context.Context, ...) {
51 ...
52 span, ctx := opentracing.StartSpanFromContext(ctx, "operation_name")
53 defer span.Finish()
54 span.LogFields(
55 log.String("event", "soft error"),
56 log.String("type", "cache timeout"),
57 log.Int("waited.millis", 1500))
58 ...
59 }
60```
61
62#### Starting an empty trace by creating a "root span"
63
64It's always possible to create a "root" `Span` with no parent or other causal
65reference.
66
67```go
68 func xyz() {
69 ...
70 sp := opentracing.StartSpan("operation_name")
71 defer sp.Finish()
72 ...
73 }
74```
75
76#### Creating a (child) Span given an existing (parent) Span
77
78```go
79 func xyz(parentSpan opentracing.Span, ...) {
80 ...
81 sp := opentracing.StartSpan(
82 "operation_name",
83 opentracing.ChildOf(parentSpan.Context()))
84 defer sp.Finish()
85 ...
86 }
87```
88
89#### Serializing to the wire
90
91```go
92 func makeSomeRequest(ctx context.Context) ... {
93 if span := opentracing.SpanFromContext(ctx); span != nil {
94 httpClient := &http.Client{}
95 httpReq, _ := http.NewRequest("GET", "http://myservice/", nil)
96
97 // Transmit the span's TraceContext as HTTP headers on our
98 // outbound request.
99 opentracing.GlobalTracer().Inject(
100 span.Context(),
101 opentracing.HTTPHeaders,
102 opentracing.HTTPHeadersCarrier(httpReq.Header))
103
104 resp, err := httpClient.Do(httpReq)
105 ...
106 }
107 ...
108 }
109```
110
111#### Deserializing from the wire
112
113```go
114 http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
115 var serverSpan opentracing.Span
116 appSpecificOperationName := ...
117 wireContext, err := opentracing.GlobalTracer().Extract(
118 opentracing.HTTPHeaders,
119 opentracing.HTTPHeadersCarrier(req.Header))
120 if err != nil {
121 // Optionally record something about err here
122 }
123
124 // Create the span referring to the RPC client if available.
125 // If wireContext == nil, a root span will be created.
126 serverSpan = opentracing.StartSpan(
127 appSpecificOperationName,
128 ext.RPCServerOption(wireContext))
129
130 defer serverSpan.Finish()
131
132 ctx := opentracing.ContextWithSpan(context.Background(), serverSpan)
133 ...
134 }
135```
136
137#### Conditionally capture a field using `log.Noop`
138
139In some situations, you may want to dynamically decide whether or not
140to log a field. For example, you may want to capture additional data,
141such as a customer ID, in non-production environments:
142
143```go
144 func Customer(order *Order) log.Field {
145 if os.Getenv("ENVIRONMENT") == "dev" {
146 return log.String("customer", order.Customer.ID)
147 }
148 return log.Noop()
149 }
150```
151
152#### Goroutine-safety
153
154The entire public API is goroutine-safe and does not require external
155synchronization.
156
157## API pointers for those implementing a tracing system
158
159Tracing 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(...)`.
160
161## API compatibility
162
163For 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.
164
165## Tracer test suite
166
167A 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.
168
169## Licensing
170
171[Apache 2.0 License](./LICENSE).
View as plain text