propagation.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package trace
  2. import (
  3. "net/http"
  4. "github.com/pkg/errors"
  5. "google.golang.org/grpc/metadata"
  6. )
  7. var (
  8. // ErrUnsupportedFormat occurs when the `format` passed to Tracer.Inject() or
  9. // Tracer.Extract() is not recognized by the Tracer implementation.
  10. ErrUnsupportedFormat = errors.New("trace: Unknown or unsupported Inject/Extract format")
  11. // ErrTraceNotFound occurs when the `carrier` passed to
  12. // Tracer.Extract() is valid and uncorrupted but has insufficient
  13. // information to extract a Trace.
  14. ErrTraceNotFound = errors.New("trace: Trace not found in Extract carrier")
  15. // ErrInvalidTrace errors occur when Tracer.Inject() is asked to
  16. // operate on a Trace which it is not prepared to handle (for
  17. // example, since it was created by a different tracer implementation).
  18. ErrInvalidTrace = errors.New("trace: Trace type incompatible with tracer")
  19. // ErrInvalidCarrier errors occur when Tracer.Inject() or Tracer.Extract()
  20. // implementations expect a different type of `carrier` than they are
  21. // given.
  22. ErrInvalidCarrier = errors.New("trace: Invalid Inject/Extract carrier")
  23. // ErrTraceCorrupted occurs when the `carrier` passed to
  24. // Tracer.Extract() is of the expected type but is corrupted.
  25. ErrTraceCorrupted = errors.New("trace: Trace data corrupted in Extract carrier")
  26. )
  27. // BuiltinFormat is used to demarcate the values within package `trace`
  28. // that are intended for use with the Tracer.Inject() and Tracer.Extract()
  29. // methods.
  30. type BuiltinFormat byte
  31. // support format list
  32. const (
  33. // HTTPFormat represents Trace as HTTP header string pairs.
  34. //
  35. // the HTTPFormat format requires that the keys and values
  36. // be valid as HTTP headers as-is (i.e., character casing may be unstable
  37. // and special characters are disallowed in keys, values should be
  38. // URL-escaped, etc).
  39. //
  40. // the carrier must be a `http.Header`.
  41. HTTPFormat BuiltinFormat = iota
  42. // GRPCFormat represents Trace as gRPC metadata.
  43. //
  44. // the carrier must be a `google.golang.org/grpc/metadata.MD`.
  45. GRPCFormat
  46. )
  47. // Carrier propagator must convert generic interface{} to something this
  48. // implement Carrier interface, Trace can use Carrier to represents itself.
  49. type Carrier interface {
  50. Set(key, val string)
  51. Get(key string) string
  52. }
  53. // propagator is responsible for injecting and extracting `Trace` instances
  54. // from a format-specific "carrier"
  55. type propagator interface {
  56. Inject(carrier interface{}) (Carrier, error)
  57. Extract(carrier interface{}) (Carrier, error)
  58. }
  59. type httpPropagator struct{}
  60. type httpCarrier http.Header
  61. func (h httpCarrier) Set(key, val string) {
  62. http.Header(h).Set(key, val)
  63. }
  64. func (h httpCarrier) Get(key string) string {
  65. return http.Header(h).Get(key)
  66. }
  67. func (httpPropagator) Inject(carrier interface{}) (Carrier, error) {
  68. header, ok := carrier.(http.Header)
  69. if !ok {
  70. return nil, ErrInvalidCarrier
  71. }
  72. if header == nil {
  73. return nil, ErrInvalidTrace
  74. }
  75. return httpCarrier(header), nil
  76. }
  77. func (httpPropagator) Extract(carrier interface{}) (Carrier, error) {
  78. header, ok := carrier.(http.Header)
  79. if !ok {
  80. return nil, ErrInvalidCarrier
  81. }
  82. if header == nil {
  83. return nil, ErrTraceNotFound
  84. }
  85. return httpCarrier(header), nil
  86. }
  87. const legacyGRPCKey = "trace"
  88. type grpcPropagator struct{}
  89. type grpcCarrier map[string][]string
  90. func (g grpcCarrier) Get(key string) string {
  91. if v, ok := g[key]; ok && len(v) > 0 {
  92. return v[0]
  93. }
  94. ts := g[legacyGRPCKey]
  95. if len(ts) != 8 {
  96. return ""
  97. }
  98. switch key {
  99. case KeyTraceID:
  100. return ts[0]
  101. case KeyTraceSpanID:
  102. return ts[1]
  103. case KeyTraceParentID:
  104. return ts[2]
  105. case KeyTraceLevel:
  106. return ts[3]
  107. case KeyTraceSampled:
  108. return ts[4]
  109. case KeyTraceCaller:
  110. return ts[5]
  111. }
  112. return ""
  113. }
  114. func (g grpcCarrier) Set(key, val string) {
  115. ts := make([]string, 8)
  116. g[legacyGRPCKey] = ts
  117. switch key {
  118. case KeyTraceID:
  119. ts[0] = val
  120. case KeyTraceSpanID:
  121. ts[1] = val
  122. case KeyTraceParentID:
  123. ts[2] = val
  124. case KeyTraceLevel:
  125. ts[3] = val
  126. case KeyTraceSampled:
  127. ts[4] = val
  128. case KeyTraceCaller:
  129. ts[5] = val
  130. default:
  131. g[key] = append(g[key], val)
  132. }
  133. }
  134. func (grpcPropagator) Inject(carrier interface{}) (Carrier, error) {
  135. md, ok := carrier.(metadata.MD)
  136. if !ok {
  137. return nil, ErrInvalidCarrier
  138. }
  139. if md == nil {
  140. return nil, ErrInvalidTrace
  141. }
  142. return grpcCarrier(md), nil
  143. }
  144. func (grpcPropagator) Extract(carrier interface{}) (Carrier, error) {
  145. md, ok := carrier.(metadata.MD)
  146. if !ok {
  147. return nil, ErrInvalidCarrier
  148. }
  149. if md == nil {
  150. return nil, ErrTraceNotFound
  151. }
  152. return grpcCarrier(md), nil
  153. }