tracer.go 10.0 KB

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