diff --git a/lib/ddtrace/pipeline/span_filter.rb b/lib/ddtrace/pipeline/span_filter.rb index aa5b5d9e17a..ce2952da5cc 100644 --- a/lib/ddtrace/pipeline/span_filter.rb +++ b/lib/ddtrace/pipeline/span_filter.rb @@ -10,12 +10,22 @@ def initialize(filter = nil, &block) @criteria = filter || block end + # Note: this SpanFilter implementation only handles traces in which child spans appear + # after parent spans in the trace array. If in the future child spans can be before + # parent spans, then the code below will need to be updated. def call(trace) - black_list = trace.select(&method(:drop_it?)) - - clean_trace(black_list, trace) while black_list.any? - - trace + deleted = Set.new + + trace.delete_if do |span| + if deleted.include?(span.parent) + deleted << span + true + else + drop = drop_it?(span) + deleted << span if drop + drop + end + end end private @@ -23,16 +33,6 @@ def call(trace) def drop_it?(span) @criteria.call(span) rescue false end - - def clean_trace(black_list, trace) - current = black_list.shift - - trace.delete(current) - - trace.each do |span| - black_list << span if span.parent == current - end - end end end end