diff --git a/lib/braintrust/trace/span_processor.rb b/lib/braintrust/trace/span_processor.rb index 7ff7c776..cf2ba8a9 100644 --- a/lib/braintrust/trace/span_processor.rb +++ b/lib/braintrust/trace/span_processor.rb @@ -80,11 +80,6 @@ def get_parent_from_context(parent_context) # Determine if a span should be forwarded to the wrapped processor # based on configured filters def should_forward_span?(span) - # Always keep root spans (spans with no parent) - # Check if parent_span_id is the invalid/zero span ID - is_root = span.parent_span_id == OpenTelemetry::Trace::INVALID_SPAN_ID - return true if is_root - # If no filters, keep everything return true if @filters.empty? diff --git a/test/braintrust/trace/span_filter_test.rb b/test/braintrust/trace/span_filter_test.rb index 051a10ed..16ae9861 100644 --- a/test/braintrust/trace/span_filter_test.rb +++ b/test/braintrust/trace/span_filter_test.rb @@ -106,13 +106,23 @@ def test_init_with_filter_ai_spans_ignores_system_attributes assert_equal "gen_ai.root", spans[0].name end - def test_init_with_filter_ai_spans_always_keeps_root_spans + def test_init_with_filter_ai_spans_filters_root_spans exporter, tracer = setup_with_filter(filter_ai_spans: true) tracer.in_span("database.query") {} spans = exporter.finished_spans - assert_equal 1, spans.length, "Root spans should always be kept" + assert_equal 0, spans.length, "Non-AI root spans should be filtered" + end + + def test_init_with_filter_ai_spans_keeps_ai_root_spans + exporter, tracer = setup_with_filter(filter_ai_spans: true) + + tracer.in_span("gen_ai.completion") {} + + spans = exporter.finished_spans + assert_equal 1, spans.length, "AI root spans should be kept" + assert_equal "gen_ai.completion", spans[0].name end def test_init_with_filter_ai_spans_drops_non_root_non_ai_spans