tracer.go 10.0 KB

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