baggage.go raw
1 // Copyright The OpenTelemetry Authors
2 // SPDX-License-Identifier: Apache-2.0
3
4 package propagation // import "go.opentelemetry.io/otel/propagation"
5
6 import (
7 "context"
8
9 "go.opentelemetry.io/otel/baggage"
10 )
11
12 const baggageHeader = "baggage"
13
14 // Baggage is a propagator that supports the W3C Baggage format.
15 //
16 // This propagates user-defined baggage associated with a trace. The complete
17 // specification is defined at https://www.w3.org/TR/baggage/.
18 type Baggage struct{}
19
20 var _ TextMapPropagator = Baggage{}
21
22 // Inject sets baggage key-values from ctx into the carrier.
23 func (Baggage) Inject(ctx context.Context, carrier TextMapCarrier) {
24 bStr := baggage.FromContext(ctx).String()
25 if bStr != "" {
26 carrier.Set(baggageHeader, bStr)
27 }
28 }
29
30 // Extract returns a copy of parent with the baggage from the carrier added.
31 // If carrier implements [ValuesGetter] (e.g. [HeaderCarrier]), Values is invoked
32 // for multiple values extraction. Otherwise, Get is called.
33 func (Baggage) Extract(parent context.Context, carrier TextMapCarrier) context.Context {
34 if multiCarrier, ok := carrier.(ValuesGetter); ok {
35 return extractMultiBaggage(parent, multiCarrier)
36 }
37 return extractSingleBaggage(parent, carrier)
38 }
39
40 // Fields returns the keys who's values are set with Inject.
41 func (Baggage) Fields() []string {
42 return []string{baggageHeader}
43 }
44
45 func extractSingleBaggage(parent context.Context, carrier TextMapCarrier) context.Context {
46 bStr := carrier.Get(baggageHeader)
47 if bStr == "" {
48 return parent
49 }
50
51 bag, err := baggage.Parse(bStr)
52 if err != nil {
53 return parent
54 }
55 return baggage.ContextWithBaggage(parent, bag)
56 }
57
58 func extractMultiBaggage(parent context.Context, carrier ValuesGetter) context.Context {
59 bVals := carrier.Values(baggageHeader)
60 if len(bVals) == 0 {
61 return parent
62 }
63 var members []baggage.Member
64 for _, bStr := range bVals {
65 currBag, err := baggage.Parse(bStr)
66 if err != nil {
67 continue
68 }
69 members = append(members, currBag.Members()...)
70 }
71
72 b, err := baggage.New(members...)
73 if err != nil || b.Len() == 0 {
74 return parent
75 }
76 return baggage.ContextWithBaggage(parent, b)
77 }
78