Skip to content
Draft
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
18 changes: 14 additions & 4 deletions lib/braintrust/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ module Braintrust
# and allows overriding with explicit options
class Config
attr_reader :api_key, :org_name, :default_project, :app_url, :api_url,
:filter_ai_spans, :span_filter_funcs
:filter_ai_spans, :span_filter_funcs, :auto_convert_ai_attachments

def initialize(api_key: nil, org_name: nil, default_project: nil, app_url: nil, api_url: nil,
filter_ai_spans: nil, span_filter_funcs: nil)
filter_ai_spans: nil, span_filter_funcs: nil, auto_convert_ai_attachments: true)
@api_key = api_key
@org_name = org_name
@default_project = default_project
@app_url = app_url
@api_url = api_url
@filter_ai_spans = filter_ai_spans
@span_filter_funcs = span_filter_funcs || []
@auto_convert_ai_attachments = auto_convert_ai_attachments
end

# Create a Config from environment variables, with option overrides
Expand All @@ -29,7 +30,7 @@ def initialize(api_key: nil, org_name: nil, default_project: nil, app_url: nil,
# @param span_filter_funcs [Array<Proc>, nil] Custom span filter functions
# @return [Config] the created config
def self.from_env(api_key: nil, org_name: nil, default_project: nil, app_url: nil, api_url: nil,
filter_ai_spans: nil, span_filter_funcs: nil)
filter_ai_spans: nil, span_filter_funcs: nil, auto_convert_ai_attachments: nil)
# Parse filter_ai_spans from ENV if not explicitly provided
env_filter_ai_spans = ENV["BRAINTRUST_OTEL_FILTER_AI_SPANS"]
filter_ai_spans_value = if filter_ai_spans.nil?
Expand All @@ -38,14 +39,23 @@ def self.from_env(api_key: nil, org_name: nil, default_project: nil, app_url: ni
filter_ai_spans
end

# Attachment auto-conversion defaults to true; disabled only when the env
# var is explicitly "false" or an explicit false is passed.
auto_convert_value = if auto_convert_ai_attachments.nil?
ENV["BRAINTRUST_AUTO_CONVERT_AI_ATTACHMENTS"] != "false"
else
auto_convert_ai_attachments
end

new(
api_key: api_key || ((ENV["BRAINTRUST_API_KEY"] && ENV["BRAINTRUST_API_KEY"].empty?) ? nil : ENV["BRAINTRUST_API_KEY"]),
org_name: org_name || ENV["BRAINTRUST_ORG_NAME"],
default_project: default_project || ENV["BRAINTRUST_DEFAULT_PROJECT"],
app_url: app_url || ENV["BRAINTRUST_APP_URL"] || "https://www.braintrust.dev",
api_url: api_url || ENV["BRAINTRUST_API_URL"] || "https://api.braintrust.dev",
filter_ai_spans: filter_ai_spans_value,
span_filter_funcs: span_filter_funcs
span_filter_funcs: span_filter_funcs,
auto_convert_ai_attachments: auto_convert_value
)
end
end
Expand Down
27 changes: 25 additions & 2 deletions lib/braintrust/trace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
require_relative "trace/span_processor"
require_relative "trace/span_exporter"
require_relative "trace/span_filter"
require_relative "trace/attachment_processor/processor"
require_relative "trace/attachment_processor/uploader"
require_relative "internal/env"
require_relative "logger"

Expand Down Expand Up @@ -81,7 +83,7 @@ def self.flush_spans
end
end

def self.enable(tracer_provider, state: nil, exporter: nil, config: nil)
def self.enable(tracer_provider, state: nil, exporter: nil, config: nil, attachment_processor: :default)
state ||= Braintrust.current_state
raise Error, "No state available" unless state

Expand All @@ -104,8 +106,11 @@ def self.enable(tracer_provider, state: nil, exporter: nil, config: nil)
# Build filters array from config
filters = build_filters(config)

# Build the attachment processor (unless explicitly overridden / disabled)
attachment_processor = build_attachment_processor(state, config) if attachment_processor == :default

# Wrap span processor in our custom span processor to add Braintrust attributes and filters
processor = SpanProcessor.new(span_processor, state, filters)
processor = SpanProcessor.new(span_processor, state, filters, attachment_processor: attachment_processor)

# Register with tracer provider
tracer_provider.add_span_processor(processor)
Expand Down Expand Up @@ -139,6 +144,24 @@ def self.build_filters(config)
filters
end

# Build the attachment processor for a given state/config, or nil when
# attachment auto-conversion is disabled.
# @param state [State]
# @param config [Config, nil]
# @return [AttachmentProcessor::Processor, nil]
def self.build_attachment_processor(state, config)
enabled = config.nil? || config.auto_convert_ai_attachments
return nil unless enabled

uploader = AttachmentProcessor::S3Uploader.new(
api_key: state.api_key,
api_url: state.api_url,
login_url: state.app_url,
org_id: (state.org_id if state.respond_to?(:org_id))
)
AttachmentProcessor::Processor.new(uploader: uploader, logger: Log)
end

# Generate a permalink URL for a span to view in the Braintrust UI
# Returns an empty string if the permalink cannot be generated
# @param span [OpenTelemetry::Trace::Span] The span to generate a permalink for
Expand Down
Loading