Skip to content

Commit 1301a18

Browse files
authored
Merge pull request #4615 from cicoyle/feat-baggage-new
Baggage Docs
2 parents e194a2a + accc567 commit 1301a18

File tree

2 files changed

+188
-3
lines changed

2 files changed

+188
-3
lines changed

daprdocs/content/en/operations/observability/tracing/tracing-overview.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,138 @@ If you decide to generate trace headers yourself, there are three ways this can
111111

112112
Read [the trace context overview]({{% ref w3c-tracing-overview %}}) for more background and examples on W3C trace context and headers.
113113

114+
### Baggage Support
115+
116+
Dapr supports two distinct mechanisms for propagating W3C Baggage alongside trace context:
117+
118+
1. **Context Baggage (OpenTelemetry)**
119+
- Follows OpenTelemetry conventions with decoded values
120+
- Used when working with OpenTelemetry context propagation
121+
- Values are stored and transmitted in their original, unencoded form
122+
- Recommended for OpenTelemetry integrations and when working with application context
123+
124+
2. **Header/Metadata Baggage**
125+
- You must URL encode special characters (for example, `%20` for spaces, `%2F` for slashes) when setting header/metadata baggage
126+
- Values remain percent-encoded in transport as required by the W3C Baggage spec
127+
- Values stay encoded when inspecting raw headers/metadata
128+
- Only OpenTelemetry APIs will decode the values
129+
- Example: Use `serverNode=DF%2028` (not `serverNode=DF 28`) when setting header baggage
130+
131+
For security purposes, context baggage and header baggage are strictly separated and never merged between domains. This ensures that baggage values maintain their intended format and security properties.
132+
133+
#### Using Baggage with Dapr
134+
135+
You can propagate baggage using either mechanism, depending on your use case.
136+
137+
1. **In your application code**: Set the baggage in the context before making a Dapr API call
138+
2. **When calling Dapr**: Pass the context to any Dapr API call
139+
3. **Inside Dapr**: The Dapr runtime automatically picks up the baggage
140+
4. **Propagation**: Dapr automatically propagates the baggage to downstream services, maintaining the appropriate encoding for each mechanism
141+
142+
Here are examples of both mechanisms:
143+
144+
**1. Using Context Baggage (OpenTelemetry)**
145+
146+
When using OpenTelemetry SDK:
147+
148+
{{< tabpane text=true >}}
149+
150+
{{% tab header="Go" %}}
151+
152+
```go
153+
import otelbaggage "go.opentelemetry.io/otel/baggage"
154+
155+
// Set baggage in context (values remain unencoded)
156+
baggage, err = otelbaggage.Parse("userId=cassie,serverNode=DF%2028")
157+
...
158+
ctx := otelbaggage.ContextWithBaggage(t.Context(), baggage)
159+
)
160+
161+
// Pass this context to any Dapr API call
162+
client.InvokeMethodWithContent(ctx, "serviceB", ...)
163+
```
164+
165+
**2. Using Header/Metadata Baggage**
166+
167+
When using gRPC metadata:
168+
```go
169+
import "google.golang.org/grpc/metadata"
170+
171+
// Set URL-encoded baggage in context
172+
ctx = metadata.AppendToOutgoingContext(ctx,
173+
"baggage", "userId=cassie,serverNode=DF%2028",
174+
)
175+
176+
// Pass this context to any Dapr API call
177+
client.InvokeMethodWithContent(ctx, "serviceB", ...)
178+
```
179+
180+
**3. Receiving Baggage in Target Service**
181+
182+
In your target service, you can access the propagated baggage:
183+
184+
```go
185+
// Using OpenTelemetry (values are automatically decoded)
186+
import "go.opentelemetry.io/otel/baggage"
187+
188+
bag := baggage.FromContext(ctx)
189+
userID := bag.Member("userId").Value() // "cassie"
190+
```
191+
192+
```go
193+
// Using raw gRPC metadata (values remain percent-encoded)
194+
import "google.golang.org/grpc/metadata"
195+
196+
md, _ := metadata.FromIncomingContext(ctx)
197+
if values := md.Get("baggage"); len(values) > 0 {
198+
// values[0] contains the percent-encoded string you set: "userId=cassie,serverNode=DF%2028"
199+
// Remember: You must URL encode special characters when setting baggage
200+
201+
// To decode the values, use OpenTelemetry APIs:
202+
bag, err := baggage.Parse(values[0])
203+
...
204+
userID := bag.Member("userId").Value() // "cassie"
205+
}
206+
```
207+
208+
*HTTP Example (URL-encoded):*
209+
```bash
210+
curl -X POST http://localhost:3500/v1.0/invoke/serviceB/method/hello \
211+
-H "Content-Type: application/json" \
212+
-H "baggage: userID=cassie,serverNode=DF%2028" \
213+
-d '{"message": "Hello service B"}'
214+
```
215+
216+
*gRPC Example (URL-encoded):*
217+
```go
218+
ctx = grpcMetadata.AppendToOutgoingContext(ctx,
219+
"baggage", "userID=cassie,serverNode=DF%2028",
220+
)
221+
```
222+
223+
{{% /tab %}}
224+
225+
{{< /tabpane >}}
226+
227+
#### Common Use Cases
228+
229+
Baggage is useful for:
230+
- Propagating user IDs or correlation IDs across services
231+
- Passing tenant or environment information
232+
- Maintaining consistent context across service boundaries
233+
- Debugging and troubleshooting distributed transactions
234+
235+
#### Best Practices
236+
237+
1. **Choose the Right Mechanism**
238+
- Use Context Baggage when working with OpenTelemetry
239+
- Use Header Baggage when working directly with HTTP/gRPC
240+
241+
2. **Security Considerations**
242+
- Be mindful that baggage is propagated across service boundaries
243+
- Don't include sensitive information in baggage
244+
- Remember that context and header baggage remain separate
245+
114246
## Related Links
115247

