Skip to content

Commit 9aa6492

Browse files
committed
Isolate sucker_punch fetch_spans calls.
1 parent 88fe894 commit 9aa6492

File tree

2 files changed

+33
-25
lines changed

2 files changed

+33
-25
lines changed

spec/datadog/tracing/contrib/sucker_punch/patcher_spec.rb

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
end
4040

4141
let(:expect_thread?) { true }
42+
let(:mutex) { Mutex.new }
4243

4344
let(:worker_class) do
4445
Class.new do
@@ -50,6 +51,12 @@ def perform(action = :none, **_)
5051
end
5152
end
5253

54+
def check_span_count_eq(count)
55+
mutex.synchronize do
56+
try_wait_until { fetch_spans_without_sorting.length == count }
57+
end
58+
end
59+
5360
context 'successful job' do
5461
subject(:dummy_worker_success) { worker_class.perform_async }
5562

@@ -60,19 +67,19 @@ def perform(action = :none, **_)
6067
it_behaves_like 'measured span for integration', true do
6168
before do
6269
dummy_worker_success
63-
try_wait_until { fetch_spans.length == 2 }
70+
check_span_count_eq(2)
6471
end
6572
end
6673

6774
it 'generates two spans, one for pushing to enqueue and one for the job itself' do
6875
is_expected.to be true
69-
try_wait_until { fetch_spans.length == 2 }
76+
check_span_count_eq(2)
7077
expect(spans.length).to eq(2)
7178
end
7279

7380
it 'instruments successful job' do
7481
is_expected.to be true
75-
try_wait_until { fetch_spans.length == 2 }
82+
check_span_count_eq(2)
7683

7784
expect(job_span.service).to eq(tracer.default_service)
7885
expect(job_span.name).to eq('sucker_punch.perform')
@@ -85,7 +92,7 @@ def perform(action = :none, **_)
8592

8693
it 'instruments successful enqueuing' do
8794
is_expected.to be true
88-
try_wait_until { fetch_spans.length == 2 }
95+
check_span_count_eq(2)
8996

9097
expect(enqueue_span.service).to eq(tracer.default_service)
9198
expect(enqueue_span.name).to eq('sucker_punch.perform_async')
@@ -106,13 +113,13 @@ def perform(action = :none, **_)
106113
it_behaves_like 'measured span for integration', true do
107114
before do
108115
dummy_worker_fail
109-
try_wait_until { fetch_spans.length == 2 }
116+
check_span_count_eq(2)
110117
end
111118
end
112119

113120
it 'instruments a failed job' do
114121
is_expected.to be true
115-
try_wait_until { fetch_spans.length == 2 }
122+
check_span_count_eq(2)
116123

117124
expect(job_span.service).to eq(tracer.default_service)
118125
expect(job_span.name).to eq('sucker_punch.perform')
@@ -133,13 +140,13 @@ def perform(action = :none, **_)
133140
it_behaves_like 'measured span for integration', true do
134141
before do
135142
dummy_worker_delay
136-
try_wait_until { fetch_spans.length == 2 }
143+
check_span_count_eq(2)
137144
end
138145
end
139146

140147
it 'instruments enqueuing for a delayed job' do
141148
dummy_worker_delay
142-
try_wait_until { fetch_spans.length == 2 }
149+
check_span_count_eq(2)
143150

144151
expect(enqueue_span.service).to eq(tracer.default_service)
145152
expect(enqueue_span.name).to eq('sucker_punch.perform_in')

spec/datadog/tracing/contrib/support/tracer_helpers.rb

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ module TracerHelpers
1414
# Returns the current tracer instance
1515
def tracer
1616
Datadog::Tracing.send(:tracer)
17-
@write_lock = Mutex.new
1817
end
1918

2019
# Returns spans and caches it (similar to +let(:spans)+).
@@ -36,33 +35,34 @@ def fetch_traces(tracer = self.tracer)
3635
# Retrieves and sorts all spans in the current tracer instance.
3736
# This method does not cache its results.
3837
def fetch_spans(tracer = self.tracer)
39-
lock = tracer.instance_variable_get(:@write_lock)
40-
return [] if lock.nil?
41-
lock.synchronize do
42-
traces = fetch_traces(tracer)
43-
traces.collect(&:spans).flatten.sort! do |a, b|
44-
if a.name == b.name
45-
if a.resource == b.resource
46-
if a.start_time == b.start_time
47-
a.end_time <=> b.end_time
48-
else
49-
a.start_time <=> b.start_time
50-
end
38+
traces = fetch_traces(tracer)
39+
traces.collect(&:spans).flatten.sort! do |a, b|
40+
if a.name == b.name
41+
if a.resource == b.resource
42+
if a.start_time == b.start_time
43+
a.end_time <=> b.end_time
5144
else
52-
a.resource <=> b.resource
45+
a.start_time <=> b.start_time
5346
end
5447
else
55-
a.name <=> b.name
48+
a.resource <=> b.resource
5649
end
50+
else
51+
a.name <=> b.name
5752
end
5853
end
5954
end
6055

56+
def fetch_spans_without_sorting(tracer = self.tracer)
57+
traces = fetch_traces(tracer)
58+
spans = traces.collect(&:spans)
59+
spans.flatten # gets spans for every trace in the tracer instance
60+
end
61+
6162
# Remove all traces from the current tracer instance and
6263
# busts cache of +#spans+ and +#span+.
6364
def clear_traces!
6465
tracer.instance_variable_set(:@traces, [])
65-
tracer.instance_variable_set(:@write_lock, Mutex.new)
6666

6767
@traces = nil
6868
@trace = nil
@@ -79,9 +79,10 @@ def clear_traces!
7979
instance = method.call(**args, &block)
8080

8181
# The mutex must be eagerly initialized to prevent race conditions on lazy initialization
82+
write_lock = Mutex.new
8283
allow(instance).to receive(:write) do |trace|
8384
instance.instance_exec do
84-
tracer.instance_variable_get(:@write_lock).synchronize do
85+
write_lock.synchronize do
8586
@traces ||= []
8687
@traces << trace
8788
end

0 commit comments

Comments
 (0)