Class: Braintrust::Trace::SpanExporter
- Inherits:
-
OpenTelemetry::Exporter::OTLP::Exporter
- Object
- OpenTelemetry::Exporter::OTLP::Exporter
- Braintrust::Trace::SpanExporter
- Includes:
- SpanOrigin
- Defined in:
- lib/braintrust/trace/span_exporter.rb
Overview
Custom OTLP exporter for the Braintrust backend. On export it:
- stamps span origin provenance onto each SpanData (via the prepended SpanOrigin behavior)
- groups spans by braintrust.parent and sets the x-bt-parent header per group, so the backend routes them to the correct experiment/project
Thread safety: BatchSpanProcessor serializes export() calls via its @export_mutex, so @headers mutation here is safe.
Constant Summary collapse
- PARENT_ATTR_KEY =
SpanProcessor::PARENT_ATTR_KEY
- PARENT_HEADER =
"x-bt-parent"- SUCCESS =
OpenTelemetry::SDK::Trace::Export::SUCCESS
- FAILURE =
OpenTelemetry::SDK::Trace::Export::FAILURE
Constants included from SpanOrigin
Braintrust::Trace::SpanOrigin::CONTEXT_JSON_ATTR_KEY
Instance Method Summary collapse
- #export(span_data, timeout: nil) ⇒ Object
-
#initialize(endpoint:, api_key:) ⇒ SpanExporter
constructor
A new instance of SpanExporter.
Methods included from SpanOrigin
attributes_with_origin, enrich, instrumentation_name, parse_context_json
Constructor Details
#initialize(endpoint:, api_key:) ⇒ SpanExporter
Returns a new instance of SpanExporter.
25 26 27 28 29 |
# File 'lib/braintrust/trace/span_exporter.rb', line 25 def initialize(endpoint:, api_key:) raise State::MissingAPIKeyError, "api_key is required" if api_key.nil? || api_key.empty? super(endpoint: endpoint, headers: {"Authorization" => "Bearer #{api_key}"}) end |
Instance Method Details
#export(span_data, timeout: nil) ⇒ Object
31 32 33 34 35 36 37 38 39 40 |
# File 'lib/braintrust/trace/span_exporter.rb', line 31 def export(span_data, timeout: nil) failed = false span_data.group_by { |sd| sd.attributes&.[](PARENT_ATTR_KEY) }.each do |parent_value, spans| @headers[PARENT_HEADER] = parent_value if parent_value failed = true unless super(spans, timeout: timeout) == SUCCESS ensure @headers.delete(PARENT_HEADER) end failed ? FAILURE : SUCCESS end |