OpenTelemetry B3 Propagator for distributed tracing context propagation using B3 headers
npx @tessl/cli install tessl/pypi-opentelemetry-propagator-b3@1.36.00
# OpenTelemetry B3 Propagator
1
2
A Python library that provides propagator implementations for the B3 format used in distributed tracing systems, particularly with Zipkin. It enables trace context propagation across service boundaries using B3 headers, supporting both single-header (b3) and multi-header (b3multi) formats.
3
4
## Package Information
5
6
- **Package Name**: opentelemetry-propagator-b3
7
- **Language**: Python
8
- **Installation**: `pip install opentelemetry-propagator-b3`
9
- **Minimum Python Version**: 3.9+
10
11
## Core Imports
12
13
```python
14
from opentelemetry.propagators.b3 import B3MultiFormat, B3SingleFormat
15
```
16
17
For backward compatibility (deprecated):
18
19
```python
20
from opentelemetry.propagators.b3 import B3Format # Deprecated since 1.2.0
21
```
22
23
## Basic Usage
24
25
```python
26
from opentelemetry.propagators.b3 import B3MultiFormat, B3SingleFormat
27
from opentelemetry import trace
28
29
# Configure B3 multi-header propagation
30
propagator = B3MultiFormat()
31
32
# Or configure B3 single-header propagation
33
propagator = B3SingleFormat()
34
35
# Example: Extract trace context from incoming HTTP headers
36
propagator = B3MultiFormat()
37
headers = {
38
"x-b3-traceid": "80f198ee56343ba864fe8b2a57d3eff7",
39
"x-b3-spanid": "e457b5a2e4d86bd1",
40
"x-b3-sampled": "1"
41
}
42
43
# Create context from headers
44
context = propagator.extract(headers)
45
46
# Use context for span creation
47
tracer = trace.get_tracer(__name__)
48
with tracer.start_as_current_span("process-request", context=context):
49
# Your application logic here
50
pass
51
52
# Example: Inject trace context into outgoing HTTP headers
53
outgoing_headers = {}
54
propagator.inject(outgoing_headers)
55
# Headers now contain B3 trace context for downstream services
56
```
57
58
## Capabilities
59
60
### B3 Multi-Header Format Propagation
61
62
Implements the B3 multi-header propagation format using separate HTTP headers for each trace context component (trace ID, span ID, sampling decision, and flags).
63
64
```python { .api }
65
class B3MultiFormat(TextMapPropagator):
66
"""Propagator for the B3 HTTP multi-header format."""
67
68
def extract(
69
self,
70
carrier: CarrierT,
71
context: typing.Optional[Context] = None,
72
getter: Getter = default_getter,
73
) -> Context:
74
"""
75
Extract trace context from carrier using B3 multi-header format.
76
77
Parameters:
78
- carrier: Dict-like object containing headers/metadata
79
- context: Optional existing context to build upon
80
- getter: Function to retrieve values from carrier
81
82
Returns:
83
Context object with trace information
84
"""
85
86
def inject(
87
self,
88
carrier: CarrierT,
89
context: typing.Optional[Context] = None,
90
setter: Setter = default_setter,
91
) -> None:
92
"""
93
Inject trace context into carrier using B3 multi-header format.
94
95
Parameters:
96
- carrier: Dict-like object to inject headers into
97
- context: Optional context containing trace information
98
- setter: Function to set values in carrier
99
"""
100
101
@property
102
def fields(self) -> typing.Set[str]:
103
"""
104
Returns the set of header fields used by this propagator.
105
106
Returns:
107
Set containing: "x-b3-traceid", "x-b3-spanid", "x-b3-sampled"
108
"""
109
```
110
111
**Header Constants:**
112
113
```python { .api }
114
TRACE_ID_KEY = "x-b3-traceid" # Trace identifier header
115
SPAN_ID_KEY = "x-b3-spanid" # Span identifier header
116
SAMPLED_KEY = "x-b3-sampled" # Sampling decision header
117
FLAGS_KEY = "x-b3-flags" # Additional flags header
118
SINGLE_HEADER_KEY = "b3" # Single header key (used by single format)
119
```
120
121
### B3 Single-Header Format Propagation
122
123
Implements the B3 single-header propagation format using a single combined HTTP header containing all trace context information.
124
125
```python { .api }
126
class B3SingleFormat(B3MultiFormat):
127
"""Propagator for the B3 HTTP single-header format."""
128
129
def inject(
130
self,
131
carrier: CarrierT,
132
context: typing.Optional[Context] = None,
133
setter: Setter = default_setter,
134
) -> None:
135
"""
136
Inject trace context into carrier using B3 single-header format.
137
138
Parameters:
139
- carrier: Dict-like object to inject headers into
140
- context: Optional context containing trace information
141
- setter: Function to set values in carrier
142
143
Note: Uses single "b3" header with format: traceid-spanid-sampled
144
"""
145
146
@property
147
def fields(self) -> typing.Set[str]:
148
"""
149
Returns the set of header fields used by this propagator.
150
151
Returns:
152
Set containing: "b3"
153
"""
154
```
155
156
**Note**: B3SingleFormat inherits the `extract()` method from B3MultiFormat, which handles both single and multi-header extraction automatically.
157
158
### Deprecated B3 Format (Legacy Support)
159
160
Provides backward compatibility for applications using the original B3Format class name.
161
162
```python { .api }
163
class B3Format(B3MultiFormat):
164
"""
165
Deprecated alias for B3MultiFormat.
166
167
Deprecated since version 1.2.0. Use B3MultiFormat instead.
168
"""
169
170
def __init__(self, *args, **kwargs):
171
"""Initialize with deprecation warning."""
172
```
173
174
## Types and Dependencies
175
176
### Required Dependencies
177
178
```python { .api }
179
# From opentelemetry-api
180
from opentelemetry.context import Context
181
from opentelemetry.propagators.textmap import (
182
CarrierT, # Type alias for carrier objects (dict-like)
183
Getter, # Type for value getter functions
184
Setter, # Type for value setter functions
185
TextMapPropagator, # Base class for text map propagators
186
default_getter, # Default getter implementation
187
default_setter, # Default setter implementation
188
)
189
190
# From typing/typing-extensions
191
import typing
192
from typing_extensions import deprecated
193
```
194
195
### Entry Point Registration
196
197
The package automatically registers propagators via entry points:
198
199
```python { .api }
200
# Available via opentelemetry_propagator entry point group
201
"b3" = "opentelemetry.propagators.b3:B3SingleFormat"
202
"b3multi" = "opentelemetry.propagators.b3:B3MultiFormat"
203
```
204
205
### Version Information
206
207
```python { .api }
208
from opentelemetry.propagators.b3.version import __version__
209
# __version__ = "1.36.0"
210
```
211
212
## Error Handling
213
214
The propagators are designed to be robust and handle malformed or missing headers gracefully:
215
216
- **Invalid trace/span IDs**: Returns the original context unchanged
217
- **Missing headers**: Uses default invalid trace/span ID values
218
- **Malformed header values**: Validates using regex patterns and ignores invalid values
219
- **Mixed header formats**: Single header takes precedence over multi-header when both present
220
221
## Integration Patterns
222
223
### Global Configuration
224
225
```python
226
# Direct usage - most common pattern
227
from opentelemetry.propagators.b3 import B3MultiFormat
228
229
propagator = B3MultiFormat()
230
# Use propagator for extract/inject operations
231
```
232
233
### Custom Carrier Handling
234
235
```python
236
from opentelemetry.propagators.b3 import B3MultiFormat
237
238
class CustomGetter:
239
def get(self, carrier, key):
240
# Custom logic to extract values from carrier
241
return carrier.get(key.lower()) # Case-insensitive lookup
242
243
class CustomSetter:
244
def set(self, carrier, key, value):
245
# Custom logic to set values in carrier
246
carrier[key.lower()] = value
247
248
propagator = B3MultiFormat()
249
context = propagator.extract(
250
carrier=custom_headers,
251
getter=CustomGetter()
252
)
253
```
254
255
### Framework Integration
256
257
```python
258
# Flask example
259
from flask import request, g
260
from opentelemetry.propagators.b3 import B3MultiFormat
261
262
@app.before_request
263
def extract_trace_context():
264
propagator = B3MultiFormat()
265
g.trace_context = propagator.extract(dict(request.headers))
266
267
# Requests example
268
import requests
269
from opentelemetry.propagators.b3 import B3SingleFormat
270
271
propagator = B3SingleFormat()
272
headers = {}
273
propagator.inject(headers)
274
response = requests.get("http://example.com", headers=headers)
275
```