116248
- [Observability concepts]({{% ref observability-concept.md %}})

daprdocs/content/en/operations/observability/tracing/w3c-tracing-overview.md

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ When a request arrives without a trace ID, Dapr creates a new one. Otherwise, it
4848
These are the specific trace context headers that are generated and propagated by Dapr for HTTP and gRPC.
4949

5050
{{< tabpane text=true >}}
51-
<!-- HTTP -->
51+
5252
{{% tab "HTTP" %}}
5353

5454
Copy these headers when propagating a trace context header from an HTTP response to an HTTP request:
@@ -73,14 +73,67 @@ tracestate: congo=t61rcWkgMzE
7373

7474
[Learn more about the tracestate fields details](https://www.w3.org/TR/trace-context/#tracestate-header).
7575

76-
{{% /tab %}}
76+
**Baggage Support**
77+
78+
Dapr supports [W3C Baggage](https://www.w3.org/TR/baggage/) for propagating key-value pairs alongside trace context through two distinct mechanisms:
79+
80+
1. **Context Baggage (OpenTelemetry)**
81+
- Follows OpenTelemetry conventions with decoded values
82+
- Used when propagating baggage through application context
83+
- Values are stored in their original, unencoded form
84+
- Example of how it would be printed with OpenTelemetry APIs:
85+
```
86+
baggage: userId=cassie,serverNode=DF 28,isVIP=true
87+
```
88+
89+
2. **HTTP Header Baggage**
90+
- You must URL encode special characters (for example, `%20` for spaces, `%2F` for slashes) when setting header baggage
91+
- Values remain percent-encoded in HTTP headers as required by the W3C Baggage spec
92+
- Values stay encoded when inspecting raw headers in Dapr
93+
- Only OpenTelemetry APIs like `otelbaggage.Parse()` will decode the values
94+
- Example (note the URL-encoded space `%20`):
95+
```bash
96+
curl -X POST http://localhost:3500/v1.0/invoke/serviceB/method/hello \
97+
-H "Content-Type: application/json" \
98+
-H "baggage: userId=cassie,serverNode=DF%2028,isVIP=true" \
99+
-d '{"message": "Hello service B"}'
100+
```
101+
102+
For security purposes, context baggage and header baggage are strictly separated and never merged between domains. This ensures that baggage values maintain their intended format and security properties in each domain.
103+
104+
Multiple baggage headers are supported and will be combined according to the W3C specification. Dapr automatically propagates baggage across service calls while maintaining the appropriate encoding for each domain.
77105
106+
{{% /tab %}}
78107
79-
<!-- gRPC -->
80108
{{% tab "gRPC" %}}
81109
82110
In the gRPC API calls, trace context is passed through `grpc-trace-bin` header.
83111
112+
**Baggage Support**
113+
114+
Dapr supports [W3C Baggage](https://www.w3.org/TR/baggage/) for propagating key-value pairs alongside trace context through two distinct mechanisms:
115+
116+
1. **Context Baggage (OpenTelemetry)**
117+
- Follows OpenTelemetry conventions with decoded values
118+
- Used when propagating baggage through gRPC context
119+
- Values are stored in their original, unencoded form
120+
- Example of how it would be printed with OpenTelemetry APIs:
121+
```
122+
baggage: userId=cassie,serverNode=DF 28,isVIP=true
123+
```
124+
125+
2. **gRPC Metadata Baggage**
126+
- You must URL encode special characters (for example, `%20` for spaces, `%2F` for slashes) when setting metadata baggage
127+
- Values remain percent-encoded in gRPC metadata
128+
- Example (note the URL-encoded space `%20`):
129+
```
130+
baggage: userId=cassie,serverNode=DF%2028,isVIP=true
131+
```
132+
133+
For security purposes, context baggage and metadata baggage are strictly separated and never merged between domains. This ensures that baggage values maintain their intended format and security properties in each domain.
134+
135+
Multiple baggage metadata entries are supported and will be combined according to the W3C specification. Dapr automatically propagates baggage across service calls while maintaining the appropriate encoding for each domain.
136+
84137
{{% /tab %}}
85138
86139
{{< /tabpane >}}

0 commit comments

Comments
 (0)