Class: Braintrust::Trace::SpanExporter

Inherits:
OpenTelemetry::Exporter::OTLP::Exporter
  • Object
show all
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

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