blob: 715f0cedfb60ef71a4fea034e947fe2d50bf5c45 [file] [log] [blame]
Girish Gowdra631ef3d2020-06-15 10:45:52 -07001package opentracing
2
3import "time"
4
5// Tracer is a simple, thin interface for Span creation and SpanContext
6// propagation.
7type Tracer interface {
8
9 // Create, start, and return a new Span with the given `operationName` and
10 // incorporate the given StartSpanOption `opts`. (Note that `opts` borrows
11 // from the "functional options" pattern, per
12 // http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis)
13 //
14 // A Span with no SpanReference options (e.g., opentracing.ChildOf() or
15 // opentracing.FollowsFrom()) becomes the root of its own trace.
16 //
17 // Examples:
18 //
19 // var tracer opentracing.Tracer = ...
20 //
21 // // The root-span case:
22 // sp := tracer.StartSpan("GetFeed")
23 //
24 // // The vanilla child span case:
25 // sp := tracer.StartSpan(
26 // "GetFeed",
27 // opentracing.ChildOf(parentSpan.Context()))
28 //
29 // // All the bells and whistles:
30 // sp := tracer.StartSpan(
31 // "GetFeed",
32 // opentracing.ChildOf(parentSpan.Context()),
33 // opentracing.Tag{"user_agent", loggedReq.UserAgent},
34 // opentracing.StartTime(loggedReq.Timestamp),
35 // )
36 //
37 StartSpan(operationName string, opts ...StartSpanOption) Span
38
39 // Inject() takes the `sm` SpanContext instance and injects it for
40 // propagation within `carrier`. The actual type of `carrier` depends on
41 // the value of `format`.
42 //
43 // OpenTracing defines a common set of `format` values (see BuiltinFormat),
44 // and each has an expected carrier type.
45 //
46 // Other packages may declare their own `format` values, much like the keys
47 // used by `context.Context` (see https://godoc.org/context#WithValue).
48 //
49 // Example usage (sans error handling):
50 //
51 // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
52 // err := tracer.Inject(
53 // span.Context(),
54 // opentracing.HTTPHeaders,
55 // carrier)
56 //
57 // NOTE: All opentracing.Tracer implementations MUST support all
58 // BuiltinFormats.
59 //
60 // Implementations may return opentracing.ErrUnsupportedFormat if `format`
61 // is not supported by (or not known by) the implementation.
62 //
63 // Implementations may return opentracing.ErrInvalidCarrier or any other
64 // implementation-specific error if the format is supported but injection
65 // fails anyway.
66 //
67 // See Tracer.Extract().
68 Inject(sm SpanContext, format interface{}, carrier interface{}) error
69
70 // Extract() returns a SpanContext instance given `format` and `carrier`.
71 //
72 // OpenTracing defines a common set of `format` values (see BuiltinFormat),
73 // and each has an expected carrier type.
74 //
75 // Other packages may declare their own `format` values, much like the keys
76 // used by `context.Context` (see
77 // https://godoc.org/golang.org/x/net/context#WithValue).
78 //
79 // Example usage (with StartSpan):
80 //
81 //
82 // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
83 // clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier)
84 //
85 // // ... assuming the ultimate goal here is to resume the trace with a
86 // // server-side Span:
87 // var serverSpan opentracing.Span
88 // if err == nil {
89 // span = tracer.StartSpan(
90 // rpcMethodName, ext.RPCServerOption(clientContext))
91 // } else {
92 // span = tracer.StartSpan(rpcMethodName)
93 // }
94 //
95 //
96 // NOTE: All opentracing.Tracer implementations MUST support all
97 // BuiltinFormats.
98 //
99 // Return values:
100 // - A successful Extract returns a SpanContext instance and a nil error
101 // - If there was simply no SpanContext to extract in `carrier`, Extract()
102 // returns (nil, opentracing.ErrSpanContextNotFound)
103 // - If `format` is unsupported or unrecognized, Extract() returns (nil,
104 // opentracing.ErrUnsupportedFormat)
105 // - If there are more fundamental problems with the `carrier` object,
106 // Extract() may return opentracing.ErrInvalidCarrier,
107 // opentracing.ErrSpanContextCorrupted, or implementation-specific
108 // errors.
109 //
110 // See Tracer.Inject().
111 Extract(format interface{}, carrier interface{}) (SpanContext, error)
112}
113
114// StartSpanOptions allows Tracer.StartSpan() callers and implementors a
115// mechanism to override the start timestamp, specify Span References, and make
116// a single Tag or multiple Tags available at Span start time.
117//
118// StartSpan() callers should look at the StartSpanOption interface and
119// implementations available in this package.
120//
121// Tracer implementations can convert a slice of `StartSpanOption` instances
122// into a `StartSpanOptions` struct like so:
123//
124// func StartSpan(opName string, opts ...opentracing.StartSpanOption) {
125// sso := opentracing.StartSpanOptions{}
126// for _, o := range opts {
127// o.Apply(&sso)
128// }
129// ...
130// }
131//
132type StartSpanOptions struct {
133 // Zero or more causal references to other Spans (via their SpanContext).
134 // If empty, start a "root" Span (i.e., start a new trace).
135 References []SpanReference
136
137 // StartTime overrides the Span's start time, or implicitly becomes
138 // time.Now() if StartTime.IsZero().
139 StartTime time.Time
140
141 // Tags may have zero or more entries; the restrictions on map values are
142 // identical to those for Span.SetTag(). May be nil.
143 //
144 // If specified, the caller hands off ownership of Tags at
145 // StartSpan() invocation time.
146 Tags map[string]interface{}
147}
148
149// StartSpanOption instances (zero or more) may be passed to Tracer.StartSpan.
150//
151// StartSpanOption borrows from the "functional options" pattern, per
152// http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
153type StartSpanOption interface {
154 Apply(*StartSpanOptions)
155}
156
157// SpanReferenceType is an enum type describing different categories of
158// relationships between two Spans. If Span-2 refers to Span-1, the
159// SpanReferenceType describes Span-1 from Span-2's perspective. For example,
160// ChildOfRef means that Span-1 created Span-2.
161//
162// NOTE: Span-1 and Span-2 do *not* necessarily depend on each other for
163// completion; e.g., Span-2 may be part of a background job enqueued by Span-1,
164// or Span-2 may be sitting in a distributed queue behind Span-1.
165type SpanReferenceType int
166
167const (
168 // ChildOfRef refers to a parent Span that caused *and* somehow depends
169 // upon the new child Span. Often (but not always), the parent Span cannot
170 // finish until the child Span does.
171 //
172 // An timing diagram for a ChildOfRef that's blocked on the new Span:
173 //
174 // [-Parent Span---------]
175 // [-Child Span----]
176 //
177 // See http://opentracing.io/spec/
178 //
179 // See opentracing.ChildOf()
180 ChildOfRef SpanReferenceType = iota
181
182 // FollowsFromRef refers to a parent Span that does not depend in any way
183 // on the result of the new child Span. For instance, one might use
184 // FollowsFromRefs to describe pipeline stages separated by queues,
185 // or a fire-and-forget cache insert at the tail end of a web request.
186 //
187 // A FollowsFromRef Span is part of the same logical trace as the new Span:
188 // i.e., the new Span is somehow caused by the work of its FollowsFromRef.
189 //
190 // All of the following could be valid timing diagrams for children that
191 // "FollowFrom" a parent.
192 //
193 // [-Parent Span-] [-Child Span-]
194 //
195 //
196 // [-Parent Span--]
197 // [-Child Span-]
198 //
199 //
200 // [-Parent Span-]
201 // [-Child Span-]
202 //
203 // See http://opentracing.io/spec/
204 //
205 // See opentracing.FollowsFrom()
206 FollowsFromRef
207)
208
209// SpanReference is a StartSpanOption that pairs a SpanReferenceType and a
210// referenced SpanContext. See the SpanReferenceType documentation for
211// supported relationships. If SpanReference is created with
212// ReferencedContext==nil, it has no effect. Thus it allows for a more concise
213// syntax for starting spans:
214//
215// sc, _ := tracer.Extract(someFormat, someCarrier)
216// span := tracer.StartSpan("operation", opentracing.ChildOf(sc))
217//
218// The `ChildOf(sc)` option above will not panic if sc == nil, it will just
219// not add the parent span reference to the options.
220type SpanReference struct {
221 Type SpanReferenceType
222 ReferencedContext SpanContext
223}
224
225// Apply satisfies the StartSpanOption interface.
226func (r SpanReference) Apply(o *StartSpanOptions) {
227 if r.ReferencedContext != nil {
228 o.References = append(o.References, r)
229 }
230}
231
232// ChildOf returns a StartSpanOption pointing to a dependent parent span.
233// If sc == nil, the option has no effect.
234//
235// See ChildOfRef, SpanReference
236func ChildOf(sc SpanContext) SpanReference {
237 return SpanReference{
238 Type: ChildOfRef,
239 ReferencedContext: sc,
240 }
241}
242
243// FollowsFrom returns a StartSpanOption pointing to a parent Span that caused
244// the child Span but does not directly depend on its result in any way.
245// If sc == nil, the option has no effect.
246//
247// See FollowsFromRef, SpanReference
248func FollowsFrom(sc SpanContext) SpanReference {
249 return SpanReference{
250 Type: FollowsFromRef,
251 ReferencedContext: sc,
252 }
253}
254
255// StartTime is a StartSpanOption that sets an explicit start timestamp for the
256// new Span.
257type StartTime time.Time
258
259// Apply satisfies the StartSpanOption interface.
260func (t StartTime) Apply(o *StartSpanOptions) {
261 o.StartTime = time.Time(t)
262}
263
264// Tags are a generic map from an arbitrary string key to an opaque value type.
265// The underlying tracing system is responsible for interpreting and
266// serializing the values.
267type Tags map[string]interface{}
268
269// Apply satisfies the StartSpanOption interface.
270func (t Tags) Apply(o *StartSpanOptions) {
271 if o.Tags == nil {
272 o.Tags = make(map[string]interface{})
273 }
274 for k, v := range t {
275 o.Tags[k] = v
276 }
277}
278
279// Tag may be passed as a StartSpanOption to add a tag to new spans,
280// or its Set method may be used to apply the tag to an existing Span,
281// for example:
282//
283// tracer.StartSpan("opName", Tag{"Key", value})
284//
285// or
286//
287// Tag{"key", value}.Set(span)
288type Tag struct {
289 Key string
290 Value interface{}
291}
292
293// Apply satisfies the StartSpanOption interface.
294func (t Tag) Apply(o *StartSpanOptions) {
295 if o.Tags == nil {
296 o.Tags = make(map[string]interface{})
297 }
298 o.Tags[t.Key] = t.Value
299}
300
301// Set applies the tag to an existing Span.
302func (t Tag) Set(s Span) {
303 s.SetTag(t.Key, t.Value)
304}