Skip to content

Commit a520ed1

Browse files
committed
gzip otel payload
1 parent e0fea69 commit a520ed1

5 files changed

Lines changed: 85 additions & 8 deletions

File tree

lib/braintrust/config.rb

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@ module Braintrust
55
# and allows overriding with explicit options
66
class Config
77
attr_reader :api_key, :org_name, :default_project, :app_url, :api_url,
8-
:filter_ai_spans, :span_filter_funcs
8+
:filter_ai_spans, :span_filter_funcs, :compress_otel_payload
99

1010
def initialize(api_key: nil, org_name: nil, default_project: nil, app_url: nil, api_url: nil,
11-
filter_ai_spans: nil, span_filter_funcs: nil)
11+
filter_ai_spans: nil, span_filter_funcs: nil, compress_otel_payload: true)
1212
@api_key = api_key
1313
@org_name = org_name
1414
@default_project = default_project
1515
@app_url = app_url
1616
@api_url = api_url
1717
@filter_ai_spans = filter_ai_spans
1818
@span_filter_funcs = span_filter_funcs || []
19+
@compress_otel_payload = compress_otel_payload
1920
end
2021

2122
# Create a Config from environment variables, with option overrides
@@ -27,9 +28,10 @@ def initialize(api_key: nil, org_name: nil, default_project: nil, app_url: nil,
2728
# @param api_url [String, nil] API URL (overrides BRAINTRUST_API_URL env var)
2829
# @param filter_ai_spans [Boolean, nil] Enable AI span filtering (overrides BRAINTRUST_OTEL_FILTER_AI_SPANS env var)
2930
# @param span_filter_funcs [Array<Proc>, nil] Custom span filter functions
31+
# @param compress_otel_payload [Boolean, nil] Gzip OTEL export payloads (overrides BRAINTRUST_COMPRESS_OTEL_PAYLOAD env var). Default: true
3032
# @return [Config] the created config
3133
def self.from_env(api_key: nil, org_name: nil, default_project: nil, app_url: nil, api_url: nil,
32-
filter_ai_spans: nil, span_filter_funcs: nil)
34+
filter_ai_spans: nil, span_filter_funcs: nil, compress_otel_payload: nil)
3335
# Parse filter_ai_spans from ENV if not explicitly provided
3436
env_filter_ai_spans = ENV["BRAINTRUST_OTEL_FILTER_AI_SPANS"]
3537
filter_ai_spans_value = if filter_ai_spans.nil?
@@ -38,15 +40,31 @@ def self.from_env(api_key: nil, org_name: nil, default_project: nil, app_url: ni
3840
filter_ai_spans
3941
end
4042

43+
# Gzip OTEL payloads by default; disable via env var if not explicitly provided
44+
compress_otel_payload_value = if compress_otel_payload.nil?
45+
parse_bool(ENV["BRAINTRUST_COMPRESS_OTEL_PAYLOAD"], default: true)
46+
else
47+
compress_otel_payload
48+
end
49+
4150
new(
4251
api_key: api_key || ((ENV["BRAINTRUST_API_KEY"] && ENV["BRAINTRUST_API_KEY"].empty?) ? nil : ENV["BRAINTRUST_API_KEY"]),
4352
org_name: org_name || ENV["BRAINTRUST_ORG_NAME"],
4453
default_project: default_project || ENV["BRAINTRUST_DEFAULT_PROJECT"],
4554
app_url: app_url || ENV["BRAINTRUST_APP_URL"] || "https://www.braintrust.dev",
4655
api_url: api_url || ENV["BRAINTRUST_API_URL"] || "https://api.braintrust.dev",
4756
filter_ai_spans: filter_ai_spans_value,
48-
span_filter_funcs: span_filter_funcs
57+
span_filter_funcs: span_filter_funcs,
58+
compress_otel_payload: compress_otel_payload_value
4959
)
5060
end
61+
62+
# Parse a boolean-ish env var value. Falsy values: "false", "0", "no", "off"
63+
# (case-insensitive). nil/empty falls back to the default.
64+
def self.parse_bool(value, default:)
65+
return default if value.nil? || value.empty?
66+
67+
!%w[false 0 no off].include?(value.strip.downcase)
68+
end
5169
end
5270
end

lib/braintrust/trace.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,11 @@ def self.enable(tracer_provider, state: nil, exporter: nil, config: nil)
8989
config ||= state.respond_to?(:config) ? state.config : nil
9090

9191
# Create OTLP HTTP exporter unless override provided
92+
compress = config.nil? || config.compress_otel_payload
9293
exporter ||= SpanExporter.new(
9394
endpoint: "#{state.api_url}/otel/v1/traces",
94-
api_key: state.api_key
95+
api_key: state.api_key,
96+
compress: compress
9597
)
9698

9799
# Use SimpleSpanProcessor for InMemorySpanExporter (testing), BatchSpanProcessor for production

lib/braintrust/trace/span_exporter.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ class SpanExporter < OpenTelemetry::Exporter::OTLP::Exporter
1717
SUCCESS = OpenTelemetry::SDK::Trace::Export::SUCCESS
1818
FAILURE = OpenTelemetry::SDK::Trace::Export::FAILURE
1919

20-
def initialize(endpoint:, api_key:)
21-
super(endpoint: endpoint, headers: {"Authorization" => "Bearer #{api_key}"})
20+
def initialize(endpoint:, api_key:, compress: true)
21+
super(
22+
endpoint: endpoint,
23+
headers: {"Authorization" => "Bearer #{api_key}"},
24+
compression: compress ? "gzip" : "none"
25+
)
2226
end
2327

2428
def export(span_data, timeout: nil)

test/braintrust/config_test.rb

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"BRAINTRUST_API_KEY" => ENV["BRAINTRUST_API_KEY"],
77
"BRAINTRUST_ORG_NAME" => ENV["BRAINTRUST_ORG_NAME"],
88
"BRAINTRUST_APP_URL" => ENV["BRAINTRUST_APP_URL"],
9-
"BRAINTRUST_API_URL" => ENV["BRAINTRUST_API_URL"]
9+
"BRAINTRUST_API_URL" => ENV["BRAINTRUST_API_URL"],
10+
"BRAINTRUST_COMPRESS_OTEL_PAYLOAD" => ENV["BRAINTRUST_COMPRESS_OTEL_PAYLOAD"]
1011
}.freeze
1112

