OpenTelemetry¶
Burr has two integrations with OpenTelemetry:
Burr can log traces to OpenTelemetry
Burr can capture any traces logged within an action and log them to OpenTelemetry
See the following resources for more information:
Reference for the various useful methods:
- class burr.integrations.opentelemetry.OpenTelemetryBridge(
- tracer_name: str = None,
- tracer: Tracer = None,
- streaming_telemetry: StreamingTelemetryMode = StreamingTelemetryMode.SINGLE_SPAN,
Lifecycle adapter that maps Burr execution events to OpenTelemetry spans and events.
How it works
The bridge implements Burr lifecycle hooks to create a span hierarchy that mirrors the execution structure:
pre_run_execute_call/post_run_execute_call— creates a top-level method span for the application method being called (e.g.step,astream_result).pre_run_step/post_run_step— creates an action span as a child of the method span. For streaming actions, behavior depends on thestreaming_telemetrymode.pre_start_span/post_end_span— creates sub-action spans for user-defined visibility spans (viaTracerFactory/__tracer).do_log_attributes— sets OTel attributes on the current span.pre_stream_generate/post_stream_generate— for streaming actions, optionally creates per-yield chunk spans and/or accumulates timing data for a summary event.
All spans are managed via a ContextVar-based token stack (
token_stack) to correctly handle nesting across sync and async execution.Usage
# replace with instructions from your preferred vendor my_vendor_library_or_tracer_provider.init() app = ( ApplicationBuilder() .with_entrypoint("prompt") .with_state(chat_history=[]) .with_graph(graph) .with_hooks(OpenTelemetryBridge()) .build() ) app.run() # will log to OpenTelemetry
Streaming telemetry modes
The
streaming_telemetryparameter controls how streaming actions are instrumented. Non-streaming actions are unaffected — they always produce a single action span.StreamingTelemetryMode.SINGLE_SPAN(default): A single action span covers the full generator lifetime (including consumer wait time). Streaming attributes are set on the span with the generation/consumer timing breakdown:stream.generation_time_ms— time spent inside the generator producing itemsstream.consumer_time_ms— time the consumer spent processing yielded itemsstream.iteration_count— number of items yieldedstream.first_item_time_ms— time to first item (TTFT)
StreamingTelemetryMode.EVENT: No action span. Astream_completed(orstream_error) span event is added to the method span with the timing summary (includingstream.total_time_mssince there is no action span to carry duration).StreamingTelemetryMode.CHUNK_SPANS: No action span. A child span ({action}::chunk_{N}) is created for each generator yield under the method span. Each chunk span measures only generation time (excludes consumer processing time).StreamingTelemetryMode.SINGLE_AND_CHUNK_SPANS: CombinesSINGLE_SPANandCHUNK_SPANS— the action span (with streaming attributes) plus per-yield chunk spans as its children.
- do_log_attributes(
- *,
- attributes: Dict[str, Any],
- **future_kwargs: Any,
Sets key-value attributes on the current OTel span.
Values are serialized via
convert_to_otel_attribute()to ensure they are OTel-compatible types (str, bool, int, float, or homogeneous sequences thereof).
- post_end_span(
- *,
- span: ActionSpan,
- **future_kwargs: Any,
Closes a sub-action span opened by
pre_start_span().
- post_run_execute_call(*, exception: Exception | None, **future_kwargs)¶
Closes the top-level method span opened by
pre_run_execute_call().
- post_run_step(*, exception: Exception, **future_kwargs: Any)¶
Closes the action span and, for streaming actions, emits summary telemetry.
Behavior depends on mode:
SINGLE_SPAN/SINGLE_AND_CHUNK_SPANS: Sets streaming attributes on the action span, then closes it.EVENT: Emits astream_completed(orstream_error) span event on the method span (the action span was skipped). Resets the skipped flag.CHUNK_SPANS: The action span was skipped; just resets the flag.
- post_stream_generate(
- *,
- item: Any,
- item_index: int,
- exception: Exception | None,
- **future_kwargs: Any,
Called just after each
__next__()/__anext__()returns (or raises).For modes with accumulation (
SINGLE_SPAN,EVENT,SINGLE_AND_CHUNK_SPANS), accumulates generation time and updates the iteration count. Whenitemis notNone, the item is counted; aNoneitem signals generator exhaustion (StopIteration).In
CHUNK_SPANSorSINGLE_AND_CHUNK_SPANSmode, closes the chunk span opened bypre_stream_generate(), setting an error status ifexceptionis provided.
- pre_run_execute_call(
- *,
- method: ExecuteMethod,
- **future_kwargs: Any,
Opens the top-level method span (e.g.
step,astream_result).This is the outermost span in the Burr trace hierarchy. Action spans and chunk spans are nested under it.
- pre_run_step(*, action: Action, **future_kwargs: Any)¶
Opens an action span for the step about to execute.
For streaming actions in
EVENTorCHUNK_SPANSmode, the action span is skipped. InSINGLE_SPANandSINGLE_AND_CHUNK_SPANSmodes, the action span is created normally.For all modes except
CHUNK_SPANS, a_StreamingAccumulatoris initialized to collect timing data across generator yields.
- pre_start_span(
- *,
- span: ActionSpan,
- **future_kwargs: Any,
Opens a sub-action span for a user-defined visibility span.
These are created by the
TracerFactory(__tracer) context manager inside actions, and are nested under the current action span.
- pre_stream_generate(
- *,
- action: str,
- item_index: int,
- **future_kwargs: Any,
Called just before each
__next__()/__anext__()on the generator.For modes with accumulation (
SINGLE_SPAN,EVENT,SINGLE_AND_CHUNK_SPANS), records the start of generation time and accumulates consumer time (the gap between the previouspost_stream_generateand now).In
CHUNK_SPANSorSINGLE_AND_CHUNK_SPANSmode, opens a child span named{action}::chunk_{item_index}.
- class burr.integrations.opentelemetry.StreamingTelemetryMode(*values)¶
Controls how streaming actions are instrumented by the OpenTelemetryBridge.
SINGLE_SPAN: A single action span covers the full generator lifetime (default).EVENT: A single action span plus astream_completedsummary span event.CHUNK_SPANS: No action span. Per-yield child spans under the method span.SINGLE_AND_CHUNK_SPANS: Action span with summary event plus per-yield child spans.
- CHUNK_SPANS = 'chunk_spans'¶
- EVENT = 'event'¶
- SINGLE_AND_CHUNK_SPANS = 'single_and_chunk_spans'¶
- SINGLE_SPAN = 'single_span'¶
- burr.integrations.opentelemetry.init_instruments(
- *instruments: Literal['openai', 'anthropic', 'cohere', 'google_generativeai', 'mistral', 'ollama', 'transformers', 'together', 'bedrock', 'replicate', 'vertexai', 'groq', 'watsonx', 'alephalpha', 'pinecone', 'qdrant', 'chroma', 'milvus', 'weaviate', 'lancedb', 'marqo', 'redis', 'langchain', 'llama_index', 'haystack', 'requests', 'httpx', 'urllib', 'urllib3'],
- init_all: bool = False,
Instruments the specified libraries, or all that are installed if it is enabled.
This will check if any libraries are available in the current environment and initialize if they are. See the
INSTRUMENTS_SPECSfield for the list of available libraries.- Parameters:
instruments – Name of libraries to instrument (e.g., requests, openai)
init_all – If True, initialize all available instruments for imported packages.
- Returns: