propagation.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package opentracing
  2. import (
  3. "errors"
  4. "net/http"
  5. )
  6. ///////////////////////////////////////////////////////////////////////////////
  7. // CORE PROPAGATION INTERFACES:
  8. ///////////////////////////////////////////////////////////////////////////////
  9. var (
  10. // ErrUnsupportedFormat occurs when the `format` passed to Tracer.Inject() or
  11. // Tracer.Extract() is not recognized by the Tracer implementation.
  12. ErrUnsupportedFormat = errors.New("opentracing: Unknown or unsupported Inject/Extract format")
  13. // ErrSpanContextNotFound occurs when the `carrier` passed to
  14. // Tracer.Extract() is valid and uncorrupted but has insufficient
  15. // information to extract a SpanContext.
  16. ErrSpanContextNotFound = errors.New("opentracing: SpanContext not found in Extract carrier")
  17. // ErrInvalidSpanContext errors occur when Tracer.Inject() is asked to
  18. // operate on a SpanContext which it is not prepared to handle (for
  19. // example, since it was created by a different tracer implementation).
  20. ErrInvalidSpanContext = errors.New("opentracing: SpanContext type incompatible with tracer")
  21. // ErrInvalidCarrier errors occur when Tracer.Inject() or Tracer.Extract()
  22. // implementations expect a different type of `carrier` than they are
  23. // given.
  24. ErrInvalidCarrier = errors.New("opentracing: Invalid Inject/Extract carrier")
  25. // ErrSpanContextCorrupted occurs when the `carrier` passed to
  26. // Tracer.Extract() is of the expected type but is corrupted.
  27. ErrSpanContextCorrupted = errors.New("opentracing: SpanContext data corrupted in Extract carrier")
  28. )
  29. ///////////////////////////////////////////////////////////////////////////////
  30. // BUILTIN PROPAGATION FORMATS:
  31. ///////////////////////////////////////////////////////////////////////////////
  32. // BuiltinFormat is used to demarcate the values within package `opentracing`
  33. // that are intended for use with the Tracer.Inject() and Tracer.Extract()
  34. // methods.
  35. type BuiltinFormat byte
  36. const (
  37. // Binary represents SpanContexts as opaque binary data.
  38. //
  39. // For Tracer.Inject(): the carrier must be an `io.Writer`.
  40. //
  41. // For Tracer.Extract(): the carrier must be an `io.Reader`.
  42. Binary BuiltinFormat = iota
  43. // TextMap represents SpanContexts as key:value string pairs.
  44. //
  45. // Unlike HTTPHeaders, the TextMap format does not restrict the key or
  46. // value character sets in any way.
  47. //
  48. // For Tracer.Inject(): the carrier must be a `TextMapWriter`.
  49. //
  50. // For Tracer.Extract(): the carrier must be a `TextMapReader`.
  51. TextMap
  52. // HTTPHeaders represents SpanContexts as HTTP header string pairs.
  53. //
  54. // Unlike TextMap, the HTTPHeaders format requires that the keys and values
  55. // be valid as HTTP headers as-is (i.e., character casing may be unstable
  56. // and special characters are disallowed in keys, values should be
  57. // URL-escaped, etc).
  58. //
  59. // For Tracer.Inject(): the carrier must be a `TextMapWriter`.
  60. //
  61. // For Tracer.Extract(): the carrier must be a `TextMapReader`.
  62. //
  63. // See HTTPHeadersCarrier for an implementation of both TextMapWriter
  64. // and TextMapReader that defers to an http.Header instance for storage.
  65. // For example, Inject():
  66. //
  67. // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
  68. // err := span.Tracer().Inject(
  69. // span.Context(), opentracing.HTTPHeaders, carrier)
  70. //
  71. // Or Extract():
  72. //
  73. // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
  74. // clientContext, err := tracer.Extract(
  75. // opentracing.HTTPHeaders, carrier)
  76. //
  77. HTTPHeaders
  78. )
  79. // TextMapWriter is the Inject() carrier for the TextMap builtin format. With
  80. // it, the caller can encode a SpanContext for propagation as entries in a map
  81. // of unicode strings.
  82. type TextMapWriter interface {
  83. // Set a key:value pair to the carrier. Multiple calls to Set() for the
  84. // same key leads to undefined behavior.
  85. //
  86. // NOTE: The backing store for the TextMapWriter may contain data unrelated
  87. // to SpanContext. As such, Inject() and Extract() implementations that
  88. // call the TextMapWriter and TextMapReader interfaces must agree on a
  89. // prefix or other convention to distinguish their own key:value pairs.
  90. Set(key, val string)
  91. }
  92. // TextMapReader is the Extract() carrier for the TextMap builtin format. With it,
  93. // the caller can decode a propagated SpanContext as entries in a map of
  94. // unicode strings.
  95. type TextMapReader interface {
  96. // ForeachKey returns TextMap contents via repeated calls to the `handler`
  97. // function. If any call to `handler` returns a non-nil error, ForeachKey
  98. // terminates and returns that error.
  99. //
  100. // NOTE: The backing store for the TextMapReader may contain data unrelated
  101. // to SpanContext. As such, Inject() and Extract() implementations that
  102. // call the TextMapWriter and TextMapReader interfaces must agree on a
  103. // prefix or other convention to distinguish their own key:value pairs.
  104. //
  105. // The "foreach" callback pattern reduces unnecessary copying in some cases
  106. // and also allows implementations to hold locks while the map is read.
  107. ForeachKey(handler func(key, val string) error) error
  108. }
  109. // TextMapCarrier allows the use of regular map[string]string
  110. // as both TextMapWriter and TextMapReader.
  111. type TextMapCarrier map[string]string
  112. // ForeachKey conforms to the TextMapReader interface.
  113. func (c TextMapCarrier) ForeachKey(handler func(key, val string) error) error {
  114. for k, v := range c {
  115. if err := handler(k, v); err != nil {
  116. return err
  117. }
  118. }
  119. return nil
  120. }
  121. // Set implements Set() of opentracing.TextMapWriter
  122. func (c TextMapCarrier) Set(key, val string) {
  123. c[key] = val
  124. }
  125. // HTTPHeadersCarrier satisfies both TextMapWriter and TextMapReader.
  126. //
  127. // Example usage for server side:
  128. //
  129. // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
  130. // clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier)
  131. //
  132. // Example usage for client side:
  133. //
  134. // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
  135. // err := tracer.Inject(
  136. // span.Context(),
  137. // opentracing.HTTPHeaders,
  138. // carrier)
  139. //
  140. type HTTPHeadersCarrier http.Header
  141. // Set conforms to the TextMapWriter interface.
  142. func (c HTTPHeadersCarrier) Set(key, val string) {
  143. h := http.Header(c)
  144. h.Set(key, val)
  145. }
  146. // ForeachKey conforms to the TextMapReader interface.
  147. func (c HTTPHeadersCarrier) ForeachKey(handler func(key, val string) error) error {
  148. for k, vals := range c {
  149. for _, v := range vals {
  150. if err := handler(k, v); err != nil {
  151. return err
  152. }
  153. }
  154. }
  155. return nil
  156. }