OpenTelemetry B3 Propagator
The `opentelemetry-propagator-b3` library provides B3 context propagation for OpenTelemetry Python, enabling distributed tracing across systems that use the B3 header format (e.g., Zipkin). It is part of the broader OpenTelemetry Python project, which follows a rapid release cycle, with new versions typically released monthly.
Warnings
- gotcha By default, the `B3Propagator` extracts both single (`b3`) and multi-header (`X-B3-*`) B3 formats but injects only the single-header `b3` format. If your system requires multi-header injection for compatibility with legacy systems, explicit configuration is needed.
- gotcha The OpenTelemetry B3 propagator intentionally does not propagate `X-B3-ParentSpanId`. This is because OpenTelemetry does not support the Zipkin-specific behavior of reusing the same ID for both client and server sides of a request, which `ParentSpanId` implies.
- gotcha The OpenTelemetry Python SDK defaults to using W3C Trace Context and W3C Baggage propagators. To enable B3 propagation, you must explicitly set `B3Propagator` as the global text map propagator in your application's initialization code, or use environment variables.
Install
-
pip install opentelemetry-propagator-b3 opentelemetry-sdk
Imports
- B3Propagator
from opentelemetry.propagators.b3 import B3Propagator
- set_global_textmap
from opentelemetry.propagate import set_global_textmap
Quickstart
import os
from opentelemetry import trace
from opentelemetry.propagate import set_global_textmap, get_global_textmap
from opentelemetry.propagators.b3 import B3Propagator
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
# Set the B3 propagator globally
set_global_textmap(B3Propagator())
# Configure a basic tracer provider for demonstration
provider = TracerProvider()
processor = SimpleSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)
def make_request():
carrier = {}
propagator = get_global_textmap()
# Inject context into a carrier (e.g., HTTP headers)
propagator.inject(carrier=carrier)
print(f"Injected B3 headers: {carrier}")
# Simulate receiving context in another service
# Here, we just extract from the same carrier for simplicity
ctx = propagator.extract(carrier=carrier)
with tracer.start_as_current_span("my-b3-propagated-span", context=ctx):
print("Span created with propagated B3 context")
if __name__ == "__main__":
make_request()