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