Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions py/src/braintrust/auto.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,12 @@ def auto_instrument(
livekit_agents: Enable LiveKit Agents instrumentation (default: True)
pipecat: Enable Pipecat AI instrumentation (default: True)
typesafe: Enable TypeSafe instrumentation (default: True)
span_customizers: Ordered synchronous export customizers for all native SDK
spans, including manual spans; dataset rows and feedback are excluded.
span_customizers: Ordered synchronous export customizers for native SDK spans
and OTel spans sent through OtelExporter or BraintrustSpanProcessor,
including manual spans; generic OTLP exporters, dataset rows, and
feedback are excluded.
Copies and replaces the global list when provided; None leaves existing
configuration unchanged. Pass [] to disable.
With BRAINTRUST_OTEL_COMPAT enabled, non-empty customizers log an error
and leave the existing configuration unchanged; instrumentation continues.

Returns:
Dict mapping integration name to whether it was successfully instrumented.
Expand Down
13 changes: 13 additions & 0 deletions py/src/braintrust/otel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from urllib.parse import urljoin

from braintrust.env import BraintrustEnv
from braintrust.span_customizer import _get_span_customizers
from braintrust.span_origin import SpanOriginEnvironment, detect_environment, merge_span_origin_context


Expand Down Expand Up @@ -132,6 +133,10 @@ class AISpanProcessor:
Only filtered spans and root spans will be forwarded to the inner processor.
This dramatically reduces telemetry volume while preserving important observability.

This filter does not run Braintrust span customizers. Wrap OtelExporter
instead of a generic OTLPSpanExporter to customize Braintrust exports,
or use BraintrustSpanProcessor for the complete pipeline.

Example:
> processor = AISpanProcessor(BatchSpanProcessor(OTLPSpanExporter()))
> provider = TracerProvider()
Expand Down Expand Up @@ -210,6 +215,9 @@ class OtelExporter(OTLPSpanExporter):
"""
A subclass of OTLPSpanExporter configured for Braintrust.

Runs the registered Braintrust span customizers before OTLP serialization.
Generic OTLPSpanExporter instances do not run these hooks.

For most use cases, consider using the Processor class instead, which provides
a more convenient all-in-one interface.

Expand Down Expand Up @@ -303,6 +311,11 @@ def initialize(self) -> None:

def export(self, spans):
self._ensure_api_key()
customizers = _get_span_customizers()
if customizers:
from .span_customizer import customize_otel_span

spans = [customize_otel_span(span, customizers) for span in spans]
return super().export(spans)

def force_flush(self, timeout_millis=30000):
Expand Down
Loading
Loading