propagation.go (5073B)
1 // Copyright The OpenTelemetry Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package propagation // import "go.opentelemetry.io/otel/propagation" 16 17 import ( 18 "context" 19 "net/http" 20 ) 21 22 // TextMapCarrier is the storage medium used by a TextMapPropagator. 23 type TextMapCarrier interface { 24 // DO NOT CHANGE: any modification will not be backwards compatible and 25 // must never be done outside of a new major release. 26 27 // Get returns the value associated with the passed key. 28 Get(key string) string 29 // DO NOT CHANGE: any modification will not be backwards compatible and 30 // must never be done outside of a new major release. 31 32 // Set stores the key-value pair. 33 Set(key string, value string) 34 // DO NOT CHANGE: any modification will not be backwards compatible and 35 // must never be done outside of a new major release. 36 37 // Keys lists the keys stored in this carrier. 38 Keys() []string 39 // DO NOT CHANGE: any modification will not be backwards compatible and 40 // must never be done outside of a new major release. 41 } 42 43 // MapCarrier is a TextMapCarrier that uses a map held in memory as a storage 44 // medium for propagated key-value pairs. 45 type MapCarrier map[string]string 46 47 // Compile time check that MapCarrier implements the TextMapCarrier. 48 var _ TextMapCarrier = MapCarrier{} 49 50 // Get returns the value associated with the passed key. 51 func (c MapCarrier) Get(key string) string { 52 return c[key] 53 } 54 55 // Set stores the key-value pair. 56 func (c MapCarrier) Set(key, value string) { 57 c[key] = value 58 } 59 60 // Keys lists the keys stored in this carrier. 61 func (c MapCarrier) Keys() []string { 62 keys := make([]string, 0, len(c)) 63 for k := range c { 64 keys = append(keys, k) 65 } 66 return keys 67 } 68 69 // HeaderCarrier adapts http.Header to satisfy the TextMapCarrier interface. 70 type HeaderCarrier http.Header 71 72 // Get returns the value associated with the passed key. 73 func (hc HeaderCarrier) Get(key string) string { 74 return http.Header(hc).Get(key) 75 } 76 77 // Set stores the key-value pair. 78 func (hc HeaderCarrier) Set(key string, value string) { 79 http.Header(hc).Set(key, value) 80 } 81 82 // Keys lists the keys stored in this carrier. 83 func (hc HeaderCarrier) Keys() []string { 84 keys := make([]string, 0, len(hc)) 85 for k := range hc { 86 keys = append(keys, k) 87 } 88 return keys 89 } 90 91 // TextMapPropagator propagates cross-cutting concerns as key-value text 92 // pairs within a carrier that travels in-band across process boundaries. 93 type TextMapPropagator interface { 94 // DO NOT CHANGE: any modification will not be backwards compatible and 95 // must never be done outside of a new major release. 96 97 // Inject set cross-cutting concerns from the Context into the carrier. 98 Inject(ctx context.Context, carrier TextMapCarrier) 99 // DO NOT CHANGE: any modification will not be backwards compatible and 100 // must never be done outside of a new major release. 101 102 // Extract reads cross-cutting concerns from the carrier into a Context. 103 Extract(ctx context.Context, carrier TextMapCarrier) context.Context 104 // DO NOT CHANGE: any modification will not be backwards compatible and 105 // must never be done outside of a new major release. 106 107 // Fields returns the keys whose values are set with Inject. 108 Fields() []string 109 // DO NOT CHANGE: any modification will not be backwards compatible and 110 // must never be done outside of a new major release. 111 } 112 113 type compositeTextMapPropagator []TextMapPropagator 114 115 func (p compositeTextMapPropagator) Inject(ctx context.Context, carrier TextMapCarrier) { 116 for _, i := range p { 117 i.Inject(ctx, carrier) 118 } 119 } 120 121 func (p compositeTextMapPropagator) Extract(ctx context.Context, carrier TextMapCarrier) context.Context { 122 for _, i := range p { 123 ctx = i.Extract(ctx, carrier) 124 } 125 return ctx 126 } 127 128 func (p compositeTextMapPropagator) Fields() []string { 129 unique := make(map[string]struct{}) 130 for _, i := range p { 131 for _, k := range i.Fields() { 132 unique[k] = struct{}{} 133 } 134 } 135 136 fields := make([]string, 0, len(unique)) 137 for k := range unique { 138 fields = append(fields, k) 139 } 140 return fields 141 } 142 143 // NewCompositeTextMapPropagator returns a unified TextMapPropagator from the 144 // group of passed TextMapPropagator. This allows different cross-cutting 145 // concerns to be propagates in a unified manner. 146 // 147 // The returned TextMapPropagator will inject and extract cross-cutting 148 // concerns in the order the TextMapPropagators were provided. Additionally, 149 // the Fields method will return a de-duplicated slice of the keys that are 150 // set with the Inject method. 151 func NewCompositeTextMapPropagator(p ...TextMapPropagator) TextMapPropagator { 152 return compositeTextMapPropagator(p) 153 }