blob: ebda5026d6b68a763c7c769945d726e3a8759d8e [file] [log] [blame]
Abhay Kumar40252eb2025-10-13 13:25:53 +00001// Copyright The OpenTelemetry Authors
2// SPDX-License-Identifier: Apache-2.0
3
4package propagation // import "go.opentelemetry.io/otel/propagation"
5
6import (
7 "context"
8
9 "go.opentelemetry.io/otel/baggage"
10)
11
12const 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/.
18type Baggage struct{}
19
20var _ TextMapPropagator = Baggage{}
21
22// Inject sets baggage key-values from ctx into the carrier.
23func (b 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.
33func (b 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.
41func (b Baggage) Fields() []string {
42 return []string{baggageHeader}
43}
44
45func 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
58func 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}