google.golang.org/grpc@v1.72.2/stats/opentelemetry/internal/tracing/carrier.go (about) 1 /* 2 * 3 * Copyright 2024 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 // Package tracing implements the OpenTelemetry carrier for context propagation 20 // in gRPC tracing. 21 package tracing 22 23 import ( 24 "context" 25 26 "google.golang.org/grpc/grpclog" 27 "google.golang.org/grpc/metadata" 28 ) 29 30 var logger = grpclog.Component("otel-plugin") 31 32 // IncomingCarrier is a TextMapCarrier that uses incoming `context.Context` to 33 // retrieve any propagated key-value pairs in text format. 34 type IncomingCarrier struct { 35 ctx context.Context 36 } 37 38 // NewIncomingCarrier creates a new `IncomingCarrier` with the given context. 39 // The incoming carrier should be used with propagator's `Extract()` method in 40 // the incoming rpc path. 41 func NewIncomingCarrier(ctx context.Context) *IncomingCarrier { 42 return &IncomingCarrier{ctx: ctx} 43 } 44 45 // Get returns the string value associated with the passed key from the 46 // carrier's incoming context metadata. 47 // 48 // It returns an empty string if the key is not present in the carrier's 49 // context or if the value associated with the key is empty. 50 // 51 // If multiple values are present for a key, it returns the last one. 52 func (c *IncomingCarrier) Get(key string) string { 53 values := metadata.ValueFromIncomingContext(c.ctx, key) 54 if len(values) == 0 { 55 return "" 56 } 57 return values[len(values)-1] 58 } 59 60 // Set just logs an error. It implements the `TextMapCarrier` interface but 61 // should not be used with `IncomingCarrier`. 62 func (c *IncomingCarrier) Set(string, string) { 63 logger.Error("Set() should not be used with IncomingCarrier.") 64 } 65 66 // Keys returns the keys stored in the carrier's context metadata. It returns 67 // keys from incoming context metadata. 68 func (c *IncomingCarrier) Keys() []string { 69 md, ok := metadata.FromIncomingContext(c.ctx) 70 if !ok { 71 return nil 72 } 73 keys := make([]string, 0, len(md)) 74 for key := range md { 75 keys = append(keys, key) 76 } 77 return keys 78 } 79 80 // Context returns the underlying context associated with the 81 // `IncomingCarrier“. 82 func (c *IncomingCarrier) Context() context.Context { 83 return c.ctx 84 } 85 86 // OutgoingCarrier is a TextMapCarrier that uses outgoing `context.Context` to 87 // store any propagated key-value pairs in text format. 88 type OutgoingCarrier struct { 89 ctx context.Context 90 } 91 92 // NewOutgoingCarrier creates a new Carrier with the given context. The 93 // outgoing carrier should be used with propagator's `Inject()` method in the 94 // outgoing rpc path. 95 func NewOutgoingCarrier(ctx context.Context) *OutgoingCarrier { 96 return &OutgoingCarrier{ctx: ctx} 97 } 98 99 // Get just logs an error and returns an empty string. It implements the 100 // `TextMapCarrier` interface but should not be used with `OutgoingCarrier`. 101 func (c *OutgoingCarrier) Get(string) string { 102 logger.Error("Get() should not be used with `OutgoingCarrier`") 103 return "" 104 } 105 106 // Set stores the key-value pair in the carrier's outgoing context metadata. 107 // 108 // If the key already exists, given value is appended to the last. 109 func (c *OutgoingCarrier) Set(key, value string) { 110 c.ctx = metadata.AppendToOutgoingContext(c.ctx, key, value) 111 } 112 113 // Keys returns the keys stored in the carrier's context metadata. It returns 114 // keys from outgoing context metadata. 115 func (c *OutgoingCarrier) Keys() []string { 116 md, ok := metadata.FromOutgoingContext(c.ctx) 117 if !ok { 118 return nil 119 } 120 keys := make([]string, 0, len(md)) 121 for key := range md { 122 keys = append(keys, key) 123 } 124 return keys 125 } 126 127 // Context returns the underlying context associated with the 128 // `OutgoingCarrier“. 129 func (c *OutgoingCarrier) Context() context.Context { 130 return c.ctx 131 }