airbrake-ruby 4.1.0 → 5.0.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 +5 -5
- data/lib/airbrake-ruby/async_sender.rb +22 -96
- data/lib/airbrake-ruby/backtrace.rb +8 -7
- data/lib/airbrake-ruby/benchmark.rb +39 -0
- data/lib/airbrake-ruby/code_hunk.rb +1 -1
- data/lib/airbrake-ruby/config/processor.rb +84 -0
- data/lib/airbrake-ruby/config/validator.rb +9 -3
- data/lib/airbrake-ruby/config.rb +76 -20
- data/lib/airbrake-ruby/deploy_notifier.rb +1 -1
- data/lib/airbrake-ruby/file_cache.rb +6 -0
- data/lib/airbrake-ruby/filter_chain.rb +16 -1
- data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +2 -2
- data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +5 -5
- data/lib/airbrake-ruby/filters/git_repository_filter.rb +3 -0
- data/lib/airbrake-ruby/filters/git_revision_filter.rb +2 -0
- data/lib/airbrake-ruby/filters/{keys_whitelist.rb → keys_allowlist.rb} +3 -3
- data/lib/airbrake-ruby/filters/{keys_blacklist.rb → keys_blocklist.rb} +3 -3
- data/lib/airbrake-ruby/filters/keys_filter.rb +39 -20
- data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/sql_filter.rb +30 -6
- data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/thread_filter.rb +4 -2
- data/lib/airbrake-ruby/grouppable.rb +12 -0
- data/lib/airbrake-ruby/ignorable.rb +1 -0
- data/lib/airbrake-ruby/inspectable.rb +2 -2
- data/lib/airbrake-ruby/loggable.rb +2 -2
- data/lib/airbrake-ruby/mergeable.rb +12 -0
- data/lib/airbrake-ruby/monotonic_time.rb +48 -0
- data/lib/airbrake-ruby/notice.rb +10 -20
- data/lib/airbrake-ruby/notice_notifier.rb +23 -42
- data/lib/airbrake-ruby/performance_breakdown.rb +52 -0
- data/lib/airbrake-ruby/performance_notifier.rb +126 -49
- data/lib/airbrake-ruby/promise.rb +1 -0
- data/lib/airbrake-ruby/query.rb +26 -11
- data/lib/airbrake-ruby/queue.rb +65 -0
- data/lib/airbrake-ruby/remote_settings/settings_data.rb +120 -0
- data/lib/airbrake-ruby/remote_settings.rb +145 -0
- data/lib/airbrake-ruby/request.rb +20 -6
- data/lib/airbrake-ruby/stashable.rb +15 -0
- data/lib/airbrake-ruby/stat.rb +34 -24
- data/lib/airbrake-ruby/sync_sender.rb +3 -2
- data/lib/airbrake-ruby/tdigest.rb +43 -58
- data/lib/airbrake-ruby/thread_pool.rb +138 -0
- data/lib/airbrake-ruby/timed_trace.rb +58 -0
- data/lib/airbrake-ruby/truncator.rb +10 -4
- data/lib/airbrake-ruby/version.rb +11 -1
- data/lib/airbrake-ruby.rb +219 -53
- data/spec/airbrake_spec.rb +428 -9
- data/spec/async_sender_spec.rb +26 -110
- data/spec/backtrace_spec.rb +44 -44
- data/spec/benchmark_spec.rb +33 -0
- data/spec/code_hunk_spec.rb +11 -11
- data/spec/config/processor_spec.rb +209 -0
- data/spec/config/validator_spec.rb +23 -6
- data/spec/config_spec.rb +77 -7
- data/spec/deploy_notifier_spec.rb +2 -2
- data/spec/{file_cache.rb → file_cache_spec.rb} +2 -4
- data/spec/filter_chain_spec.rb +28 -1
- data/spec/filters/dependency_filter_spec.rb +1 -1
- data/spec/filters/gem_root_filter_spec.rb +9 -9
- data/spec/filters/git_last_checkout_filter_spec.rb +21 -4
- data/spec/filters/git_repository_filter.rb +1 -1
- data/spec/filters/git_revision_filter_spec.rb +13 -11
- data/spec/filters/{keys_whitelist_spec.rb → keys_allowlist_spec.rb} +29 -28
- data/spec/filters/{keys_blacklist_spec.rb → keys_blocklist_spec.rb} +39 -29
- data/spec/filters/root_directory_filter_spec.rb +9 -9
- data/spec/filters/sql_filter_spec.rb +110 -55
- data/spec/filters/system_exit_filter_spec.rb +1 -1
- data/spec/filters/thread_filter_spec.rb +33 -31
- data/spec/fixtures/project_root/code.rb +9 -9
- data/spec/loggable_spec.rb +17 -0
- data/spec/monotonic_time_spec.rb +23 -0
- data/spec/{notice_notifier_spec → notice_notifier}/options_spec.rb +19 -21
- data/spec/notice_notifier_spec.rb +20 -80
- data/spec/notice_spec.rb +9 -11
- data/spec/performance_breakdown_spec.rb +11 -0
- data/spec/performance_notifier_spec.rb +360 -85
- data/spec/query_spec.rb +11 -0
- data/spec/queue_spec.rb +18 -0
- data/spec/remote_settings/settings_data_spec.rb +365 -0
- data/spec/remote_settings_spec.rb +230 -0
- data/spec/request_spec.rb +9 -0
- data/spec/response_spec.rb +8 -8
- data/spec/spec_helper.rb +9 -13
- data/spec/stashable_spec.rb +23 -0
- data/spec/stat_spec.rb +17 -15
- data/spec/sync_sender_spec.rb +14 -12
- data/spec/tdigest_spec.rb +6 -6
- data/spec/thread_pool_spec.rb +187 -0
- data/spec/timed_trace_spec.rb +125 -0
- data/spec/truncator_spec.rb +12 -12
- metadata +55 -18
@@ -1,16 +1,22 @@
|
|
1
1
|
RSpec.describe Airbrake::PerformanceNotifier do
|
2
2
|
let(:routes) { 'https://api.airbrake.io/api/v5/projects/1/routes-stats' }
|
3
3
|
let(:queries) { 'https://api.airbrake.io/api/v5/projects/1/queries-stats' }
|
4
|
+
let(:breakdowns) { 'https://api.airbrake.io/api/v5/projects/1/routes-breakdowns' }
|
5
|
+
let(:queues) { 'https://api.airbrake.io/api/v5/projects/1/queues-stats' }
|
4
6
|
|
5
7
|
before do
|
6
8
|
stub_request(:put, routes).to_return(status: 200, body: '')
|
7
9
|
stub_request(:put, queries).to_return(status: 200, body: '')
|
10
|
+
stub_request(:put, breakdowns).to_return(status: 200, body: '')
|
11
|
+
stub_request(:put, queues).to_return(status: 200, body: '')
|
8
12
|
|
9
13
|
Airbrake::Config.instance = Airbrake::Config.new(
|
10
14
|
project_id: 1,
|
11
15
|
project_key: 'banana',
|
12
16
|
performance_stats: true,
|
13
|
-
performance_stats_flush_period: 0
|
17
|
+
performance_stats_flush_period: 0,
|
18
|
+
query_stats: true,
|
19
|
+
job_stats: true,
|
14
20
|
)
|
15
21
|
end
|
16
22
|
|
@@ -24,10 +30,11 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
24
30
|
func: 'foo',
|
25
31
|
file: 'foo.rb',
|
26
32
|
line: 123,
|
27
|
-
|
28
|
-
|
29
|
-
)
|
33
|
+
timing: 60000,
|
34
|
+
time: Time.new(2018, 1, 1, 0, 49, 0, 0),
|
35
|
+
),
|
30
36
|
)
|
37
|
+
subject.close
|
31
38
|
|
32
39
|
expect(
|
33
40
|
a_request(:put, queries).with(body: %r|
|
@@ -43,7 +50,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
43
50
|
"sum":60000.0,
|
44
51
|
"sumsq":3600000000.0,
|
45
52
|
"tdigest":"AAAAAkA0AAAAAAAAAAAAAUdqYAAB"
|
46
|
-
}\]}\z|x)
|
53
|
+
}\]}\z|x),
|
47
54
|
).to have_been_made
|
48
55
|
end
|
49
56
|
|
@@ -53,10 +60,11 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
53
60
|
method: 'POST',
|
54
61
|
route: '/foo',
|
55
62
|
status_code: 200,
|
56
|
-
|
57
|
-
|
58
|
-
)
|
63
|
+
timing: 60000,
|
64
|
+
time: Time.new(2018, 1, 1, 0, 49, 0, 0),
|
65
|
+
),
|
59
66
|
)
|
67
|
+
subject.close
|
60
68
|
|
61
69
|
expect(
|
62
70
|
a_request(:put, routes).with(body: %r|
|
@@ -69,7 +77,89 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
69
77
|
"sum":60000.0,
|
70
78
|
"sumsq":3600000000.0,
|
71
79
|
"tdigest":"AAAAAkA0AAAAAAAAAAAAAUdqYAAB"
|
72
|
-
}\]}\z|x)
|
80
|
+
}\]}\z|x),
|
81
|
+
).to have_been_made
|
82
|
+
end
|
83
|
+
|
84
|
+
it "sends full performance breakdown" do
|
85
|
+
subject.notify(
|
86
|
+
Airbrake::PerformanceBreakdown.new(
|
87
|
+
method: 'DELETE',
|
88
|
+
route: '/routes-breakdowns',
|
89
|
+
response_type: 'json',
|
90
|
+
timing: 60000,
|
91
|
+
time: Time.new(2018, 1, 1, 0, 49, 0, 0),
|
92
|
+
groups: { db: 131, view: 421 },
|
93
|
+
),
|
94
|
+
)
|
95
|
+
subject.close
|
96
|
+
|
97
|
+
expect(
|
98
|
+
a_request(:put, breakdowns).with(body: %r|
|
99
|
+
\A{"routes":\[{
|
100
|
+
"method":"DELETE",
|
101
|
+
"route":"/routes-breakdowns",
|
102
|
+
"responseType":"json",
|
103
|
+
"time":"2018-01-01T00:49:00\+00:00",
|
104
|
+
"count":1,
|
105
|
+
"sum":60000.0,
|
106
|
+
"sumsq":3600000000.0,
|
107
|
+
"tdigest":"AAAAAkA0AAAAAAAAAAAAAUdqYAAB",
|
108
|
+
"groups":{
|
109
|
+
"db":{
|
110
|
+
"count":1,
|
111
|
+
"sum":131.0,
|
112
|
+
"sumsq":17161.0,
|
113
|
+
"tdigest":"AAAAAkA0AAAAAAAAAAAAAUMDAAAB"
|
114
|
+
},
|
115
|
+
"view":{
|
116
|
+
"count":1,
|
117
|
+
"sum":421.0,
|
118
|
+
"sumsq":177241.0,
|
119
|
+
"tdigest":"AAAAAkA0AAAAAAAAAAAAAUPSgAAB"
|
120
|
+
}
|
121
|
+
}
|
122
|
+
}\]}\z|x),
|
123
|
+
).to have_been_made
|
124
|
+
end
|
125
|
+
|
126
|
+
it "sends full queue" do
|
127
|
+
subject.notify(
|
128
|
+
Airbrake::Queue.new(
|
129
|
+
queue: 'emails',
|
130
|
+
error_count: 2,
|
131
|
+
groups: { redis: 131, sql: 421 },
|
132
|
+
timing: 60000,
|
133
|
+
time: Time.new(2018, 1, 1, 0, 49, 0, 0),
|
134
|
+
),
|
135
|
+
)
|
136
|
+
subject.close
|
137
|
+
|
138
|
+
expect(
|
139
|
+
a_request(:put, queues).with(body: /
|
140
|
+
\A{"queues":\[{
|
141
|
+
"queue":"emails",
|
142
|
+
"errorCount":2,
|
143
|
+
"time":"2018-01-01T00:49:00\+00:00",
|
144
|
+
"count":1,
|
145
|
+
"sum":60000.0,
|
146
|
+
"sumsq":3600000000.0,
|
147
|
+
"tdigest":"AAAAAkA0AAAAAAAAAAAAAUdqYAAB",
|
148
|
+
"groups":{
|
149
|
+
"redis":{
|
150
|
+
"count":1,
|
151
|
+
"sum":131.0,
|
152
|
+
"sumsq":17161.0,
|
153
|
+
"tdigest":"AAAAAkA0AAAAAAAAAAAAAUMDAAAB"
|
154
|
+
},
|
155
|
+
"sql":{
|
156
|
+
"count":1,
|
157
|
+
"sum":421.0,
|
158
|
+
"sumsq":177241.0,
|
159
|
+
"tdigest":"AAAAAkA0AAAAAAAAAAAAAUPSgAAB"
|
160
|
+
}
|
161
|
+
}
|
162
|
+
}\]}\z/x),
|
73
163
|
).to have_been_made
|
74
164
|
end
|
75
165
|
|
@@ -79,11 +169,14 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
79
169
|
method: 'GET',
|
80
170
|
route: '/foo',
|
81
171
|
status_code: 200,
|
82
|
-
|
83
|
-
|
172
|
+
timing: 60000,
|
173
|
+
time: Time.new(2018, 1, 1, 0, 0, 20, 0),
|
174
|
+
),
|
84
175
|
)
|
176
|
+
subject.close
|
177
|
+
|
85
178
|
expect(
|
86
|
-
a_request(:put, routes).with(body: /"time":"2018-01-01T00:00:00\+00:00"/)
|
179
|
+
a_request(:put, routes).with(body: /"time":"2018-01-01T00:00:00\+00:00"/),
|
87
180
|
).to have_been_made
|
88
181
|
end
|
89
182
|
|
@@ -93,19 +186,21 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
93
186
|
method: 'GET',
|
94
187
|
route: '/foo',
|
95
188
|
status_code: 200,
|
96
|
-
|
97
|
-
)
|
189
|
+
timing: 213,
|
190
|
+
),
|
98
191
|
)
|
99
192
|
subject.notify(
|
100
193
|
Airbrake::Request.new(
|
101
194
|
method: 'GET',
|
102
195
|
route: '/foo',
|
103
196
|
status_code: 200,
|
104
|
-
|
105
|
-
)
|
197
|
+
timing: 123,
|
198
|
+
),
|
106
199
|
)
|
200
|
+
subject.close
|
201
|
+
|
107
202
|
expect(
|
108
|
-
a_request(:put, routes).with(body: /"count":2/)
|
203
|
+
a_request(:put, routes).with(body: /"count":2/),
|
109
204
|
).to have_been_made
|
110
205
|
end
|
111
206
|
|
@@ -115,19 +210,21 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
115
210
|
method: 'GET',
|
116
211
|
route: '/foo',
|
117
212
|
status_code: 200,
|
118
|
-
|
119
|
-
|
120
|
-
)
|
213
|
+
timing: 1000,
|
214
|
+
time: Time.new(2018, 1, 1, 0, 0, 49, 0),
|
215
|
+
),
|
121
216
|
)
|
122
217
|
subject.notify(
|
123
218
|
Airbrake::Request.new(
|
124
219
|
method: 'GET',
|
125
220
|
route: '/foo',
|
126
221
|
status_code: 200,
|
127
|
-
|
128
|
-
|
129
|
-
)
|
222
|
+
timing: 6000,
|
223
|
+
time: Time.new(2018, 1, 1, 0, 1, 49, 0),
|
224
|
+
),
|
130
225
|
)
|
226
|
+
subject.close
|
227
|
+
|
131
228
|
expect(
|
132
229
|
a_request(:put, routes).with(
|
133
230
|
body: %r|\A
|
@@ -138,8 +235,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
138
235
|
{"method":"GET","route":"/foo","statusCode":200,
|
139
236
|
"time":"2018-01-01T00:01:00\+00:00","count":1,"sum":6000.0,
|
140
237
|
"sumsq":36000000.0,"tdigest":"AAAAAkA0AAAAAAAAAAAAAUW7gAAB"}\]}
|
141
|
-
\z|x
|
142
|
-
)
|
238
|
+
\z|x,
|
239
|
+
),
|
143
240
|
).to have_been_made
|
144
241
|
end
|
145
242
|
|
@@ -149,19 +246,21 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
149
246
|
method: 'GET',
|
150
247
|
route: '/foo',
|
151
248
|
status_code: 200,
|
152
|
-
|
153
|
-
|
154
|
-
)
|
249
|
+
timing: 60000,
|
250
|
+
time: Time.new(2018, 1, 1, 0, 49, 0, 0),
|
251
|
+
),
|
155
252
|
)
|
156
253
|
subject.notify(
|
157
254
|
Airbrake::Request.new(
|
158
255
|
method: 'POST',
|
159
256
|
route: '/foo',
|
160
257
|
status_code: 200,
|
161
|
-
|
162
|
-
|
163
|
-
)
|
258
|
+
timing: 60000,
|
259
|
+
time: Time.new(2018, 1, 1, 0, 49, 0, 0),
|
260
|
+
),
|
164
261
|
)
|
262
|
+
subject.close
|
263
|
+
|
165
264
|
expect(
|
166
265
|
a_request(:put, routes).with(
|
167
266
|
body: %r|\A
|
@@ -172,52 +271,135 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
172
271
|
{"method":"POST","route":"/foo","statusCode":200,
|
173
272
|
"time":"2018-01-01T00:49:00\+00:00","count":1,"sum":60000.0,
|
174
273
|
"sumsq":3600000000.0,"tdigest":"AAAAAkA0AAAAAAAAAAAAAUdqYAAB"}\]}
|
175
|
-
\z|x
|
176
|
-
)
|
274
|
+
\z|x,
|
275
|
+
),
|
177
276
|
).to have_been_made
|
178
277
|
end
|
179
278
|
|
180
|
-
it "
|
181
|
-
|
182
|
-
Airbrake::
|
183
|
-
method: '
|
184
|
-
route: '/
|
185
|
-
|
186
|
-
|
187
|
-
|
279
|
+
it "groups performance breakdowns by route key" do
|
280
|
+
subject.notify(
|
281
|
+
Airbrake::PerformanceBreakdown.new(
|
282
|
+
method: 'DELETE',
|
283
|
+
route: '/routes-breakdowns',
|
284
|
+
response_type: 'json',
|
285
|
+
timing: 2000,
|
286
|
+
time: Time.new(2018, 1, 1, 0, 0, 20, 0),
|
287
|
+
groups: { db: 131, view: 421 },
|
288
|
+
),
|
188
289
|
)
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
method: 'GET', route: '/foo', status_code: 200, start_time: Time.new
|
199
|
-
)
|
290
|
+
subject.notify(
|
291
|
+
Airbrake::PerformanceBreakdown.new(
|
292
|
+
method: 'DELETE',
|
293
|
+
route: '/routes-breakdowns',
|
294
|
+
response_type: 'json',
|
295
|
+
timing: 2000,
|
296
|
+
time: Time.new(2018, 1, 1, 0, 0, 30, 0),
|
297
|
+
groups: { db: 55, view: 11 },
|
298
|
+
),
|
200
299
|
)
|
300
|
+
subject.close
|
201
301
|
|
202
|
-
expect(
|
203
|
-
|
204
|
-
|
205
|
-
|
302
|
+
expect(
|
303
|
+
a_request(:put, breakdowns).with(body: %r|
|
304
|
+
\A{"routes":\[{
|
305
|
+
"method":"DELETE",
|
306
|
+
"route":"/routes-breakdowns",
|
307
|
+
"responseType":"json",
|
308
|
+
"time":"2018-01-01T00:00:00\+00:00",
|
309
|
+
"count":2,
|
310
|
+
"sum":4000.0,
|
311
|
+
"sumsq":8000000.0,
|
312
|
+
"tdigest":"AAAAAkA0AAAAAAAAAAAAAUT6AAAC",
|
313
|
+
"groups":{
|
314
|
+
"db":{
|
315
|
+
"count":2,
|
316
|
+
"sum":186.0,
|
317
|
+
"sumsq":20186.0,
|
318
|
+
"tdigest":"AAAAAkA0AAAAAAAAAAAAAkJcAABCmAAAAQE="
|
319
|
+
},
|
320
|
+
"view":{
|
321
|
+
"count":2,
|
322
|
+
"sum":432.0,
|
323
|
+
"sumsq":177362.0,
|
324
|
+
"tdigest":"AAAAAkA0AAAAAAAAAAAAAkEwAABDzQAAAQE="
|
325
|
+
}
|
326
|
+
}
|
327
|
+
}\]}\z|x),
|
328
|
+
).to have_been_made
|
206
329
|
end
|
207
330
|
|
208
|
-
it "
|
209
|
-
|
210
|
-
|
331
|
+
it "groups queues by queue key" do
|
332
|
+
subject.notify(
|
333
|
+
Airbrake::Queue.new(
|
334
|
+
queue: 'emails',
|
335
|
+
error_count: 2,
|
336
|
+
groups: { redis: 131, sql: 421 },
|
337
|
+
timing: 60000,
|
338
|
+
time: Time.new(2018, 1, 1, 0, 49, 0, 0),
|
339
|
+
),
|
340
|
+
)
|
341
|
+
subject.notify(
|
342
|
+
Airbrake::Queue.new(
|
343
|
+
queue: 'emails',
|
344
|
+
error_count: 3,
|
345
|
+
groups: { redis: 131, sql: 421 },
|
346
|
+
timing: 60000,
|
347
|
+
time: Time.new(2018, 1, 1, 0, 49, 0, 0),
|
348
|
+
),
|
211
349
|
)
|
350
|
+
subject.close
|
212
351
|
|
352
|
+
expect(
|
353
|
+
a_request(:put, queues).with(body: /
|
354
|
+
\A{"queues":\[{
|
355
|
+
"queue":"emails",
|
356
|
+
"errorCount":5,
|
357
|
+
"time":"2018-01-01T00:49:00\+00:00",
|
358
|
+
"count":2,
|
359
|
+
"sum":120000.0,
|
360
|
+
"sumsq":7200000000.0,
|
361
|
+
"tdigest":"AAAAAkA0AAAAAAAAAAAAAUdqYAAC",
|
362
|
+
"groups":{
|
363
|
+
"redis":{
|
364
|
+
"count":2,
|
365
|
+
"sum":262.0,
|
366
|
+
"sumsq":34322.0,
|
367
|
+
"tdigest":"AAAAAkA0AAAAAAAAAAAAAUMDAAAC"
|
368
|
+
},
|
369
|
+
"sql":{
|
370
|
+
"count":2,
|
371
|
+
"sum":842.0,
|
372
|
+
"sumsq":354482.0,
|
373
|
+
"tdigest":"AAAAAkA0AAAAAAAAAAAAAUPSgAAC"
|
374
|
+
}
|
375
|
+
}
|
376
|
+
}\]}\z/x),
|
377
|
+
).to have_been_made
|
378
|
+
end
|
379
|
+
|
380
|
+
it "returns a promise" do
|
213
381
|
promise = subject.notify(
|
214
382
|
Airbrake::Request.new(
|
215
|
-
method: 'GET',
|
216
|
-
|
383
|
+
method: 'GET',
|
384
|
+
route: '/foo',
|
385
|
+
status_code: 200,
|
386
|
+
timing: 123,
|
387
|
+
),
|
217
388
|
)
|
389
|
+
subject.close
|
390
|
+
|
391
|
+
expect(promise).to be_an(Airbrake::Promise)
|
392
|
+
expect(promise.value).to eq('' => '')
|
393
|
+
end
|
218
394
|
|
219
|
-
|
220
|
-
|
395
|
+
it "checks performance stat configuration" do
|
396
|
+
request = Airbrake::Request.new(
|
397
|
+
method: 'GET', route: '/foo', status_code: 200, timing: 123,
|
398
|
+
)
|
399
|
+
expect(Airbrake::Config.instance).to receive(:check_performance_options)
|
400
|
+
.with(request).and_return(Airbrake::Promise.new)
|
401
|
+
subject.notify(request)
|
402
|
+
subject.close
|
221
403
|
end
|
222
404
|
|
223
405
|
it "sends environment when it's specified" do
|
@@ -228,13 +410,15 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
228
410
|
method: 'POST',
|
229
411
|
route: '/foo',
|
230
412
|
status_code: 200,
|
231
|
-
|
232
|
-
)
|
413
|
+
timing: 123,
|
414
|
+
),
|
233
415
|
)
|
416
|
+
subject.close
|
417
|
+
|
234
418
|
expect(
|
235
419
|
a_request(:put, routes).with(
|
236
|
-
body: /\A{"routes":\[.+\],"environment":"test"}\z/x
|
237
|
-
)
|
420
|
+
body: /\A{"routes":\[.+\],"environment":"test"}\z/x,
|
421
|
+
),
|
238
422
|
).to have_been_made
|
239
423
|
end
|
240
424
|
|
@@ -255,7 +439,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
255
439
|
project_id: 1,
|
256
440
|
project_key: 'banana',
|
257
441
|
performance_stats: true,
|
258
|
-
performance_stats_flush_period: flush_period
|
442
|
+
performance_stats_flush_period: flush_period,
|
259
443
|
)
|
260
444
|
|
261
445
|
subject.notify(
|
@@ -263,8 +447,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
263
447
|
method: 'GET',
|
264
448
|
route: '/foo',
|
265
449
|
status_code: 200,
|
266
|
-
|
267
|
-
)
|
450
|
+
timing: 123,
|
451
|
+
),
|
268
452
|
)
|
269
453
|
|
270
454
|
subject.notify(
|
@@ -272,8 +456,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
272
456
|
method: 'POST',
|
273
457
|
route: '/foo',
|
274
458
|
query: 'SELECT * FROM things',
|
275
|
-
|
276
|
-
)
|
459
|
+
timing: 123,
|
460
|
+
),
|
277
461
|
)
|
278
462
|
|
279
463
|
sleep(flush_period + 0.5)
|
@@ -292,9 +476,11 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
292
476
|
method: 'GET',
|
293
477
|
route: '/foo',
|
294
478
|
status_code: 200,
|
295
|
-
|
296
|
-
)
|
479
|
+
timing: 1,
|
480
|
+
),
|
297
481
|
)
|
482
|
+
subject.close
|
483
|
+
|
298
484
|
expect(a_request(:put, routes)).not_to have_been_made
|
299
485
|
end
|
300
486
|
|
@@ -304,11 +490,29 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
304
490
|
method: 'POST',
|
305
491
|
route: '/foo',
|
306
492
|
query: 'SELECT * FROM things',
|
307
|
-
|
308
|
-
)
|
493
|
+
timing: 1,
|
494
|
+
),
|
309
495
|
)
|
496
|
+
subject.close
|
497
|
+
|
310
498
|
expect(a_request(:put, queries)).not_to have_been_made
|
311
499
|
end
|
500
|
+
|
501
|
+
it "returns a rejected promise" do
|
502
|
+
promise = subject.notify(
|
503
|
+
Airbrake::Query.new(
|
504
|
+
method: 'POST',
|
505
|
+
route: '/foo',
|
506
|
+
query: 'SELECT * FROM things',
|
507
|
+
timing: 1,
|
508
|
+
),
|
509
|
+
)
|
510
|
+
subject.close
|
511
|
+
|
512
|
+
expect(promise.value).to eq(
|
513
|
+
'error' => 'Airbrake::Query was ignored by a filter',
|
514
|
+
)
|
515
|
+
end
|
312
516
|
end
|
313
517
|
|
314
518
|
context "when a filter that modifies payload was defined" do
|
@@ -324,24 +528,93 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
324
528
|
method: 'POST',
|
325
529
|
route: '/foo',
|
326
530
|
query: 'SELECT * FROM things',
|
327
|
-
|
328
|
-
)
|
531
|
+
timing: 123,
|
532
|
+
),
|
329
533
|
)
|
534
|
+
subject.close
|
535
|
+
|
330
536
|
expect(
|
331
537
|
a_request(:put, queries).with(
|
332
|
-
body: /\A{"queries":\[{"method":"POST","route":"\[Filtered\]"
|
333
|
-
)
|
538
|
+
body: /\A{"queries":\[{"method":"POST","route":"\[Filtered\]"/,
|
539
|
+
),
|
334
540
|
).to have_been_made
|
335
541
|
end
|
336
542
|
end
|
543
|
+
|
544
|
+
context "when provided :timing is zero" do
|
545
|
+
it "doesn't notify" do
|
546
|
+
queue = Airbrake::Queue.new(queue: 'bananas', error_count: 0, timing: 0)
|
547
|
+
subject.notify(queue)
|
548
|
+
subject.close
|
549
|
+
|
550
|
+
expect(a_request(:put, queues)).not_to have_been_made
|
551
|
+
end
|
552
|
+
|
553
|
+
it "returns a rejected promise" do
|
554
|
+
queue = Airbrake::Queue.new(queue: 'bananas', error_count: 0, timing: 0)
|
555
|
+
promise = subject.notify(queue)
|
556
|
+
subject.close
|
557
|
+
|
558
|
+
expect(promise.value).to eq('error' => ':timing cannot be zero')
|
559
|
+
end
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
describe "#notify_sync" do
|
564
|
+
it "notifies synchronously" do
|
565
|
+
retval = subject.notify_sync(
|
566
|
+
Airbrake::Query.new(
|
567
|
+
method: 'POST',
|
568
|
+
route: '/foo',
|
569
|
+
query: 'SELECT * FROM things',
|
570
|
+
timing: 123,
|
571
|
+
),
|
572
|
+
)
|
573
|
+
|
574
|
+
expect(
|
575
|
+
a_request(:put, queries).with(
|
576
|
+
body: %r|\A{"queries":\[{"method":"POST","route":"/foo"|,
|
577
|
+
),
|
578
|
+
).to have_been_made
|
579
|
+
expect(retval).to eq('' => '')
|
580
|
+
end
|
581
|
+
end
|
582
|
+
|
583
|
+
describe "#close" do
|
584
|
+
before do
|
585
|
+
Airbrake::Config.instance.merge(performance_stats_flush_period: 0.1)
|
586
|
+
end
|
587
|
+
|
588
|
+
after do
|
589
|
+
Airbrake::Config.instance.merge(performance_stats_flush_period: 0)
|
590
|
+
end
|
591
|
+
|
592
|
+
it "kills the background thread" do
|
593
|
+
expect_any_instance_of(Thread).to receive(:kill).and_call_original
|
594
|
+
subject.notify(
|
595
|
+
Airbrake::Query.new(
|
596
|
+
method: 'POST',
|
597
|
+
route: '/foo',
|
598
|
+
query: 'SELECT * FROM things',
|
599
|
+
timing: 123,
|
600
|
+
),
|
601
|
+
)
|
602
|
+
subject.close
|
603
|
+
end
|
604
|
+
|
605
|
+
it "logs the exit message" do
|
606
|
+
allow(Airbrake::Loggable.instance).to receive(:debug)
|
607
|
+
expect(Airbrake::Loggable.instance).to receive(:debug).with(
|
608
|
+
/performance notifier closed/,
|
609
|
+
)
|
610
|
+
subject.close
|
611
|
+
end
|
337
612
|
end
|
338
613
|
|
339
614
|
describe "#delete_filter" do
|
340
615
|
let(:filter) do
|
341
616
|
Class.new do
|
342
|
-
def call(resource)
|
343
|
-
resource.ignore!
|
344
|
-
end
|
617
|
+
def call(resource); end
|
345
618
|
end
|
346
619
|
end
|
347
620
|
|
@@ -354,9 +627,11 @@ RSpec.describe Airbrake::PerformanceNotifier do
|
|
354
627
|
method: 'POST',
|
355
628
|
route: '/foo',
|
356
629
|
status_code: 200,
|
357
|
-
|
358
|
-
)
|
630
|
+
timing: 123,
|
631
|
+
),
|
359
632
|
)
|
633
|
+
subject.close
|
634
|
+
|
360
635
|
expect(a_request(:put, routes)).to have_been_made
|
361
636
|
end
|
362
637
|
end
|
data/spec/query_spec.rb
ADDED
data/spec/queue_spec.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
RSpec.describe Airbrake::Queue do
|
2
|
+
subject { described_class.new(queue: 'bananas', error_count: 0) }
|
3
|
+
|
4
|
+
describe "#ignore" do
|
5
|
+
it { is_expected.to respond_to(:ignore!) }
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#stash" do
|
9
|
+
it { is_expected.to respond_to(:stash) }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#route" do
|
13
|
+
it "always returns an empty route" do
|
14
|
+
queue = described_class.new(queue: 'a', error_count: 0)
|
15
|
+
expect(queue.route).to be_empty
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|