OpenTelemetry Baggage Span Processor
The `opentelemetry-processor-baggage` library provides a `BaggageSpanProcessor` for OpenTelemetry Python, which automatically reads entries stored in Baggage from the parent context and adds their keys and values to the span as attributes upon span start. This enables propagating business context across services. It is part of the `opentelemetry-python-contrib` repository, which has an active release cadence, often with pre-release (`0.x.y.b0`) versions. The current version is 0.62b0.
Warnings
- gotcha Do not put sensitive or personally identifiable information (PII) in Baggage. Baggage is automatically propagated across service boundaries, typically in HTTP headers, making it visible in transit and potentially to external third-party services.
- gotcha Baggage entries add to the size of HTTP headers. Keep Baggage keys and values concise and limit the number of entries to avoid exceeding header size limits imposed by load balancers, proxies, or web servers, which can lead to request failures.
- gotcha Baggage is mutable by any service in the request chain. There is no built-in access control, meaning a downstream service could unintentionally or maliciously modify or remove Baggage entries set by upstream services.
- gotcha Baggage is distinct from span attributes. Without a processor like `BaggageSpanProcessor`, Baggage entries are not automatically added to spans. They are propagated in the context but won't appear on the trace unless explicitly added.
Install
-
pip install opentelemetry-processor-baggage
Imports
- BaggageSpanProcessor
from opentelemetry.processor.baggage import BaggageSpanProcessor, ALLOW_ALL_BAGGAGE_KEYS
Quickstart
import os
from opentelemetry import baggage, trace
from opentelemetry.context import attach, detach
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleExportSpanProcessor
from opentelemetry.processor.baggage import BaggageSpanProcessor, ALLOW_ALL_BAGGAGE_KEYS
# --- Example 1: Copy all baggage entries to span attributes ---
# Configure TracerProvider
provider = TracerProvider()
# Add the BaggageSpanProcessor to copy all baggage entries to span attributes
provider.add_span_processor(BaggageSpanProcessor(ALLOW_ALL_BAGGAGE_KEYS))
# Add a console exporter for demonstration
provider.add_span_processor(SimpleExportSpanProcessor(ConsoleSpanExporter()))
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)
# Create a context with baggage
# IMPORTANT: Baggage entries are strings, convert non-string values
ctx = baggage.set_baggage("user.id", "user123")
ctx = baggage.set_baggage("tenant.id", "acme", context=ctx)
ctx_token = attach(ctx)
try:
with tracer.start_as_current_span("parent_span") as parent_span:
print(f"Parent Span ID: {parent_span.context.span_id:x}")
# Baggage is automatically propagated to child spans
with tracer.start_as_current_span("child_span") as child_span:
print(f"Child Span ID: {child_span.context.span_id:x}")
print(f"Child Span Attributes (should contain baggage): {child_span.attributes}")
finally:
detach(ctx_token)
print("\n--- Example 2: Copy baggage entries with a custom predicate ---")
# Configure a new provider with a custom predicate
provider_custom = TracerProvider()
# Only copy baggage entries starting with 'my-key'
starts_with_predicate = lambda baggage_key: baggage_key.startswith("my-key")
provider_custom.add_span_processor(BaggageSpanProcessor(starts_with_predicate))
provider_custom.add_span_processor(SimpleExportSpanProcessor(ConsoleSpanExporter()))
trace.set_tracer_provider(provider_custom) # Set this new provider
tracer_custom = trace.get_tracer("custom_predicate_example")
ctx_custom = baggage.set_baggage("my-key-1", "value1")
ctx_custom = baggage.set_baggage("other-key", "value_ignored", context=ctx_custom)
ctx_custom_token = attach(ctx_custom)
try:
with tracer_custom.start_as_current_span("filtered_span") as filtered_span:
print(f"Filtered Span ID: {filtered_span.context.span_id:x}")
print(f"Filtered Span Attributes (should only contain 'my-key-1'): {filtered_span.attributes}")
finally:
detach(ctx_custom_token)