airbrake-ruby 5.2.0-java → 6.0.2-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/airbrake-ruby/async_sender.rb +3 -1
- data/lib/airbrake-ruby/config.rb +3 -3
- data/lib/airbrake-ruby/context.rb +51 -0
- data/lib/airbrake-ruby/filter_chain.rb +2 -0
- data/lib/airbrake-ruby/filters/context_filter.rb +4 -5
- data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +1 -1
- data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +2 -2
- data/lib/airbrake-ruby/filters/git_repository_filter.rb +1 -1
- data/lib/airbrake-ruby/filters/git_revision_filter.rb +1 -1
- data/lib/airbrake-ruby/filters/keys_filter.rb +2 -2
- data/lib/airbrake-ruby/filters/sql_filter.rb +8 -8
- data/lib/airbrake-ruby/filters/thread_filter.rb +1 -1
- data/lib/airbrake-ruby/ignorable.rb +0 -2
- data/lib/airbrake-ruby/monotonic_time.rb +1 -1
- data/lib/airbrake-ruby/notice_notifier.rb +3 -4
- data/lib/airbrake-ruby/performance_notifier.rb +39 -40
- data/lib/airbrake-ruby/remote_settings/settings_data.rb +1 -1
- data/lib/airbrake-ruby/remote_settings.rb +26 -3
- data/lib/airbrake-ruby/stat.rb +1 -1
- data/lib/airbrake-ruby/tdigest.rb +10 -9
- data/lib/airbrake-ruby/thread_pool.rb +8 -6
- data/lib/airbrake-ruby/time_truncate.rb +2 -2
- data/lib/airbrake-ruby/timed_trace.rb +1 -3
- data/lib/airbrake-ruby/version.rb +1 -1
- data/lib/airbrake-ruby.rb +24 -23
- data/spec/airbrake_spec.rb +139 -76
- data/spec/async_sender_spec.rb +10 -8
- data/spec/backtrace_spec.rb +13 -10
- data/spec/benchmark_spec.rb +5 -3
- data/spec/code_hunk_spec.rb +24 -15
- data/spec/config/processor_spec.rb +12 -4
- data/spec/config/validator_spec.rb +5 -2
- data/spec/config_spec.rb +28 -20
- data/spec/context_spec.rb +54 -0
- data/spec/deploy_notifier_spec.rb +6 -4
- data/spec/file_cache_spec.rb +1 -0
- data/spec/filter_chain_spec.rb +29 -24
- data/spec/filters/context_filter_spec.rb +14 -5
- data/spec/filters/dependency_filter_spec.rb +3 -1
- data/spec/filters/exception_attributes_filter_spec.rb +5 -3
- data/spec/filters/gem_root_filter_spec.rb +5 -2
- data/spec/filters/git_last_checkout_filter_spec.rb +10 -12
- data/spec/filters/git_repository_filter.rb +9 -9
- data/spec/filters/git_revision_filter_spec.rb +20 -20
- data/spec/filters/keys_allowlist_spec.rb +25 -16
- data/spec/filters/keys_blocklist_spec.rb +25 -18
- data/spec/filters/root_directory_filter_spec.rb +3 -3
- data/spec/filters/sql_filter_spec.rb +26 -26
- data/spec/filters/system_exit_filter_spec.rb +4 -2
- data/spec/filters/thread_filter_spec.rb +15 -13
- data/spec/loggable_spec.rb +2 -2
- data/spec/monotonic_time_spec.rb +8 -6
- data/spec/nested_exception_spec.rb +46 -46
- data/spec/notice_notifier/options_spec.rb +23 -13
- data/spec/notice_notifier_spec.rb +52 -47
- data/spec/notice_spec.rb +6 -2
- data/spec/performance_notifier_spec.rb +69 -62
- data/spec/promise_spec.rb +38 -32
- data/spec/remote_settings/callback_spec.rb +27 -8
- data/spec/remote_settings/settings_data_spec.rb +4 -4
- data/spec/remote_settings_spec.rb +23 -9
- data/spec/response_spec.rb +34 -12
- data/spec/stashable_spec.rb +5 -5
- data/spec/stat_spec.rb +7 -5
- data/spec/sync_sender_spec.rb +49 -16
- data/spec/tdigest_spec.rb +60 -55
- data/spec/thread_pool_spec.rb +65 -56
- data/spec/time_truncate_spec.rb +23 -6
- data/spec/timed_trace_spec.rb +32 -30
- data/spec/truncator_spec.rb +72 -43
- metadata +54 -50
data/spec/tdigest_spec.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
RSpec.describe Airbrake::TDigest do
|
2
|
+
subject(:tdigest) { described_class.new }
|
3
|
+
|
2
4
|
describe "byte serialization" do
|
3
5
|
it "loads serialized data" do
|
4
|
-
|
5
|
-
10.times {
|
6
|
-
bytes =
|
6
|
+
tdigest.push(60, 100)
|
7
|
+
10.times { tdigest.push(rand * 100) }
|
8
|
+
bytes = tdigest.as_bytes
|
7
9
|
new_tdigest = described_class.from_bytes(bytes)
|
8
|
-
expect(new_tdigest.percentile(0.9)).to eq(
|
10
|
+
expect(new_tdigest.percentile(0.9)).to eq(tdigest.percentile(0.9))
|
9
11
|
expect(new_tdigest.as_bytes).to eq(bytes)
|
10
12
|
end
|
11
13
|
|
12
14
|
it "handles zero size" do
|
13
|
-
bytes =
|
15
|
+
bytes = tdigest.as_bytes
|
14
16
|
expect(described_class.from_bytes(bytes).size).to be_zero
|
15
17
|
end
|
16
18
|
|
@@ -24,65 +26,64 @@ RSpec.describe Airbrake::TDigest do
|
|
24
26
|
|
25
27
|
describe "small byte serialization" do
|
26
28
|
it "loads serialized data" do
|
27
|
-
10.times {
|
28
|
-
bytes =
|
29
|
+
10.times { tdigest.push(10) }
|
30
|
+
bytes = tdigest.as_small_bytes
|
29
31
|
new_tdigest = described_class.from_bytes(bytes)
|
30
32
|
# Expect some rounding error due to compression
|
31
33
|
expect(new_tdigest.percentile(0.9).round(5)).to eq(
|
32
|
-
|
34
|
+
tdigest.percentile(0.9).round(5),
|
33
35
|
)
|
34
36
|
expect(new_tdigest.as_small_bytes).to eq(bytes)
|
35
37
|
end
|
36
38
|
|
37
39
|
it "handles zero size" do
|
38
|
-
bytes =
|
40
|
+
bytes = tdigest.as_small_bytes
|
39
41
|
expect(described_class.from_bytes(bytes).size).to be_zero
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
45
|
describe "JSON serialization" do
|
44
46
|
it "loads serialized data" do
|
45
|
-
|
46
|
-
json =
|
47
|
+
tdigest.push(60, 100)
|
48
|
+
json = tdigest.as_json
|
47
49
|
new_tdigest = described_class.from_json(json)
|
48
|
-
expect(new_tdigest.percentile(0.9)).to eq(
|
50
|
+
expect(new_tdigest.percentile(0.9)).to eq(tdigest.percentile(0.9))
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
52
54
|
describe "#percentile" do
|
53
55
|
it "returns nil if empty" do
|
54
|
-
expect(
|
56
|
+
expect(tdigest.percentile(0.90)).to be_nil # This should not crash
|
55
57
|
end
|
56
58
|
|
57
59
|
it "raises ArgumentError of input not between 0 and 1" do
|
58
|
-
expect {
|
60
|
+
expect { tdigest.percentile(1.1) }.to raise_error(ArgumentError)
|
59
61
|
end
|
60
62
|
|
61
63
|
describe "with only single value" do
|
62
64
|
it "returns the value" do
|
63
|
-
|
64
|
-
expect(
|
65
|
+
tdigest.push(60, 100)
|
66
|
+
expect(tdigest.percentile(0.90)).to eq(60)
|
65
67
|
end
|
66
68
|
|
67
69
|
it "returns 0 for all percentiles when only 0 present" do
|
68
|
-
|
69
|
-
expect(
|
70
|
+
tdigest.push(0)
|
71
|
+
expect(tdigest.percentile([0.0, 0.5, 1.0])).to eq([0, 0, 0])
|
70
72
|
end
|
71
73
|
end
|
72
74
|
|
73
75
|
describe "with alot of uniformly distributed points" do
|
74
76
|
it "has minimal error" do
|
75
77
|
seed = srand(1234) # Makes the values a proper fixture
|
76
|
-
N = 100_000
|
77
78
|
maxerr = 0
|
78
|
-
values = Array.new(
|
79
|
+
values = Array.new(100_000).map { rand }
|
79
80
|
srand(seed)
|
80
81
|
|
81
|
-
|
82
|
-
|
82
|
+
tdigest.push(values)
|
83
|
+
tdigest.compress!
|
83
84
|
|
84
85
|
0.step(1, 0.1).each do |i|
|
85
|
-
q =
|
86
|
+
q = tdigest.percentile(i)
|
86
87
|
maxerr = [maxerr, (i - q).abs].max
|
87
88
|
end
|
88
89
|
|
@@ -93,7 +94,7 @@ RSpec.describe Airbrake::TDigest do
|
|
93
94
|
|
94
95
|
describe "#push" do
|
95
96
|
it "calls _cumulate so won't crash because of uninitialized mean_cumn" do
|
96
|
-
|
97
|
+
tdigest.push(
|
97
98
|
[
|
98
99
|
125000000.0,
|
99
100
|
104166666.66666666,
|
@@ -132,59 +133,62 @@ RSpec.describe Airbrake::TDigest do
|
|
132
133
|
end
|
133
134
|
|
134
135
|
it "does not blow up if data comes in sorted" do
|
135
|
-
|
136
|
-
expect(
|
137
|
-
|
138
|
-
expect(
|
136
|
+
tdigest.push(0..10_000)
|
137
|
+
expect(tdigest.centroids.size).to be < 5_000
|
138
|
+
tdigest.compress!
|
139
|
+
expect(tdigest.centroids.size).to be < 1_000
|
139
140
|
end
|
140
141
|
end
|
141
142
|
|
142
143
|
describe "#size" do
|
143
144
|
it "reports the number of observations" do
|
144
145
|
n = 10_000
|
145
|
-
n.times {
|
146
|
-
|
147
|
-
expect(
|
146
|
+
n.times { tdigest.push(rand) }
|
147
|
+
tdigest.compress!
|
148
|
+
expect(tdigest.size).to eq(n)
|
148
149
|
end
|
149
150
|
end
|
150
151
|
|
151
152
|
describe "#+" do
|
152
153
|
it "works with empty tdigests" do
|
153
154
|
other = described_class.new(0.001, 50, 1.2)
|
154
|
-
expect((
|
155
|
+
expect((tdigest + other).centroids.size).to eq(0)
|
155
156
|
end
|
156
157
|
|
157
158
|
describe "adding two tdigests" do
|
159
|
+
let(:other) { described_class.new(0.001, 50, 1.2) }
|
160
|
+
|
158
161
|
before do
|
159
|
-
|
160
|
-
[subject, @other].each do |td|
|
162
|
+
[tdigest, other].each do |td|
|
161
163
|
td.push(60, 100)
|
162
164
|
10.times { td.push(rand * 100) }
|
163
165
|
end
|
164
166
|
end
|
165
167
|
|
168
|
+
# rubocop:disable RSpec/MultipleExpectations
|
166
169
|
it "has the parameters of the left argument (the calling tdigest)" do
|
167
|
-
new_tdigest =
|
170
|
+
new_tdigest = tdigest + other
|
168
171
|
expect(new_tdigest.instance_variable_get(:@delta)).to eq(
|
169
|
-
|
172
|
+
tdigest.instance_variable_get(:@delta),
|
170
173
|
)
|
171
174
|
expect(new_tdigest.instance_variable_get(:@k)).to eq(
|
172
|
-
|
175
|
+
tdigest.instance_variable_get(:@k),
|
173
176
|
)
|
174
177
|
expect(new_tdigest.instance_variable_get(:@cx)).to eq(
|
175
|
-
|
178
|
+
tdigest.instance_variable_get(:@cx),
|
176
179
|
)
|
177
180
|
end
|
181
|
+
# rubocop:enable RSpec/MultipleExpectations
|
178
182
|
|
179
183
|
it "returns a tdigest with less than or equal centroids" do
|
180
|
-
new_tdigest =
|
184
|
+
new_tdigest = tdigest + other
|
181
185
|
expect(new_tdigest.centroids.size)
|
182
|
-
.to be <=
|
186
|
+
.to be <= tdigest.centroids.size + other.centroids.size
|
183
187
|
end
|
184
188
|
|
185
189
|
it "has the size of the two digests combined" do
|
186
|
-
new_tdigest =
|
187
|
-
expect(new_tdigest.size).to eq(
|
190
|
+
new_tdigest = tdigest + other
|
191
|
+
expect(new_tdigest.size).to eq(tdigest.size + other.size)
|
188
192
|
end
|
189
193
|
end
|
190
194
|
end
|
@@ -192,14 +196,15 @@ RSpec.describe Airbrake::TDigest do
|
|
192
196
|
describe "#merge!" do
|
193
197
|
it "works with empty tdigests" do
|
194
198
|
other = described_class.new(0.001, 50, 1.2)
|
195
|
-
|
196
|
-
expect(
|
199
|
+
tdigest.merge!(other)
|
200
|
+
expect(tdigest.centroids.size).to be_zero
|
197
201
|
end
|
198
202
|
|
199
203
|
describe "with populated tdigests" do
|
204
|
+
let(:other) { described_class.new(0.001, 50, 1.2) }
|
205
|
+
|
200
206
|
before do
|
201
|
-
|
202
|
-
[subject, @other].each do |td|
|
207
|
+
[tdigest, other].each do |td|
|
203
208
|
td.push(60, 100)
|
204
209
|
10.times { td.push(rand * 100) }
|
205
210
|
end
|
@@ -207,23 +212,23 @@ RSpec.describe Airbrake::TDigest do
|
|
207
212
|
|
208
213
|
it "has the parameters of the calling tdigest" do
|
209
214
|
vars = %i[@delta @k @cx]
|
210
|
-
expected =
|
211
|
-
|
215
|
+
expected = vars.map { |v| [v, tdigest.instance_variable_get(v)] }.to_h
|
216
|
+
tdigest.merge!(other)
|
212
217
|
vars.each do |v|
|
213
|
-
expect(
|
218
|
+
expect(tdigest.instance_variable_get(v)).to eq(expected[v])
|
214
219
|
end
|
215
220
|
end
|
216
221
|
|
217
222
|
it "returns a tdigest with less than or equal centroids" do
|
218
|
-
combined_size =
|
219
|
-
|
220
|
-
expect(
|
223
|
+
combined_size = tdigest.centroids.size + other.centroids.size
|
224
|
+
tdigest.merge!(other)
|
225
|
+
expect(tdigest.centroids.size).to be <= combined_size
|
221
226
|
end
|
222
227
|
|
223
228
|
it "has the size of the two digests combined" do
|
224
|
-
combined_size =
|
225
|
-
|
226
|
-
expect(
|
229
|
+
combined_size = tdigest.size + other.size
|
230
|
+
tdigest.merge!(other)
|
231
|
+
expect(tdigest.size).to eq(combined_size)
|
227
232
|
end
|
228
233
|
end
|
229
234
|
end
|
data/spec/thread_pool_spec.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
RSpec.describe Airbrake::ThreadPool do
|
2
|
-
|
3
|
-
let(:worker_size) { 1 }
|
4
|
-
let(:queue_size) { 2 }
|
5
|
-
|
6
|
-
subject do
|
2
|
+
subject(:thread_pool) do
|
7
3
|
described_class.new(
|
8
4
|
worker_size: worker_size,
|
9
5
|
queue_size: queue_size,
|
@@ -11,27 +7,27 @@ RSpec.describe Airbrake::ThreadPool do
|
|
11
7
|
)
|
12
8
|
end
|
13
9
|
|
10
|
+
let(:tasks) { [] }
|
11
|
+
let(:worker_size) { 1 }
|
12
|
+
let(:queue_size) { 2 }
|
13
|
+
|
14
14
|
describe "#<<" do
|
15
15
|
it "returns true" do
|
16
|
-
retval =
|
17
|
-
|
16
|
+
retval = thread_pool << 1
|
17
|
+
thread_pool.close
|
18
18
|
expect(retval).to eq(true)
|
19
19
|
end
|
20
20
|
|
21
21
|
it "performs work in background" do
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
thread_pool << 2
|
23
|
+
thread_pool << 1
|
24
|
+
thread_pool.close
|
25
25
|
|
26
26
|
expect(tasks).to eq([2, 1])
|
27
27
|
end
|
28
28
|
|
29
29
|
context "when the queue is full" do
|
30
|
-
|
31
|
-
allow(subject).to receive(:backlog).and_return(queue_size)
|
32
|
-
end
|
33
|
-
|
34
|
-
subject do
|
30
|
+
subject(:full_thread_pool) do
|
35
31
|
described_class.new(
|
36
32
|
worker_size: 1,
|
37
33
|
queue_size: 1,
|
@@ -39,26 +35,33 @@ RSpec.describe Airbrake::ThreadPool do
|
|
39
35
|
)
|
40
36
|
end
|
41
37
|
|
38
|
+
before do
|
39
|
+
# rubocop:disable RSpec/SubjectStub
|
40
|
+
allow(full_thread_pool).to receive(:backlog).and_return(queue_size)
|
41
|
+
# rubocop:enable RSpec/SubjectStub
|
42
|
+
end
|
43
|
+
|
42
44
|
it "returns false" do
|
43
|
-
retval =
|
44
|
-
|
45
|
+
retval = full_thread_pool << 1
|
46
|
+
full_thread_pool.close
|
45
47
|
expect(retval).to eq(false)
|
46
48
|
end
|
47
49
|
|
48
50
|
it "discards tasks" do
|
49
|
-
200.times {
|
50
|
-
|
51
|
+
200.times { full_thread_pool << 1 }
|
52
|
+
full_thread_pool.close
|
51
53
|
|
52
54
|
expect(tasks.size).to be_zero
|
53
55
|
end
|
54
56
|
|
55
57
|
it "logs discarded tasks" do
|
56
|
-
|
57
|
-
|
58
|
-
|
58
|
+
allow(Airbrake::Loggable.instance).to receive(:info)
|
59
|
+
|
60
|
+
15.times { full_thread_pool << 1 }
|
61
|
+
full_thread_pool.close
|
59
62
|
|
60
|
-
|
61
|
-
|
63
|
+
expect(Airbrake::Loggable.instance)
|
64
|
+
.to have_received(:info).exactly(15).times
|
62
65
|
end
|
63
66
|
end
|
64
67
|
end
|
@@ -67,22 +70,22 @@ RSpec.describe Airbrake::ThreadPool do
|
|
67
70
|
let(:worker_size) { 0 }
|
68
71
|
|
69
72
|
it "returns the size of the queue" do
|
70
|
-
|
71
|
-
expect(
|
73
|
+
thread_pool << 1
|
74
|
+
expect(thread_pool.backlog).to eq(1)
|
72
75
|
end
|
73
76
|
end
|
74
77
|
|
75
78
|
describe "#has_workers?" do
|
76
79
|
it "returns false when the thread pool is not closed, but has 0 workers" do
|
77
|
-
|
80
|
+
thread_pool.workers.list.each do |worker|
|
78
81
|
worker.kill.join
|
79
82
|
end
|
80
|
-
expect(
|
83
|
+
expect(thread_pool).not_to have_workers
|
81
84
|
end
|
82
85
|
|
83
86
|
it "returns false when the thread pool is closed" do
|
84
|
-
|
85
|
-
expect(
|
87
|
+
thread_pool.close
|
88
|
+
expect(thread_pool).not_to have_workers
|
86
89
|
end
|
87
90
|
|
88
91
|
describe "forking behavior" do
|
@@ -93,20 +96,22 @@ RSpec.describe Airbrake::ThreadPool do
|
|
93
96
|
end
|
94
97
|
end
|
95
98
|
|
99
|
+
# rubocop:disable RSpec/MultipleExpectations
|
96
100
|
it "respawns workers on fork()" do
|
97
|
-
pid = fork { expect(
|
101
|
+
pid = fork { expect(thread_pool).to have_workers }
|
98
102
|
Process.wait(pid)
|
99
|
-
|
103
|
+
thread_pool.close
|
100
104
|
|
101
105
|
expect(Process.last_status).to be_success
|
102
|
-
expect(
|
106
|
+
expect(thread_pool).not_to have_workers
|
103
107
|
end
|
108
|
+
# rubocop:enable RSpec/MultipleExpectations
|
104
109
|
|
105
110
|
it "ensures that a new thread group is created per process" do
|
106
|
-
|
107
|
-
pid = fork {
|
111
|
+
thread_pool << 1
|
112
|
+
pid = fork { thread_pool.has_workers? }
|
108
113
|
Process.wait(pid)
|
109
|
-
|
114
|
+
thread_pool.close
|
110
115
|
|
111
116
|
expect(Process.last_status).to be_success
|
112
117
|
end
|
@@ -116,27 +121,29 @@ RSpec.describe Airbrake::ThreadPool do
|
|
116
121
|
describe "#close" do
|
117
122
|
context "when there's no work to do" do
|
118
123
|
it "joins the spawned thread" do
|
119
|
-
workers =
|
124
|
+
workers = thread_pool.workers.list
|
120
125
|
expect(workers).to all(be_alive)
|
121
126
|
|
122
|
-
|
127
|
+
thread_pool.close
|
123
128
|
expect(workers).to all(be_stop)
|
124
129
|
end
|
125
130
|
end
|
126
131
|
|
127
132
|
context "when there's some work to do" do
|
128
133
|
it "logs how many tasks are left to process" do
|
129
|
-
|
130
|
-
worker_size: 0, queue_size: 2, block: proc {},
|
131
|
-
)
|
134
|
+
allow(Airbrake::Loggable.instance).to receive(:debug)
|
132
135
|
|
133
|
-
|
134
|
-
|
136
|
+
thread_pool = described_class.new(
|
137
|
+
name: 'foo', worker_size: 0, queue_size: 2, block: proc {},
|
135
138
|
)
|
136
|
-
expect(Airbrake::Loggable.instance).to receive(:debug).with(/closed/)
|
137
139
|
|
138
140
|
2.times { thread_pool << 1 }
|
139
141
|
thread_pool.close
|
142
|
+
|
143
|
+
expect(Airbrake::Loggable.instance).to have_received(:debug).with(
|
144
|
+
/waiting to process \d+ task\(s\)/,
|
145
|
+
)
|
146
|
+
expect(Airbrake::Loggable.instance).to have_received(:debug).with(/foo.+closed/)
|
140
147
|
end
|
141
148
|
|
142
149
|
it "waits until the queue gets empty" do
|
@@ -144,7 +151,7 @@ RSpec.describe Airbrake::ThreadPool do
|
|
144
151
|
worker_size: 1, queue_size: 2, block: proc {},
|
145
152
|
)
|
146
153
|
|
147
|
-
10.times {
|
154
|
+
10.times { thread_pool << 1 }
|
148
155
|
thread_pool.close
|
149
156
|
expect(thread_pool.backlog).to be_zero
|
150
157
|
end
|
@@ -153,17 +160,17 @@ RSpec.describe Airbrake::ThreadPool do
|
|
153
160
|
context "when it was already closed" do
|
154
161
|
it "doesn't increase the queue size" do
|
155
162
|
begin
|
156
|
-
|
163
|
+
thread_pool.close
|
157
164
|
rescue Airbrake::Error
|
158
165
|
nil
|
159
166
|
end
|
160
167
|
|
161
|
-
expect(
|
168
|
+
expect(thread_pool.backlog).to be_zero
|
162
169
|
end
|
163
170
|
|
164
171
|
it "raises error" do
|
165
|
-
|
166
|
-
expect {
|
172
|
+
thread_pool.close
|
173
|
+
expect { thread_pool.close }.to raise_error(
|
167
174
|
Airbrake::Error, 'this thread pool is closed already'
|
168
175
|
)
|
169
176
|
end
|
@@ -171,17 +178,19 @@ RSpec.describe Airbrake::ThreadPool do
|
|
171
178
|
end
|
172
179
|
|
173
180
|
describe "#spawn_workers" do
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
expect(
|
181
|
+
after { thread_pool.close }
|
182
|
+
|
183
|
+
it "spawns an enclosed thread group" do
|
184
|
+
expect(thread_pool.workers).to be_a(ThreadGroup)
|
185
|
+
expect(thread_pool.workers).to be_enclosed
|
186
|
+
end
|
178
187
|
|
179
|
-
|
188
|
+
it "spawns threads that are alive" do
|
189
|
+
expect(thread_pool.workers.list).to all(be_alive)
|
180
190
|
end
|
181
191
|
|
182
192
|
it "spawns exactly `workers_size` workers" do
|
183
|
-
expect(
|
184
|
-
subject.close
|
193
|
+
expect(thread_pool.workers.list.size).to eq(worker_size)
|
185
194
|
end
|
186
195
|
end
|
187
196
|
end
|
data/spec/time_truncate_spec.rb
CHANGED
@@ -1,13 +1,30 @@
|
|
1
1
|
RSpec.describe Airbrake::TimeTruncate do
|
2
|
+
time = Time.new(2018, 1, 1, 0, 0, 20, 0)
|
3
|
+
time_with_zone = Time.new(2018, 1, 1, 0, 0, 20, '-05:00')
|
4
|
+
|
2
5
|
describe "#utc_truncate_minutes" do
|
3
|
-
|
4
|
-
time
|
5
|
-
|
6
|
+
shared_examples 'time conversion' do |t|
|
7
|
+
it "truncates the time to the floor minute and returns an RFC3339 timestamp" do
|
8
|
+
expect(described_class.utc_truncate_minutes(t))
|
9
|
+
.to eq('2018-01-01T00:00:00+00:00')
|
10
|
+
end
|
11
|
+
|
12
|
+
it "converts time with zone to UTC" do
|
13
|
+
expect(described_class.utc_truncate_minutes(time_with_zone))
|
14
|
+
.to eq('2018-01-01T05:00:00+00:00')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when the time argument is a Time object" do
|
19
|
+
include_examples 'time conversion', time
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when the time argument is a Float" do
|
23
|
+
include_examples 'time conversion', time.to_f
|
6
24
|
end
|
7
25
|
|
8
|
-
|
9
|
-
time
|
10
|
-
expect(subject.utc_truncate_minutes(time)).to eq('2018-01-01T05:00:00+00:00')
|
26
|
+
context "when the time argument is an Integer" do
|
27
|
+
include_examples 'time conversion', time.to_i
|
11
28
|
end
|
12
29
|
end
|
13
30
|
end
|
data/spec/timed_trace_spec.rb
CHANGED
@@ -1,50 +1,52 @@
|
|
1
1
|
RSpec.describe Airbrake::TimedTrace do
|
2
|
+
subject(:timed_trace) { described_class.new }
|
3
|
+
|
2
4
|
describe ".span" do
|
3
5
|
it "returns a timed trace" do
|
4
|
-
expect(described_class.span('operation') {}).to be_a(described_class)
|
6
|
+
expect(described_class.span('operation') { anything }).to be_a(described_class)
|
5
7
|
end
|
6
8
|
|
7
9
|
it "returns a timed trace with a stopped span" do
|
8
|
-
timed_trace = described_class.span('operation') {}
|
10
|
+
timed_trace = described_class.span('operation') { anything }
|
9
11
|
expect(timed_trace.spans).to match('operation' => be > 0)
|
10
12
|
end
|
11
13
|
end
|
12
14
|
|
13
15
|
describe "#span" do
|
14
16
|
it "captures a span" do
|
15
|
-
|
16
|
-
expect(
|
17
|
+
timed_trace.span('operation') { anything }
|
18
|
+
expect(timed_trace.spans).to match('operation' => be > 0)
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
22
|
describe "#start_span" do
|
21
23
|
context "when called once" do
|
22
24
|
it "returns true" do
|
23
|
-
expect(
|
25
|
+
expect(timed_trace.start_span('operation')).to eq(true)
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
27
29
|
context "when called multiple times" do
|
28
|
-
before {
|
30
|
+
before { timed_trace.start_span('operation') }
|
29
31
|
|
30
32
|
it "returns false" do
|
31
|
-
expect(
|
33
|
+
expect(timed_trace.start_span('operation')).to eq(false)
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
35
37
|
context "when another span was started" do
|
36
|
-
before {
|
38
|
+
before { timed_trace.start_span('operation') }
|
37
39
|
|
38
40
|
it "returns true" do
|
39
|
-
expect(
|
41
|
+
expect(timed_trace.start_span('another operation')).to eq(true)
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
45
|
context "when #spans was called" do
|
44
|
-
before {
|
46
|
+
before { timed_trace.start_span('operation') }
|
45
47
|
|
46
48
|
it "returns spans with zero values" do
|
47
|
-
expect(
|
49
|
+
expect(timed_trace.spans).to eq('operation' => 0.0)
|
48
50
|
end
|
49
51
|
end
|
50
52
|
end
|
@@ -52,35 +54,35 @@ RSpec.describe Airbrake::TimedTrace do
|
|
52
54
|
describe "#stop_span" do
|
53
55
|
context "when #start_span wasn't invoked" do
|
54
56
|
it "returns false" do
|
55
|
-
expect(
|
57
|
+
expect(timed_trace.stop_span('operation')).to eq(false)
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
61
|
context "when #start_span was invoked" do
|
60
|
-
before {
|
62
|
+
before { timed_trace.start_span('operation') }
|
61
63
|
|
62
64
|
it "returns true" do
|
63
|
-
expect(
|
65
|
+
expect(timed_trace.stop_span('operation')).to eq(true)
|
64
66
|
end
|
65
67
|
end
|
66
68
|
|
67
69
|
context "when multiple spans were started" do
|
68
70
|
before do
|
69
|
-
|
70
|
-
|
71
|
+
timed_trace.start_span('operation')
|
72
|
+
timed_trace.start_span('another operation')
|
71
73
|
end
|
72
74
|
|
73
75
|
context "and when stopping in LIFO order" do
|
74
76
|
it "returns true for all spans" do
|
75
|
-
expect(
|
76
|
-
expect(
|
77
|
+
expect(timed_trace.stop_span('another operation')).to eq(true)
|
78
|
+
expect(timed_trace.stop_span('operation')).to eq(true)
|
77
79
|
end
|
78
80
|
end
|
79
81
|
|
80
82
|
context "and when stopping in FIFO order" do
|
81
83
|
it "returns true for all spans" do
|
82
|
-
expect(
|
83
|
-
expect(
|
84
|
+
expect(timed_trace.stop_span('operation')).to eq(true)
|
85
|
+
expect(timed_trace.stop_span('another operation')).to eq(true)
|
84
86
|
end
|
85
87
|
end
|
86
88
|
end
|
@@ -89,33 +91,33 @@ RSpec.describe Airbrake::TimedTrace do
|
|
89
91
|
describe "#spans" do
|
90
92
|
context "when no spans were captured" do
|
91
93
|
it "returns an empty hash" do
|
92
|
-
expect(
|
94
|
+
expect(timed_trace.spans).to eq({})
|
93
95
|
end
|
94
96
|
end
|
95
97
|
|
96
98
|
context "when a span was captured" do
|
97
99
|
before do
|
98
|
-
|
99
|
-
|
100
|
+
timed_trace.start_span('operation')
|
101
|
+
timed_trace.stop_span('operation')
|
100
102
|
end
|
101
103
|
|
102
104
|
it "returns a Hash with the corresponding span" do
|
103
|
-
|
104
|
-
expect(
|
105
|
+
timed_trace.stop_span('operation')
|
106
|
+
expect(timed_trace.spans).to match('operation' => be > 0)
|
105
107
|
end
|
106
108
|
end
|
107
109
|
|
108
110
|
context "when multiple spans were captured" do
|
109
111
|
before do
|
110
|
-
|
111
|
-
|
112
|
+
timed_trace.start_span('operation')
|
113
|
+
timed_trace.stop_span('operation')
|
112
114
|
|
113
|
-
|
114
|
-
|
115
|
+
timed_trace.start_span('another operation')
|
116
|
+
timed_trace.stop_span('another operation')
|
115
117
|
end
|
116
118
|
|
117
119
|
it "returns a Hash with all spans" do
|
118
|
-
expect(
|
120
|
+
expect(timed_trace.spans).to match(
|
119
121
|
'operation' => be > 0,
|
120
122
|
'another operation' => be > 0,
|
121
123
|
)
|