airbrake-ruby 4.8.0 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/airbrake-ruby.rb +132 -57
- data/lib/airbrake-ruby/async_sender.rb +7 -30
- data/lib/airbrake-ruby/backtrace.rb +8 -7
- data/lib/airbrake-ruby/benchmark.rb +1 -1
- data/lib/airbrake-ruby/code_hunk.rb +1 -1
- data/lib/airbrake-ruby/config.rb +59 -15
- data/lib/airbrake-ruby/config/processor.rb +71 -0
- data/lib/airbrake-ruby/config/validator.rb +9 -3
- data/lib/airbrake-ruby/deploy_notifier.rb +1 -1
- data/lib/airbrake-ruby/file_cache.rb +1 -1
- 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 +7 -7
- data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/thread_filter.rb +5 -4
- 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 +1 -1
- data/lib/airbrake-ruby/mergeable.rb +12 -0
- data/lib/airbrake-ruby/monotonic_time.rb +5 -0
- data/lib/airbrake-ruby/notice.rb +7 -14
- data/lib/airbrake-ruby/notice_notifier.rb +11 -3
- data/lib/airbrake-ruby/performance_breakdown.rb +16 -10
- data/lib/airbrake-ruby/performance_notifier.rb +80 -58
- data/lib/airbrake-ruby/promise.rb +1 -0
- data/lib/airbrake-ruby/query.rb +20 -15
- data/lib/airbrake-ruby/queue.rb +65 -0
- data/lib/airbrake-ruby/remote_settings.rb +105 -0
- data/lib/airbrake-ruby/remote_settings/callback.rb +44 -0
- data/lib/airbrake-ruby/remote_settings/settings_data.rb +116 -0
- data/lib/airbrake-ruby/request.rb +14 -12
- data/lib/airbrake-ruby/stat.rb +26 -33
- data/lib/airbrake-ruby/sync_sender.rb +3 -2
- data/lib/airbrake-ruby/tdigest.rb +43 -58
- data/lib/airbrake-ruby/thread_pool.rb +11 -1
- data/lib/airbrake-ruby/truncator.rb +10 -4
- data/lib/airbrake-ruby/version.rb +11 -1
- data/spec/airbrake_spec.rb +206 -71
- data/spec/async_sender_spec.rb +3 -12
- data/spec/backtrace_spec.rb +44 -44
- data/spec/code_hunk_spec.rb +11 -11
- data/spec/config/processor_spec.rb +143 -0
- data/spec/config/validator_spec.rb +23 -6
- data/spec/config_spec.rb +40 -14
- data/spec/deploy_notifier_spec.rb +2 -2
- 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 +10 -10
- 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 +58 -60
- data/spec/filters/system_exit_filter_spec.rb +1 -1
- data/spec/filters/thread_filter_spec.rb +32 -30
- data/spec/fixtures/project_root/code.rb +9 -9
- data/spec/loggable_spec.rb +17 -0
- data/spec/monotonic_time_spec.rb +11 -0
- data/spec/notice_notifier/options_spec.rb +17 -17
- data/spec/notice_notifier_spec.rb +20 -20
- data/spec/notice_spec.rb +6 -6
- data/spec/performance_breakdown_spec.rb +0 -1
- data/spec/performance_notifier_spec.rb +220 -73
- data/spec/query_spec.rb +1 -1
- data/spec/queue_spec.rb +18 -0
- data/spec/remote_settings/callback_spec.rb +143 -0
- data/spec/remote_settings/settings_data_spec.rb +348 -0
- data/spec/remote_settings_spec.rb +187 -0
- data/spec/request_spec.rb +1 -3
- data/spec/response_spec.rb +8 -8
- data/spec/spec_helper.rb +6 -6
- data/spec/stat_spec.rb +2 -12
- data/spec/sync_sender_spec.rb +14 -12
- data/spec/tdigest_spec.rb +7 -7
- data/spec/thread_pool_spec.rb +39 -10
- data/spec/timed_trace_spec.rb +1 -1
- data/spec/truncator_spec.rb +12 -12
- metadata +32 -14
@@ -45,7 +45,15 @@ module Airbrake
|
|
45
45
|
# @return [Boolean] true if the message was successfully sent to the pool,
|
46
46
|
# false if the queue is full
|
47
47
|
def <<(message)
|
48
|
-
|
48
|
+
if backlog >= @queue_size
|
49
|
+
logger.error(
|
50
|
+
"#{LOG_LABEL} ThreadPool has reached its capacity of " \
|
51
|
+
"#{@queue_size} and the following message will not be " \
|
52
|
+
"processed: #{message.inspect}",
|
53
|
+
)
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
|
49
57
|
@queue << message
|
50
58
|
true
|
51
59
|
end
|
@@ -75,6 +83,7 @@ module Airbrake
|
|
75
83
|
|
76
84
|
if @pid != Process.pid && @workers.list.empty?
|
77
85
|
@pid = Process.pid
|
86
|
+
@workers = ThreadGroup.new
|
78
87
|
spawn_workers
|
79
88
|
end
|
80
89
|
|
@@ -120,6 +129,7 @@ module Airbrake
|
|
120
129
|
Thread.new do
|
121
130
|
while (message = @queue.pop)
|
122
131
|
break if message == :stop
|
132
|
+
|
123
133
|
@block.call(message)
|
124
134
|
end
|
125
135
|
end
|
@@ -12,6 +12,10 @@ module Airbrake
|
|
12
12
|
# strings with +ENCODING_OPTIONS+
|
13
13
|
TEMP_ENCODING = 'utf-16'.freeze
|
14
14
|
|
15
|
+
# @return [Array<Encoding>] encodings that are eligible for fixing invalid
|
16
|
+
# characters
|
17
|
+
SUPPORTED_ENCODINGS = [Encoding::UTF_8, Encoding::ASCII].freeze
|
18
|
+
|
15
19
|
# @return [String] what to append when something is a circular reference
|
16
20
|
CIRCULAR = '[Circular]'.freeze
|
17
21
|
|
@@ -35,6 +39,7 @@ module Airbrake
|
|
35
39
|
def truncate(object, seen = Set.new)
|
36
40
|
if seen.include?(object.object_id)
|
37
41
|
return CIRCULAR if CIRCULAR_TYPES.any? { |t| object.is_a?(t) }
|
42
|
+
|
38
43
|
return object
|
39
44
|
end
|
40
45
|
truncate_object(object, seen << object.object_id)
|
@@ -63,6 +68,7 @@ module Airbrake
|
|
63
68
|
def truncate_string(str)
|
64
69
|
fixed_str = replace_invalid_characters(str)
|
65
70
|
return fixed_str if fixed_str.length <= @max_size
|
71
|
+
|
66
72
|
(fixed_str.slice(0, @max_size) + TRUNCATED).freeze
|
67
73
|
end
|
68
74
|
|
@@ -76,6 +82,7 @@ module Airbrake
|
|
76
82
|
truncated_hash = {}
|
77
83
|
hash.each_with_index do |(key, val), idx|
|
78
84
|
break if idx + 1 > @max_size
|
85
|
+
|
79
86
|
truncated_hash[key] = truncate(val, seen)
|
80
87
|
end
|
81
88
|
|
@@ -103,13 +110,12 @@ module Airbrake
|
|
103
110
|
# @return [String] a UTF-8 encoded string
|
104
111
|
# @see https://github.com/flori/json/commit/3e158410e81f94dbbc3da6b7b35f4f64983aa4e3
|
105
112
|
def replace_invalid_characters(str)
|
106
|
-
|
107
|
-
utf8_string = (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII)
|
113
|
+
utf8_string = SUPPORTED_ENCODINGS.include?(str.encoding)
|
108
114
|
return str if utf8_string && str.valid_encoding?
|
109
115
|
|
110
116
|
temp_str = str.dup
|
111
|
-
temp_str.encode!(TEMP_ENCODING, ENCODING_OPTIONS) if utf8_string
|
112
|
-
temp_str.encode!('utf-8', ENCODING_OPTIONS)
|
117
|
+
temp_str.encode!(TEMP_ENCODING, **ENCODING_OPTIONS) if utf8_string
|
118
|
+
temp_str.encode!('utf-8', **ENCODING_OPTIONS)
|
113
119
|
end
|
114
120
|
end
|
115
121
|
end
|
@@ -2,5 +2,15 @@
|
|
2
2
|
# More information: http://semver.org/
|
3
3
|
module Airbrake
|
4
4
|
# @return [String] the library version
|
5
|
-
|
5
|
+
# @api public
|
6
|
+
AIRBRAKE_RUBY_VERSION = '5.2.0'.freeze
|
7
|
+
|
8
|
+
# @return [Hash{Symbol=>String}] the information about the notifier library
|
9
|
+
# @since v5.0.0
|
10
|
+
# @api public
|
11
|
+
NOTIFIER_INFO = {
|
12
|
+
name: 'airbrake-ruby'.freeze,
|
13
|
+
version: Airbrake::AIRBRAKE_RUBY_VERSION,
|
14
|
+
url: 'https://github.com/airbrake/airbrake-ruby'.freeze,
|
15
|
+
}.freeze
|
6
16
|
end
|
data/spec/airbrake_spec.rb
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
RSpec.describe Airbrake do
|
2
|
+
let(:remote_settings) { instance_double(Airbrake::RemoteSettings) }
|
3
|
+
|
4
|
+
before do
|
5
|
+
allow(Airbrake::RemoteSettings).to receive(:poll).and_return(remote_settings)
|
6
|
+
allow(remote_settings).to receive(:stop_polling)
|
7
|
+
end
|
8
|
+
|
9
|
+
after { described_class.instance_variable_set(:@remote_settings, nil) }
|
10
|
+
|
2
11
|
it "gets initialized with a performance notifier" do
|
3
12
|
expect(described_class.performance_notifier).not_to be_nil
|
4
13
|
end
|
@@ -51,28 +60,6 @@ RSpec.describe Airbrake do
|
|
51
60
|
expect(described_class).to be_configured
|
52
61
|
end
|
53
62
|
|
54
|
-
context "when a notifier was configured" do
|
55
|
-
before do
|
56
|
-
expect(described_class).to receive(:configured?).and_return(true)
|
57
|
-
end
|
58
|
-
|
59
|
-
it "closes previously configured notice notifier" do
|
60
|
-
expect(described_class).to receive(:close)
|
61
|
-
described_class.configure {}
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
context "when a notifier wasn't configured" do
|
66
|
-
before do
|
67
|
-
expect(described_class).to receive(:configured?).and_return(false)
|
68
|
-
end
|
69
|
-
|
70
|
-
it "doesn't close previously configured notice notifier" do
|
71
|
-
expect(described_class).not_to receive(:close)
|
72
|
-
described_class.configure {}
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
63
|
context "when called multiple times" do
|
77
64
|
it "doesn't overwrite performance notifier" do
|
78
65
|
described_class.configure {}
|
@@ -97,43 +84,65 @@ RSpec.describe Airbrake do
|
|
97
84
|
described_class.configure {}
|
98
85
|
expect(described_class.deploy_notifier).to eql(deploy_notifier)
|
99
86
|
end
|
87
|
+
|
88
|
+
it "doesn't append the same notice notifier filters over and over" do
|
89
|
+
described_class.configure do |c|
|
90
|
+
c.project_id = 1
|
91
|
+
c.project_key = '2'
|
92
|
+
end
|
93
|
+
|
94
|
+
expect(described_class.notice_notifier).not_to receive(:add_filter)
|
95
|
+
10.times { described_class.configure {} }
|
96
|
+
end
|
97
|
+
|
98
|
+
it "appends some default filters" do
|
99
|
+
allow(described_class.notice_notifier).to receive(:add_filter)
|
100
|
+
expect(described_class.notice_notifier).to receive(:add_filter).with(
|
101
|
+
an_instance_of(Airbrake::Filters::RootDirectoryFilter),
|
102
|
+
)
|
103
|
+
|
104
|
+
described_class.configure do |c|
|
105
|
+
c.project_id = 1
|
106
|
+
c.project_key = '2'
|
107
|
+
end
|
108
|
+
end
|
100
109
|
end
|
101
110
|
|
102
|
-
context "when
|
103
|
-
before { allow(
|
111
|
+
context "when blocklist_keys gets configured" do
|
112
|
+
before { allow(described_class.notice_notifier).to receive(:add_filter) }
|
104
113
|
|
105
|
-
it "adds
|
106
|
-
expect(
|
107
|
-
.with(an_instance_of(Airbrake::Filters::
|
108
|
-
described_class.configure { |c| c.
|
114
|
+
it "adds blocklist filter" do
|
115
|
+
expect(described_class.notice_notifier).to receive(:add_filter)
|
116
|
+
.with(an_instance_of(Airbrake::Filters::KeysBlocklist))
|
117
|
+
described_class.configure { |c| c.blocklist_keys = %w[password] }
|
109
118
|
end
|
110
119
|
|
111
|
-
it "initializes
|
112
|
-
expect(Airbrake::Filters::
|
113
|
-
described_class.configure { |c| c.
|
120
|
+
it "initializes blocklist with specified parameters" do
|
121
|
+
expect(Airbrake::Filters::KeysBlocklist).to receive(:new).with(%w[password])
|
122
|
+
described_class.configure { |c| c.blocklist_keys = %w[password] }
|
114
123
|
end
|
115
124
|
end
|
116
125
|
|
117
|
-
context "when
|
118
|
-
before { allow(
|
126
|
+
context "when allowlist_keys gets configured" do
|
127
|
+
before { allow(described_class.notice_notifier).to receive(:add_filter) }
|
119
128
|
|
120
|
-
it "adds
|
121
|
-
expect(
|
122
|
-
.with(an_instance_of(Airbrake::Filters::
|
123
|
-
described_class.configure { |c| c.
|
129
|
+
it "adds allowlist filter" do
|
130
|
+
expect(described_class.notice_notifier).to receive(:add_filter)
|
131
|
+
.with(an_instance_of(Airbrake::Filters::KeysAllowlist))
|
132
|
+
described_class.configure { |c| c.allowlist_keys = %w[banana] }
|
124
133
|
end
|
125
134
|
|
126
|
-
it "initializes
|
127
|
-
expect(Airbrake::Filters::
|
128
|
-
described_class.configure { |c| c.
|
135
|
+
it "initializes allowlist with specified parameters" do
|
136
|
+
expect(Airbrake::Filters::KeysAllowlist).to receive(:new).with(%w[banana])
|
137
|
+
described_class.configure { |c| c.allowlist_keys = %w[banana] }
|
129
138
|
end
|
130
139
|
end
|
131
140
|
|
132
141
|
context "when root_directory gets configured" do
|
133
|
-
before { allow(
|
142
|
+
before { allow(described_class.notice_notifier).to receive(:add_filter) }
|
134
143
|
|
135
144
|
it "adds root directory filter" do
|
136
|
-
expect(
|
145
|
+
expect(described_class.notice_notifier).to receive(:add_filter)
|
137
146
|
.with(an_instance_of(Airbrake::Filters::RootDirectoryFilter))
|
138
147
|
described_class.configure { |c| c.root_directory = '/my/path' }
|
139
148
|
end
|
@@ -145,7 +154,7 @@ RSpec.describe Airbrake do
|
|
145
154
|
end
|
146
155
|
|
147
156
|
it "adds git revision filter" do
|
148
|
-
expect(
|
157
|
+
expect(described_class.notice_notifier).to receive(:add_filter)
|
149
158
|
.with(an_instance_of(Airbrake::Filters::GitRevisionFilter))
|
150
159
|
described_class.configure { |c| c.root_directory = '/my/path' }
|
151
160
|
end
|
@@ -157,7 +166,7 @@ RSpec.describe Airbrake do
|
|
157
166
|
end
|
158
167
|
|
159
168
|
it "adds git repository filter" do
|
160
|
-
expect(
|
169
|
+
expect(described_class.notice_notifier).to receive(:add_filter)
|
161
170
|
.with(an_instance_of(Airbrake::Filters::GitRepositoryFilter))
|
162
171
|
described_class.configure { |c| c.root_directory = '/my/path' }
|
163
172
|
end
|
@@ -169,7 +178,7 @@ RSpec.describe Airbrake do
|
|
169
178
|
end
|
170
179
|
|
171
180
|
it "adds git last checkout filter" do
|
172
|
-
expect(
|
181
|
+
expect(described_class.notice_notifier).to receive(:add_filter)
|
173
182
|
.with(an_instance_of(Airbrake::Filters::GitLastCheckoutFilter))
|
174
183
|
described_class.configure { |c| c.root_directory = '/my/path' }
|
175
184
|
end
|
@@ -182,20 +191,7 @@ RSpec.describe Airbrake do
|
|
182
191
|
end
|
183
192
|
end
|
184
193
|
|
185
|
-
describe "
|
186
|
-
context "when Airbrake was previously configured" do
|
187
|
-
before do
|
188
|
-
expect(described_class).to receive(:configured?).and_return(true)
|
189
|
-
end
|
190
|
-
|
191
|
-
it "closes notice notifier" do
|
192
|
-
expect(described_class).to receive(:close)
|
193
|
-
subject.reset
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
describe "#notify_request" do
|
194
|
+
describe ".notify_request" do
|
199
195
|
context "when :stash key is not provided" do
|
200
196
|
it "doesn't add anything to the stash of the request" do
|
201
197
|
expect(described_class.performance_notifier).to receive(:notify) do |request|
|
@@ -206,7 +202,7 @@ RSpec.describe Airbrake do
|
|
206
202
|
method: 'GET',
|
207
203
|
route: '/',
|
208
204
|
status_code: 200,
|
209
|
-
|
205
|
+
timing: 1,
|
210
206
|
)
|
211
207
|
end
|
212
208
|
end
|
@@ -222,15 +218,31 @@ RSpec.describe Airbrake do
|
|
222
218
|
method: 'GET',
|
223
219
|
route: '/',
|
224
220
|
status_code: 200,
|
225
|
-
|
221
|
+
timing: 1,
|
226
222
|
},
|
227
|
-
request_id: 1
|
223
|
+
request_id: 1,
|
228
224
|
)
|
229
225
|
end
|
230
226
|
end
|
231
227
|
end
|
232
228
|
|
233
|
-
describe "
|
229
|
+
describe ".notify_request_sync" do
|
230
|
+
it "notifies request synchronously" do
|
231
|
+
expect(described_class.performance_notifier).to receive(:notify_sync)
|
232
|
+
|
233
|
+
described_class.notify_request_sync(
|
234
|
+
{
|
235
|
+
method: 'GET',
|
236
|
+
route: '/',
|
237
|
+
status_code: 200,
|
238
|
+
timing: 1,
|
239
|
+
},
|
240
|
+
request_id: 1,
|
241
|
+
)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe ".notify_query" do
|
234
246
|
context "when :stash key is not provided" do
|
235
247
|
it "doesn't add anything to the stash of the query" do
|
236
248
|
expect(described_class.performance_notifier).to receive(:notify) do |query|
|
@@ -241,7 +253,7 @@ RSpec.describe Airbrake do
|
|
241
253
|
method: 'GET',
|
242
254
|
route: '/',
|
243
255
|
query: '',
|
244
|
-
|
256
|
+
timing: 1,
|
245
257
|
)
|
246
258
|
end
|
247
259
|
end
|
@@ -257,15 +269,31 @@ RSpec.describe Airbrake do
|
|
257
269
|
method: 'GET',
|
258
270
|
route: '/',
|
259
271
|
query: '',
|
260
|
-
|
272
|
+
timing: 1,
|
261
273
|
},
|
262
|
-
request_id: 1
|
274
|
+
request_id: 1,
|
263
275
|
)
|
264
276
|
end
|
265
277
|
end
|
266
278
|
end
|
267
279
|
|
268
|
-
describe "
|
280
|
+
describe ".notify_query_sync" do
|
281
|
+
it "notifies query synchronously" do
|
282
|
+
expect(described_class.performance_notifier).to receive(:notify_sync)
|
283
|
+
|
284
|
+
described_class.notify_query_sync(
|
285
|
+
{
|
286
|
+
method: 'GET',
|
287
|
+
route: '/',
|
288
|
+
query: '',
|
289
|
+
timing: 1,
|
290
|
+
},
|
291
|
+
request_id: 1,
|
292
|
+
)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
describe ".notify_performance_breakdown" do
|
269
297
|
context "when :stash key is not provided" do
|
270
298
|
it "doesn't add anything to the stash of the performance breakdown" do
|
271
299
|
expect(described_class.performance_notifier).to receive(:notify) do |query|
|
@@ -276,7 +304,7 @@ RSpec.describe Airbrake do
|
|
276
304
|
method: 'GET',
|
277
305
|
route: '/',
|
278
306
|
query: '',
|
279
|
-
|
307
|
+
timing: 1,
|
280
308
|
)
|
281
309
|
end
|
282
310
|
end
|
@@ -284,7 +312,7 @@ RSpec.describe Airbrake do
|
|
284
312
|
context "when :stash key is provided" do
|
285
313
|
it "adds the value as the stash of the performance breakdown" do
|
286
314
|
expect(
|
287
|
-
described_class.performance_notifier
|
315
|
+
described_class.performance_notifier,
|
288
316
|
).to receive(:notify) do |performance_breakdown|
|
289
317
|
expect(performance_breakdown.stash).to eq(request_id: 1)
|
290
318
|
end
|
@@ -295,14 +323,76 @@ RSpec.describe Airbrake do
|
|
295
323
|
route: '/',
|
296
324
|
response_type: :html,
|
297
325
|
groups: {},
|
298
|
-
|
326
|
+
timing: 1,
|
327
|
+
},
|
328
|
+
request_id: 1,
|
329
|
+
)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
describe ".notify_performance_breakdown_sync" do
|
335
|
+
it "notifies performance breakdown synchronously" do
|
336
|
+
expect(described_class.performance_notifier).to receive(:notify_sync)
|
337
|
+
|
338
|
+
described_class.notify_performance_breakdown_sync(
|
339
|
+
{
|
340
|
+
method: 'GET',
|
341
|
+
route: '/',
|
342
|
+
response_type: :html,
|
343
|
+
groups: {},
|
344
|
+
timing: 1,
|
345
|
+
},
|
346
|
+
request_id: 1,
|
347
|
+
)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
describe ".notify_queue" do
|
352
|
+
context "when :stash key is not provided" do
|
353
|
+
it "doesn't add anything to the stash of the queue" do
|
354
|
+
expect(described_class.performance_notifier).to receive(:notify) do |queue|
|
355
|
+
expect(queue.stash).to be_empty
|
356
|
+
end
|
357
|
+
|
358
|
+
described_class.notify_queue(
|
359
|
+
queue: 'bananas',
|
360
|
+
error_count: 10,
|
361
|
+
)
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
context "when :stash key is provided" do
|
366
|
+
it "adds the value as the stash of the queue" do
|
367
|
+
expect(described_class.performance_notifier).to receive(:notify) do |queue|
|
368
|
+
expect(queue.stash).to eq(request_id: 1)
|
369
|
+
end
|
370
|
+
|
371
|
+
described_class.notify_queue(
|
372
|
+
{
|
373
|
+
queue: 'bananas',
|
374
|
+
error_count: 10,
|
299
375
|
},
|
300
|
-
request_id: 1
|
376
|
+
request_id: 1,
|
301
377
|
)
|
302
378
|
end
|
303
379
|
end
|
304
380
|
end
|
305
381
|
|
382
|
+
describe ".notify_queue_sync" do
|
383
|
+
it "notifies queue synchronously" do
|
384
|
+
expect(described_class.performance_notifier).to receive(:notify_sync)
|
385
|
+
|
386
|
+
described_class.notify_queue_sync(
|
387
|
+
{
|
388
|
+
queue: 'bananas',
|
389
|
+
error_count: 10,
|
390
|
+
},
|
391
|
+
request_id: 1,
|
392
|
+
)
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
306
396
|
describe ".performance_notifier" do
|
307
397
|
it "returns a performance notifier" do
|
308
398
|
expect(described_class.performance_notifier)
|
@@ -321,4 +411,49 @@ RSpec.describe Airbrake do
|
|
321
411
|
expect(described_class.deploy_notifier).to be_an(Airbrake::DeployNotifier)
|
322
412
|
end
|
323
413
|
end
|
414
|
+
|
415
|
+
describe ".close" do
|
416
|
+
after { described_class.reset }
|
417
|
+
|
418
|
+
context "when notice_notifier is defined" do
|
419
|
+
it "gets closed" do
|
420
|
+
expect(described_class.notice_notifier).to receive(:close)
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
context "when notice_notifier is undefined" do
|
425
|
+
it "doesn't get closed (because it wasn't initialized)" do
|
426
|
+
described_class.instance_variable_set(:@notice_notifier, nil)
|
427
|
+
expect_any_instance_of(Airbrake::NoticeNotifier).not_to receive(:close)
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
context "when performance_notifier is defined" do
|
432
|
+
it "gets closed" do
|
433
|
+
expect(described_class.performance_notifier).to receive(:close)
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
context "when perforance_notifier is undefined" do
|
438
|
+
it "doesn't get closed (because it wasn't initialized)" do
|
439
|
+
described_class.instance_variable_set(:@performance_notifier, nil)
|
440
|
+
expect_any_instance_of(Airbrake::PerformanceNotifier)
|
441
|
+
.not_to receive(:close)
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
context "when remote settings are defined" do
|
446
|
+
it "stops polling" do
|
447
|
+
described_class.instance_variable_set(:@remote_settings, remote_settings)
|
448
|
+
expect(remote_settings).to receive(:stop_polling)
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
context "when remote settings are undefined" do
|
453
|
+
it "doesn't stop polling (because they weren't initialized)" do
|
454
|
+
described_class.instance_variable_set(:@remote_settings, nil)
|
455
|
+
expect(remote_settings).not_to receive(:stop_polling)
|
456
|
+
end
|
457
|
+
end
|
458
|
+
end
|
324
459
|
end
|