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 15package propagation // import "go.opentelemetry.io/otel/propagation" 16 17import ( 18 "context" 19 "net/http" 20) 21 22// TextMapCarrier is the storage medium used by a TextMapPropagator. 23type TextMapCarrier interface { 24 // Get returns the value associated with the passed key. 25 Get(key string) string 26 // Set stores the key-value pair. 27 Set(key string, value string) 28 // Keys lists the keys stored in this carrier. 29 Keys() []string 30} 31 32// HeaderCarrier adapts http.Header to satisfy the TextMapCarrier interface. 33type HeaderCarrier http.Header 34 35// Get returns the value associated with the passed key. 36func (hc HeaderCarrier) Get(key string) string { 37 return http.Header(hc).Get(key) 38} 39 40// Set stores the key-value pair. 41func (hc HeaderCarrier) Set(key string, value string) { 42 http.Header(hc).Set(key, value) 43} 44 45// Keys lists the keys stored in this carrier. 46func (hc HeaderCarrier) Keys() []string { 47 keys := make([]string, 0, len(hc)) 48 for k := range hc { 49 keys = append(keys, k) 50 } 51 return keys 52} 53 54// TextMapPropagator propagates cross-cutting concerns as key-value text 55// pairs within a carrier that travels in-band across process boundaries. 56type TextMapPropagator interface { 57 // Inject set cross-cutting concerns from the Context into the carrier. 58 Inject(ctx context.Context, carrier TextMapCarrier) 59 // Extract reads cross-cutting concerns from the carrier into a Context. 60 Extract(ctx context.Context, carrier TextMapCarrier) context.Context 61 // Fields returns the keys who's values are set with Inject. 62 Fields() []string 63} 64 65type compositeTextMapPropagator []TextMapPropagator 66 67func (p compositeTextMapPropagator) Inject(ctx context.Context, carrier TextMapCarrier) { 68 for _, i := range p { 69 i.Inject(ctx, carrier) 70 } 71} 72 73func (p compositeTextMapPropagator) Extract(ctx context.Context, carrier TextMapCarrier) context.Context { 74 for _, i := range p { 75 ctx = i.Extract(ctx, carrier) 76 } 77 return ctx 78} 79 80func (p compositeTextMapPropagator) Fields() []string { 81 unique := make(map[string]struct{}) 82 for _, i := range p { 83 for _, k := range i.Fields() { 84 unique[k] = struct{}{} 85 } 86 } 87 88 fields := make([]string, 0, len(unique)) 89 for k := range unique { 90 fields = append(fields, k) 91 } 92 return fields 93} 94 95// NewCompositeTextMapPropagator returns a unified TextMapPropagator from the 96// group of passed TextMapPropagator. This allows different cross-cutting 97// concerns to be propagates in a unified manner. 98// 99// The returned TextMapPropagator will inject and extract cross-cutting 100// concerns in the order the TextMapPropagators were provided. Additionally, 101// the Fields method will return a de-duplicated slice of the keys that are 102// set with the Inject method. 103func NewCompositeTextMapPropagator(p ...TextMapPropagator) TextMapPropagator { 104 return compositeTextMapPropagator(p) 105} 106