1213
class Braintrust::ConfigTest < Minitest::Test
@@ -61,4 +62,37 @@ def test_env_vars_override_defaults
6162

6263
assert_equal "https://custom.braintrust.dev", config.app_url
6364
end
65+
66+
def test_compress_otel_payload_defaults_to_true
67+
config = Braintrust::Config.from_env
68+
69+
assert_equal true, config.compress_otel_payload
70+
end
71+
72+
def test_compress_otel_payload_disabled_by_env_var
73+
%w[false 0 no off FALSE Off].each do |val|
74+
ENV["BRAINTRUST_COMPRESS_OTEL_PAYLOAD"] = val
75+
76+
config = Braintrust::Config.from_env
77+
78+
assert_equal false, config.compress_otel_payload,
79+
"expected #{val.inspect} to disable compression"
80+
end
81+
end
82+
83+
def test_compress_otel_payload_truthy_env_var
84+
ENV["BRAINTRUST_COMPRESS_OTEL_PAYLOAD"] = "true"
85+
86+
config = Braintrust::Config.from_env
87+
88+
assert_equal true, config.compress_otel_payload
89+
end
90+
91+
def test_compress_otel_payload_explicit_overrides_env_var
92+
ENV["BRAINTRUST_COMPRESS_OTEL_PAYLOAD"] = "false"
93+
94+
config = Braintrust::Config.from_env(compress_otel_payload: true)
95+
96+
assert_equal true, config.compress_otel_payload
97+
end
6498
end

test/braintrust/trace/span_exporter_test.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,25 @@ def test_empty_span_data
163163
assert_equal 0, exporter.calls.length
164164
end
165165

166+
def test_uses_gzip_compression_by_default
167+
exporter = Braintrust::Trace::SpanExporter.new(
168+
endpoint: "https://example.com/otel/v1/traces",
169+
api_key: "test-key"
170+
)
171+
172+
assert_equal "gzip", exporter.instance_variable_get(:@compression)
173+
end
174+
175+
def test_compression_disabled_when_compress_false
176+
exporter = Braintrust::Trace::SpanExporter.new(
177+
endpoint: "https://example.com/otel/v1/traces",
178+
api_key: "test-key",
179+
compress: false
180+
)
181+
182+
assert_equal "none", exporter.instance_variable_get(:@compression)
183+
end
184+
166185
def test_header_cleaned_up_even_on_error
167186
exporter = RecordingExporter.new
168187
exporter.define_singleton_method(:send_bytes) do |data, timeout:|

0 commit comments

Comments
 (0)