airbrake-ruby 4.5.1 → 4.7.0
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.rb +2 -0
- data/lib/airbrake-ruby/async_sender.rb +21 -83
- data/lib/airbrake-ruby/config.rb +24 -3
- data/lib/airbrake-ruby/file_cache.rb +6 -0
- data/lib/airbrake-ruby/filters/sql_filter.rb +22 -1
- data/lib/airbrake-ruby/performance_breakdown.rb +2 -1
- data/lib/airbrake-ruby/performance_notifier.rb +44 -16
- data/lib/airbrake-ruby/query.rb +2 -1
- data/lib/airbrake-ruby/request.rb +2 -1
- data/lib/airbrake-ruby/thread_pool.rb +128 -0
- data/lib/airbrake-ruby/version.rb +1 -1
- data/spec/async_sender_spec.rb +32 -115
- data/spec/config_spec.rb +45 -0
- data/spec/{file_cache.rb → file_cache_spec.rb} +2 -4
- data/spec/filters/sql_filter_spec.rb +47 -4
- data/spec/filters/thread_filter_spec.rb +2 -2
- data/spec/{notice_notifier_spec → notice_notifier}/options_spec.rb +0 -0
- data/spec/performance_notifier_spec.rb +64 -28
- data/spec/thread_pool_spec.rb +158 -0
- metadata +9 -6
@@ -245,12 +245,12 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
|
|
245
245
|
|
246
246
|
it "appends thread inspect (self)" do
|
247
247
|
subject.call(notice)
|
248
|
-
expect(notice[:params][:thread][:self]).to match(/\A#<Thread
|
248
|
+
expect(notice[:params][:thread][:self]).to match(/\A#<Thread:.+>\z/)
|
249
249
|
end
|
250
250
|
|
251
251
|
it "appends thread group" do
|
252
252
|
subject.call(notice)
|
253
|
-
expect(notice[:params][:thread][:group][0]).to match(/\A#<Thread
|
253
|
+
expect(notice[:params][:thread][:group][0]).to match(/\A#<Thread:.+>\z/)
|
254
254
|
end
|
255
255
|
|
256
256
|
it "appends priority" do
|
File without changes
|
@@ -12,7 +12,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
12
12
|
project_id: 1,
|
13
13
|
project_key: 'banana',
|
14
14
|
performance_stats: true,
|
15
|
-
performance_stats_flush_period: 0
|
15
|
+
performance_stats_flush_period: 0,
|
16
|
+
query_stats: true
|
16
17
|
)
|
17
18
|
end
|
18
19
|
|
@@ -30,6 +31,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
30
31
|
end_time: Time.new(2018, 1, 1, 0, 50, 0, 0)
|
31
32
|
)
|
32
33
|
)
|
34
|
+
subject.close
|
33
35
|
|
34
36
|
expect(
|
35
37
|
a_request(:put, queries).with(body: %r|
|
@@ -59,6 +61,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
59
61
|
end_time: Time.new(2018, 1, 1, 0, 50, 0, 0)
|
60
62
|
)
|
61
63
|
)
|
64
|
+
subject.close
|
62
65
|
|
63
66
|
expect(
|
64
67
|
a_request(:put, routes).with(body: %r|
|
@@ -86,6 +89,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
86
89
|
groups: { db: 131, view: 421 }
|
87
90
|
)
|
88
91
|
)
|
92
|
+
subject.close
|
89
93
|
|
90
94
|
expect(
|
91
95
|
a_request(:put, breakdowns).with(body: %r|
|
@@ -125,6 +129,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
125
129
|
start_time: Time.new(2018, 1, 1, 0, 0, 20, 0)
|
126
130
|
)
|
127
131
|
)
|
132
|
+
subject.close
|
133
|
+
|
128
134
|
expect(
|
129
135
|
a_request(:put, routes).with(body: /"time":"2018-01-01T00:00:00\+00:00"/)
|
130
136
|
).to have_been_made
|
@@ -147,6 +153,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
147
153
|
start_time: Time.new(2018, 1, 1, 0, 0, 50, 0)
|
148
154
|
)
|
149
155
|
)
|
156
|
+
subject.close
|
157
|
+
|
150
158
|
expect(
|
151
159
|
a_request(:put, routes).with(body: /"count":2/)
|
152
160
|
).to have_been_made
|
@@ -171,6 +179,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
171
179
|
end_time: Time.new(2018, 1, 1, 0, 1, 55, 0)
|
172
180
|
)
|
173
181
|
)
|
182
|
+
subject.close
|
183
|
+
|
174
184
|
expect(
|
175
185
|
a_request(:put, routes).with(
|
176
186
|
body: %r|\A
|
@@ -205,6 +215,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
205
215
|
end_time: Time.new(2018, 1, 1, 0, 50, 0, 0)
|
206
216
|
)
|
207
217
|
)
|
218
|
+
subject.close
|
219
|
+
|
208
220
|
expect(
|
209
221
|
a_request(:put, routes).with(
|
210
222
|
body: %r|\A
|
@@ -241,6 +253,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
241
253
|
groups: { db: 55, view: 11 }
|
242
254
|
)
|
243
255
|
)
|
256
|
+
subject.close
|
244
257
|
|
245
258
|
expect(
|
246
259
|
a_request(:put, breakdowns).with(body: %r|
|
@@ -280,38 +293,20 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
280
293
|
start_time: Time.new(2018, 1, 1, 0, 49, 0, 0)
|
281
294
|
)
|
282
295
|
)
|
296
|
+
subject.close
|
297
|
+
|
283
298
|
expect(promise).to be_an(Airbrake::Promise)
|
284
299
|
expect(promise.value).to eq('' => nil)
|
285
300
|
end
|
286
301
|
|
287
|
-
it "
|
288
|
-
Airbrake::
|
289
|
-
|
290
|
-
promise = subject.notify(
|
291
|
-
Airbrake::Request.new(
|
292
|
-
method: 'GET', route: '/foo', status_code: 200, start_time: Time.new
|
293
|
-
)
|
294
|
-
)
|
295
|
-
|
296
|
-
expect(a_request(:put, routes)).not_to have_been_made
|
297
|
-
expect(promise.value).to eq(
|
298
|
-
'error' => "The Performance Stats feature is disabled"
|
299
|
-
)
|
300
|
-
end
|
301
|
-
|
302
|
-
it "doesn't send route stats when current environment is ignored" do
|
303
|
-
Airbrake::Config.instance.merge(
|
304
|
-
performance_stats: true, environment: 'test', ignore_environments: %w[test]
|
302
|
+
it "checks performance stat configuration" do
|
303
|
+
request = Airbrake::Request.new(
|
304
|
+
method: 'GET', route: '/foo', status_code: 200, start_time: Time.new
|
305
305
|
)
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
)
|
311
|
-
)
|
312
|
-
|
313
|
-
expect(a_request(:put, routes)).not_to have_been_made
|
314
|
-
expect(promise.value).to eq('error' => "current environment 'test' is ignored")
|
306
|
+
expect(Airbrake::Config.instance).to receive(:check_performance_options)
|
307
|
+
.with(request).and_return(Airbrake::Promise.new)
|
308
|
+
subject.notify(request)
|
309
|
+
subject.close
|
315
310
|
end
|
316
311
|
|
317
312
|
it "sends environment when it's specified" do
|
@@ -325,6 +320,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
325
320
|
start_time: Time.new
|
326
321
|
)
|
327
322
|
)
|
323
|
+
subject.close
|
324
|
+
|
328
325
|
expect(
|
329
326
|
a_request(:put, routes).with(
|
330
327
|
body: /\A{"routes":\[.+\],"environment":"test"}\z/x
|
@@ -389,6 +386,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
389
386
|
start_time: Time.new(2018, 1, 1, 0, 49, 0, 0)
|
390
387
|
)
|
391
388
|
)
|
389
|
+
subject.close
|
390
|
+
|
392
391
|
expect(a_request(:put, routes)).not_to have_been_made
|
393
392
|
end
|
394
393
|
|
@@ -401,6 +400,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
401
400
|
start_time: Time.new(2018, 1, 1, 0, 49, 0, 0)
|
402
401
|
)
|
403
402
|
)
|
403
|
+
subject.close
|
404
|
+
|
404
405
|
expect(a_request(:put, queries)).not_to have_been_made
|
405
406
|
end
|
406
407
|
end
|
@@ -421,6 +422,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
421
422
|
start_time: Time.new(2018, 1, 1, 0, 49, 0, 0)
|
422
423
|
)
|
423
424
|
)
|
425
|
+
subject.close
|
426
|
+
|
424
427
|
expect(
|
425
428
|
a_request(:put, queries).with(
|
426
429
|
body: /\A{"queries":\[{"method":"POST","route":"\[Filtered\]"/
|
@@ -430,6 +433,37 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
430
433
|
end
|
431
434
|
end
|
432
435
|
|
436
|
+
describe "#close" do
|
437
|
+
before do
|
438
|
+
Airbrake::Config.instance.merge(performance_stats_flush_period: 0.1)
|
439
|
+
end
|
440
|
+
|
441
|
+
after do
|
442
|
+
Airbrake::Config.instance.merge(performance_stats_flush_period: 0)
|
443
|
+
end
|
444
|
+
|
445
|
+
it "kills the background thread" do
|
446
|
+
expect_any_instance_of(Thread).to receive(:kill).and_call_original
|
447
|
+
subject.notify(
|
448
|
+
Airbrake::Query.new(
|
449
|
+
method: 'POST',
|
450
|
+
route: '/foo',
|
451
|
+
query: 'SELECT * FROM things',
|
452
|
+
start_time: Time.new(2018, 1, 1, 0, 49, 0, 0)
|
453
|
+
)
|
454
|
+
)
|
455
|
+
subject.close
|
456
|
+
end
|
457
|
+
|
458
|
+
it "logs the exit message" do
|
459
|
+
allow(Airbrake::Loggable.instance).to receive(:debug)
|
460
|
+
expect(Airbrake::Loggable.instance).to receive(:debug).with(
|
461
|
+
/performance notifier closed/
|
462
|
+
)
|
463
|
+
subject.close
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
433
467
|
describe "#delete_filter" do
|
434
468
|
let(:filter) do
|
435
469
|
Class.new do
|
@@ -449,6 +483,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
449
483
|
start_time: Time.new(2018, 1, 1, 0, 49, 0, 0)
|
450
484
|
)
|
451
485
|
)
|
486
|
+
subject.close
|
487
|
+
|
452
488
|
expect(a_request(:put, routes)).to have_been_made
|
453
489
|
end
|
454
490
|
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
RSpec.describe Airbrake::ThreadPool do
|
2
|
+
let(:tasks) { [] }
|
3
|
+
let(:worker_size) { 1 }
|
4
|
+
let(:queue_size) { 2 }
|
5
|
+
|
6
|
+
subject do
|
7
|
+
described_class.new(
|
8
|
+
worker_size: worker_size,
|
9
|
+
queue_size: queue_size,
|
10
|
+
block: proc { |message| tasks << message }
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#<<" do
|
15
|
+
it "returns true" do
|
16
|
+
retval = subject << 1
|
17
|
+
subject.close
|
18
|
+
expect(retval).to eq(true)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "performs work in background" do
|
22
|
+
subject << 2
|
23
|
+
subject << 1
|
24
|
+
subject.close
|
25
|
+
|
26
|
+
expect(tasks).to eq([2, 1])
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when the queue is full" do
|
30
|
+
before do
|
31
|
+
allow(subject).to receive(:backlog).and_return(queue_size)
|
32
|
+
end
|
33
|
+
|
34
|
+
subject do
|
35
|
+
described_class.new(
|
36
|
+
worker_size: 1,
|
37
|
+
queue_size: 1,
|
38
|
+
block: proc { |message| tasks << message }
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns false" do
|
43
|
+
retval = subject << 1
|
44
|
+
subject.close
|
45
|
+
expect(retval).to eq(false)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "discards tasks" do
|
49
|
+
200.times { subject << 1 }
|
50
|
+
subject.close
|
51
|
+
|
52
|
+
expect(tasks.size).to be_zero
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#backlog" do
|
58
|
+
let(:worker_size) { 0 }
|
59
|
+
|
60
|
+
it "returns the size of the queue" do
|
61
|
+
subject << 1
|
62
|
+
expect(subject.backlog).to eq(1)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#has_workers?" do
|
67
|
+
it "returns false when the thread pool is not closed, but has 0 workers" do
|
68
|
+
subject.workers.list.each do |worker|
|
69
|
+
worker.kill.join
|
70
|
+
end
|
71
|
+
expect(subject).not_to have_workers
|
72
|
+
end
|
73
|
+
|
74
|
+
it "returns false when the thread pool is closed" do
|
75
|
+
subject.close
|
76
|
+
expect(subject).not_to have_workers
|
77
|
+
end
|
78
|
+
|
79
|
+
it "respawns workers on fork()", skip: %w[jruby].include?(RUBY_ENGINE) do
|
80
|
+
pid = fork { expect(subject).to have_workers }
|
81
|
+
Process.wait(pid)
|
82
|
+
subject.close
|
83
|
+
expect(subject).not_to have_workers
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#close" do
|
88
|
+
context "when there's no work to do" do
|
89
|
+
it "joins the spawned thread" do
|
90
|
+
workers = subject.workers.list
|
91
|
+
expect(workers).to all(be_alive)
|
92
|
+
|
93
|
+
subject.close
|
94
|
+
expect(workers).to all(be_stop)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "when there's some work to do" do
|
99
|
+
it "logs how many tasks are left to process" do
|
100
|
+
thread_pool = described_class.new(
|
101
|
+
worker_size: 0, queue_size: 2, block: proc {}
|
102
|
+
)
|
103
|
+
|
104
|
+
expect(Airbrake::Loggable.instance).to receive(:debug).with(
|
105
|
+
/waiting to process \d+ task\(s\)/
|
106
|
+
)
|
107
|
+
expect(Airbrake::Loggable.instance).to receive(:debug).with(/closed/)
|
108
|
+
|
109
|
+
2.times { thread_pool << 1 }
|
110
|
+
thread_pool.close
|
111
|
+
end
|
112
|
+
|
113
|
+
it "waits until the queue gets empty" do
|
114
|
+
thread_pool = described_class.new(
|
115
|
+
worker_size: 1, queue_size: 2, block: proc {}
|
116
|
+
)
|
117
|
+
|
118
|
+
10.times { subject << 1 }
|
119
|
+
thread_pool.close
|
120
|
+
expect(thread_pool.backlog).to be_zero
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "when it was already closed" do
|
125
|
+
it "doesn't increase the queue size" do
|
126
|
+
begin
|
127
|
+
subject.close
|
128
|
+
rescue Airbrake::Error
|
129
|
+
nil
|
130
|
+
end
|
131
|
+
|
132
|
+
expect(subject.backlog).to be_zero
|
133
|
+
end
|
134
|
+
|
135
|
+
it "raises error" do
|
136
|
+
subject.close
|
137
|
+
expect { subject.close }.to raise_error(
|
138
|
+
Airbrake::Error, 'this thread pool is closed already'
|
139
|
+
)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "#spawn_workers" do
|
145
|
+
it "spawns alive threads in an enclosed ThreadGroup" do
|
146
|
+
expect(subject.workers).to be_a(ThreadGroup)
|
147
|
+
expect(subject.workers.list).to all(be_alive)
|
148
|
+
expect(subject.workers).to be_enclosed
|
149
|
+
|
150
|
+
subject.close
|
151
|
+
end
|
152
|
+
|
153
|
+
it "spawns exactly `workers_size` workers" do
|
154
|
+
expect(subject.workers.list.size).to eq(worker_size)
|
155
|
+
subject.close
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: airbrake-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Airbrake Technologies, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-10-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rbtree3
|
@@ -80,6 +80,7 @@ files:
|
|
80
80
|
- lib/airbrake-ruby/stat.rb
|
81
81
|
- lib/airbrake-ruby/sync_sender.rb
|
82
82
|
- lib/airbrake-ruby/tdigest.rb
|
83
|
+
- lib/airbrake-ruby/thread_pool.rb
|
83
84
|
- lib/airbrake-ruby/time_truncate.rb
|
84
85
|
- lib/airbrake-ruby/timed_trace.rb
|
85
86
|
- lib/airbrake-ruby/truncator.rb
|
@@ -92,7 +93,7 @@ files:
|
|
92
93
|
- spec/config/validator_spec.rb
|
93
94
|
- spec/config_spec.rb
|
94
95
|
- spec/deploy_notifier_spec.rb
|
95
|
-
- spec/
|
96
|
+
- spec/file_cache_spec.rb
|
96
97
|
- spec/filter_chain_spec.rb
|
97
98
|
- spec/filters/context_filter_spec.rb
|
98
99
|
- spec/filters/dependency_filter_spec.rb
|
@@ -118,8 +119,8 @@ files:
|
|
118
119
|
- spec/inspectable_spec.rb
|
119
120
|
- spec/monotonic_time_spec.rb
|
120
121
|
- spec/nested_exception_spec.rb
|
122
|
+
- spec/notice_notifier/options_spec.rb
|
121
123
|
- spec/notice_notifier_spec.rb
|
122
|
-
- spec/notice_notifier_spec/options_spec.rb
|
123
124
|
- spec/notice_spec.rb
|
124
125
|
- spec/performance_breakdown_spec.rb
|
125
126
|
- spec/performance_notifier_spec.rb
|
@@ -132,6 +133,7 @@ files:
|
|
132
133
|
- spec/stat_spec.rb
|
133
134
|
- spec/sync_sender_spec.rb
|
134
135
|
- spec/tdigest_spec.rb
|
136
|
+
- spec/thread_pool_spec.rb
|
135
137
|
- spec/time_truncate_spec.rb
|
136
138
|
- spec/timed_trace_spec.rb
|
137
139
|
- spec/truncator_spec.rb
|
@@ -187,6 +189,7 @@ test_files:
|
|
187
189
|
- spec/notice_notifier_spec.rb
|
188
190
|
- spec/time_truncate_spec.rb
|
189
191
|
- spec/promise_spec.rb
|
192
|
+
- spec/thread_pool_spec.rb
|
190
193
|
- spec/config/validator_spec.rb
|
191
194
|
- spec/sync_sender_spec.rb
|
192
195
|
- spec/ignorable_spec.rb
|
@@ -195,10 +198,11 @@ test_files:
|
|
195
198
|
- spec/airbrake_spec.rb
|
196
199
|
- spec/nested_exception_spec.rb
|
197
200
|
- spec/timed_trace_spec.rb
|
201
|
+
- spec/file_cache_spec.rb
|
198
202
|
- spec/request_spec.rb
|
203
|
+
- spec/notice_notifier/options_spec.rb
|
199
204
|
- spec/filter_chain_spec.rb
|
200
205
|
- spec/response_spec.rb
|
201
|
-
- spec/file_cache.rb
|
202
206
|
- spec/code_hunk_spec.rb
|
203
207
|
- spec/fixtures/notroot.txt
|
204
208
|
- spec/fixtures/project_root/long_line.txt
|
@@ -210,4 +214,3 @@ test_files:
|
|
210
214
|
- spec/inspectable_spec.rb
|
211
215
|
- spec/stashable_spec.rb
|
212
216
|
- spec/query_spec.rb
|
213
|
-
- spec/notice_notifier_spec/options_spec.rb
|