propagation.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package propagation // import "go.opentelemetry.io/otel/propagation"
  4. import (
  5. "context"
  6. "net/http"
  7. )
  8. // TextMapCarrier is the storage medium used by a TextMapPropagator.
  9. // See ValuesGetter for how a TextMapCarrier can get multiple values for a key.
  10. type TextMapCarrier interface {
  11. // DO NOT CHANGE: any modification will not be backwards compatible and
  12. // must never be done outside of a new major release.
  13. // Get returns the value associated with the passed key.
  14. Get(key string) string
  15. // DO NOT CHANGE: any modification will not be backwards compatible and
  16. // must never be done outside of a new major release.
  17. // Set stores the key-value pair.
  18. Set(key, value string)
  19. // DO NOT CHANGE: any modification will not be backwards compatible and
  20. // must never be done outside of a new major release.
  21. // Keys lists the keys stored in this carrier.
  22. Keys() []string
  23. // DO NOT CHANGE: any modification will not be backwards compatible and
  24. // must never be done outside of a new major release.
  25. }
  26. // ValuesGetter can return multiple values for a single key,
  27. // with contrast to TextMapCarrier.Get which returns a single value.
  28. type ValuesGetter interface {
  29. // DO NOT CHANGE: any modification will not be backwards compatible and
  30. // must never be done outside of a new major release.
  31. // Values returns all values associated with the passed key.
  32. Values(key string) []string
  33. // DO NOT CHANGE: any modification will not be backwards compatible and
  34. // must never be done outside of a new major release.
  35. }
  36. // MapCarrier is a TextMapCarrier that uses a map held in memory as a storage
  37. // medium for propagated key-value pairs.
  38. type MapCarrier map[string]string
  39. // Compile time check that MapCarrier implements the TextMapCarrier.
  40. var _ TextMapCarrier = MapCarrier{}
  41. // Get returns the value associated with the passed key.
  42. func (c MapCarrier) Get(key string) string {
  43. return c[key]
  44. }
  45. // Set stores the key-value pair.
  46. func (c MapCarrier) Set(key, value string) {
  47. c[key] = value
  48. }
  49. // Keys lists the keys stored in this carrier.
  50. func (c MapCarrier) Keys() []string {
  51. keys := make([]string, 0, len(c))
  52. for k := range c {
  53. keys = append(keys, k)
  54. }
  55. return keys
  56. }
  57. // HeaderCarrier adapts http.Header to satisfy the TextMapCarrier and ValuesGetter interfaces.
  58. type HeaderCarrier http.Header
  59. // Compile time check that HeaderCarrier implements ValuesGetter.
  60. var _ TextMapCarrier = HeaderCarrier{}
  61. // Compile time check that HeaderCarrier implements TextMapCarrier.
  62. var _ ValuesGetter = HeaderCarrier{}
  63. // Get returns the first value associated with the passed key.
  64. func (hc HeaderCarrier) Get(key string) string {
  65. return http.Header(hc).Get(key)
  66. }
  67. // Values returns all values associated with the passed key.
  68. func (hc HeaderCarrier) Values(key string) []string {
  69. return http.Header(hc).Values(key)
  70. }
  71. // Set stores the key-value pair.
  72. func (hc HeaderCarrier) Set(key, value string) {
  73. http.Header(hc).Set(key, value)
  74. }
  75. // Keys lists the keys stored in this carrier.
  76. func (hc HeaderCarrier) Keys() []string {
  77. keys := make([]string, 0, len(hc))
  78. for k := range hc {
  79. keys = append(keys, k)
  80. }
  81. return keys
  82. }
  83. // TextMapPropagator propagates cross-cutting concerns as key-value text
  84. // pairs within a carrier that travels in-band across process boundaries.
  85. type TextMapPropagator interface {
  86. // DO NOT CHANGE: any modification will not be backwards compatible and
  87. // must never be done outside of a new major release.
  88. // Inject set cross-cutting concerns from the Context into the carrier.
  89. Inject(ctx context.Context, carrier TextMapCarrier)
  90. // DO NOT CHANGE: any modification will not be backwards compatible and
  91. // must never be done outside of a new major release.
  92. // Extract reads cross-cutting concerns from the carrier into a Context.
  93. // Implementations may check if the carrier implements ValuesGetter,
  94. // to support extraction of multiple values per key.
  95. Extract(ctx context.Context, carrier TextMapCarrier) context.Context
  96. // DO NOT CHANGE: any modification will not be backwards compatible and
  97. // must never be done outside of a new major release.
  98. // Fields returns the keys whose values are set with Inject.
  99. Fields() []string
  100. // DO NOT CHANGE: any modification will not be backwards compatible and
  101. // must never be done outside of a new major release.
  102. }
  103. type compositeTextMapPropagator []TextMapPropagator
  104. func (p compositeTextMapPropagator) Inject(ctx context.Context, carrier TextMapCarrier) {
  105. for _, i := range p {
  106. i.Inject(ctx, carrier)
  107. }
  108. }
  109. func (p compositeTextMapPropagator) Extract(ctx context.Context, carrier TextMapCarrier) context.Context {
  110. for _, i := range p {
  111. ctx = i.Extract(ctx, carrier)
  112. }
  113. return ctx
  114. }
  115. func (p compositeTextMapPropagator) Fields() []string {
  116. unique := make(map[string]struct{})
  117. for _, i := range p {
  118. for _, k := range i.Fields() {
  119. unique[k] = struct{}{}
  120. }
  121. }
  122. fields := make([]string, 0, len(unique))
  123. for k := range unique {
  124. fields = append(fields, k)
  125. }
  126. return fields
  127. }
  128. // NewCompositeTextMapPropagator returns a unified TextMapPropagator from the
  129. // group of passed TextMapPropagator. This allows different cross-cutting
  130. // concerns to be propagates in a unified manner.
  131. //
  132. // The returned TextMapPropagator will inject and extract cross-cutting
  133. // concerns in the order the TextMapPropagators were provided. Additionally,
  134. // the Fields method will return a de-duplicated slice of the keys that are
  135. // set with the Inject method.
  136. func NewCompositeTextMapPropagator(p ...TextMapPropagator) TextMapPropagator {
  137. return compositeTextMapPropagator(p)
  138. }