airbrake-ruby 4.6.0 → 6.2.2

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.
Files changed (107) hide show
  1. checksums.yaml +5 -5
  2. data/lib/airbrake-ruby/async_sender.rb +24 -109
  3. data/lib/airbrake-ruby/backlog.rb +123 -0
  4. data/lib/airbrake-ruby/backtrace.rb +8 -7
  5. data/lib/airbrake-ruby/benchmark.rb +1 -1
  6. data/lib/airbrake-ruby/code_hunk.rb +1 -1
  7. data/lib/airbrake-ruby/config/processor.rb +77 -0
  8. data/lib/airbrake-ruby/config/validator.rb +9 -3
  9. data/lib/airbrake-ruby/config.rb +78 -19
  10. data/lib/airbrake-ruby/context.rb +51 -0
  11. data/lib/airbrake-ruby/deploy_notifier.rb +1 -1
  12. data/lib/airbrake-ruby/file_cache.rb +6 -0
  13. data/lib/airbrake-ruby/filter_chain.rb +18 -1
  14. data/lib/airbrake-ruby/filters/context_filter.rb +4 -5
  15. data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
  16. data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +3 -3
  17. data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
  18. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +7 -7
  19. data/lib/airbrake-ruby/filters/git_repository_filter.rb +11 -2
  20. data/lib/airbrake-ruby/filters/git_revision_filter.rb +3 -1
  21. data/lib/airbrake-ruby/filters/{keys_whitelist.rb → keys_allowlist.rb} +3 -3
  22. data/lib/airbrake-ruby/filters/{keys_blacklist.rb → keys_blocklist.rb} +3 -3
  23. data/lib/airbrake-ruby/filters/keys_filter.rb +41 -22
  24. data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
  25. data/lib/airbrake-ruby/filters/sql_filter.rb +35 -11
  26. data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
  27. data/lib/airbrake-ruby/filters/thread_filter.rb +6 -5
  28. data/lib/airbrake-ruby/grouppable.rb +12 -0
  29. data/lib/airbrake-ruby/ignorable.rb +1 -2
  30. data/lib/airbrake-ruby/inspectable.rb +2 -2
  31. data/lib/airbrake-ruby/loggable.rb +1 -1
  32. data/lib/airbrake-ruby/mergeable.rb +12 -0
  33. data/lib/airbrake-ruby/monotonic_time.rb +6 -1
  34. data/lib/airbrake-ruby/nested_exception.rb +22 -1
  35. data/lib/airbrake-ruby/notice.rb +12 -17
  36. data/lib/airbrake-ruby/notice_notifier.rb +15 -7
  37. data/lib/airbrake-ruby/performance_breakdown.rb +16 -9
  38. data/lib/airbrake-ruby/performance_notifier.rb +106 -54
  39. data/lib/airbrake-ruby/promise.rb +1 -0
  40. data/lib/airbrake-ruby/query.rb +20 -14
  41. data/lib/airbrake-ruby/queue.rb +65 -0
  42. data/lib/airbrake-ruby/remote_settings/callback.rb +44 -0
  43. data/lib/airbrake-ruby/remote_settings/settings_data.rb +116 -0
  44. data/lib/airbrake-ruby/remote_settings.rb +128 -0
  45. data/lib/airbrake-ruby/request.rb +14 -11
  46. data/lib/airbrake-ruby/response.rb +56 -5
  47. data/lib/airbrake-ruby/stat.rb +27 -34
  48. data/lib/airbrake-ruby/sync_sender.rb +43 -11
  49. data/lib/airbrake-ruby/tdigest.rb +52 -66
  50. data/lib/airbrake-ruby/thread_pool.rb +139 -0
  51. data/lib/airbrake-ruby/time_truncate.rb +2 -2
  52. data/lib/airbrake-ruby/timed_trace.rb +1 -3
  53. data/lib/airbrake-ruby/truncator.rb +10 -4
  54. data/lib/airbrake-ruby/version.rb +11 -1
  55. data/lib/airbrake-ruby.rb +157 -78
  56. metadata +122 -116
  57. data/spec/airbrake_spec.rb +0 -324
  58. data/spec/async_sender_spec.rb +0 -155
  59. data/spec/backtrace_spec.rb +0 -427
  60. data/spec/benchmark_spec.rb +0 -33
  61. data/spec/code_hunk_spec.rb +0 -115
  62. data/spec/config/validator_spec.rb +0 -184
  63. data/spec/config_spec.rb +0 -154
  64. data/spec/deploy_notifier_spec.rb +0 -48
  65. data/spec/file_cache.rb +0 -36
  66. data/spec/filter_chain_spec.rb +0 -92
  67. data/spec/filters/context_filter_spec.rb +0 -23
  68. data/spec/filters/dependency_filter_spec.rb +0 -12
  69. data/spec/filters/exception_attributes_filter_spec.rb +0 -50
  70. data/spec/filters/gem_root_filter_spec.rb +0 -41
  71. data/spec/filters/git_last_checkout_filter_spec.rb +0 -46
  72. data/spec/filters/git_repository_filter.rb +0 -61
  73. data/spec/filters/git_revision_filter_spec.rb +0 -126
  74. data/spec/filters/keys_blacklist_spec.rb +0 -225
  75. data/spec/filters/keys_whitelist_spec.rb +0 -194
  76. data/spec/filters/root_directory_filter_spec.rb +0 -39
  77. data/spec/filters/sql_filter_spec.rb +0 -219
  78. data/spec/filters/system_exit_filter_spec.rb +0 -14
  79. data/spec/filters/thread_filter_spec.rb +0 -277
  80. data/spec/fixtures/notroot.txt +0 -7
  81. data/spec/fixtures/project_root/code.rb +0 -221
  82. data/spec/fixtures/project_root/empty_file.rb +0 -0
  83. data/spec/fixtures/project_root/long_line.txt +0 -1
  84. data/spec/fixtures/project_root/short_file.rb +0 -3
  85. data/spec/fixtures/project_root/vendor/bundle/ignored_file.rb +0 -5
  86. data/spec/helpers.rb +0 -9
  87. data/spec/ignorable_spec.rb +0 -14
  88. data/spec/inspectable_spec.rb +0 -45
  89. data/spec/monotonic_time_spec.rb +0 -12
  90. data/spec/nested_exception_spec.rb +0 -73
  91. data/spec/notice_notifier_spec/options_spec.rb +0 -259
  92. data/spec/notice_notifier_spec.rb +0 -356
  93. data/spec/notice_spec.rb +0 -296
  94. data/spec/performance_breakdown_spec.rb +0 -12
  95. data/spec/performance_notifier_spec.rb +0 -435
  96. data/spec/promise_spec.rb +0 -197
  97. data/spec/query_spec.rb +0 -11
  98. data/spec/request_spec.rb +0 -11
  99. data/spec/response_spec.rb +0 -88
  100. data/spec/spec_helper.rb +0 -100
  101. data/spec/stashable_spec.rb +0 -23
  102. data/spec/stat_spec.rb +0 -47
  103. data/spec/sync_sender_spec.rb +0 -133
  104. data/spec/tdigest_spec.rb +0 -230
  105. data/spec/time_truncate_spec.rb +0 -13
  106. data/spec/timed_trace_spec.rb +0 -125
  107. data/spec/truncator_spec.rb +0 -238
data/spec/notice_spec.rb DELETED
@@ -1,296 +0,0 @@
1
- RSpec.describe Airbrake::Notice do
2
- let(:notice) { described_class.new(AirbrakeTestError.new, bingo: '1') }
3
-
4
- describe "#to_json" do
5
- context "app_version" do
6
- context "when missing" do
7
- before { Airbrake::Config.instance.merge(app_version: nil) }
8
-
9
- it "doesn't include app_version" do
10
- expect(notice.to_json).not_to match(/"context":{"version":"1.2.3"/)
11
- end
12
- end
13
-
14
- context "when present" do
15
- let(:notice) { described_class.new(AirbrakeTestError.new) }
16
-
17
- before do
18
- Airbrake::Config.instance.merge(
19
- app_version: "1.2.3",
20
- root_directory: "/one/two"
21
- )
22
- end
23
-
24
- it "includes app_version" do
25
- expect(notice.to_json).to match(/"context":{"version":"1.2.3"/)
26
- end
27
-
28
- it "includes root_directory" do
29
- expect(notice.to_json).to match(%r{"rootDirectory":"/one/two"})
30
- end
31
- end
32
- end
33
-
34
- context "when versions is empty" do
35
- it "doesn't set the 'versions' payload" do
36
- expect(notice.to_json).not_to match(
37
- /"context":{"versions":{"dep":"1.2.3"}}/
38
- )
39
- end
40
- end
41
-
42
- context "when versions is not empty" do
43
- it "sets the 'versions' payload" do
44
- notice[:context][:versions] = { 'dep' => '1.2.3' }
45
- expect(notice.to_json).to match(
46
- /"context":{.*"versions":{"dep":"1.2.3"}.*}/
47
- )
48
- end
49
- end
50
-
51
- context "truncation" do
52
- shared_examples 'payloads' do |size, msg|
53
- it msg do
54
- ex = AirbrakeTestError.new
55
-
56
- backtrace = []
57
- size.times { backtrace << "bin/rails:3:in `<main>'" }
58
- ex.set_backtrace(backtrace)
59
-
60
- notice = described_class.new(ex)
61
-
62
- expect(notice.to_json.bytesize).to be < 64000
63
- end
64
- end
65
-
66
- max_msg = 'truncates to the max allowed size'
67
-
68
- context "with an extremely huge payload" do
69
- include_examples 'payloads', 200_000, max_msg
70
- end
71
-
72
- context "with a big payload" do
73
- include_examples 'payloads', 50_000, max_msg
74
- end
75
-
76
- small_msg = "doesn't truncate it"
77
-
78
- context "with a small payload" do
79
- include_examples 'payloads', 1000, small_msg
80
- end
81
-
82
- context "with a tiny payload" do
83
- include_examples 'payloads', 300, small_msg
84
- end
85
-
86
- context "when truncation failed" do
87
- it "returns nil" do
88
- expect_any_instance_of(Airbrake::Truncator)
89
- .to receive(:reduce_max_size).and_return(0)
90
-
91
- encoded = Base64.encode64("\xD3\xE6\xBC\x9D\xBA").encode!('ASCII-8BIT')
92
- bad_string = Base64.decode64(encoded)
93
-
94
- ex = AirbrakeTestError.new
95
-
96
- backtrace = []
97
- 10.times { backtrace << "bin/rails:3:in `<#{bad_string}>'" }
98
- ex.set_backtrace(backtrace)
99
-
100
- notice = described_class.new(ex)
101
- expect(notice.to_json).to be_nil
102
- end
103
- end
104
-
105
- describe "object replacement with its string version" do
106
- let(:klass) { Class.new {} }
107
- let(:ex) { AirbrakeTestError.new }
108
- let(:params) { { bingo: [Object.new, klass.new] } }
109
- let(:notice) { described_class.new(ex, params) }
110
-
111
- before do
112
- backtrace = []
113
- backtrace_size.times { backtrace << "bin/rails:3:in `<main>'" }
114
- ex.set_backtrace(backtrace)
115
- end
116
-
117
- context "with payload within the limits" do
118
- let(:backtrace_size) { 1000 }
119
-
120
- it "doesn't happen" do
121
- expect(notice.to_json)
122
- .to match(/bingo":\["#<Object:.+>","#<#<Class:.+>:.+>"/)
123
- end
124
- end
125
-
126
- context "with payload bigger than the limit" do
127
- context "with payload within the limits" do
128
- let(:backtrace_size) { 50_000 }
129
-
130
- it "happens" do
131
- expect(notice.to_json)
132
- .to match(/bingo":\[".+Object.+",".+Class.+"/)
133
- end
134
- end
135
- end
136
- end
137
- end
138
-
139
- context "given a closed IO object" do
140
- context "and when it is not monkey-patched by ActiveSupport" do
141
- it "is not getting truncated" do
142
- notice[:params] = { obj: IO.new(0).tap(&:close) }
143
- expect(notice.to_json).to match(/"obj":"#<IO:0x.+>"/)
144
- end
145
- end
146
-
147
- context "and when it is monkey-patched by ActiveSupport" do
148
- # Instances of this class contain a closed IO object assigned to an
149
- # instance variable. Normally, the JSON gem, which we depend on can
150
- # parse closed IO objects. However, because ActiveSupport monkey-patches
151
- # #to_json and calls #to_a on them, they raise IOError when we try to
152
- # serialize them.
153
- #
154
- # @see https://goo.gl/0A3xNC
155
- class ObjectWithIoIvars
156
- def initialize
157
- @bongo = Tempfile.new('bongo').tap(&:close)
158
- end
159
-
160
- # @raise [NotImplementedError] when inside a Rails environment
161
- def to_json(*)
162
- raise NotImplementedError
163
- end
164
- end
165
-
166
- # @see ObjectWithIoIvars
167
- class ObjectWithNestedIoIvars
168
- def initialize
169
- @bish = ObjectWithIoIvars.new
170
- end
171
-
172
- # @see ObjectWithIoIvars#to_json
173
- def to_json(*)
174
- raise NotImplementedError
175
- end
176
- end
177
-
178
- context "and also when it's a closed Tempfile" do
179
- it "doesn't fail" do
180
- notice[:params] = { obj: Tempfile.new('bongo').tap(&:close) }
181
- expect(notice.to_json).to match(/"obj":"#<(Temp)?file:0x.+>"/i)
182
- end
183
- end
184
-
185
- context "and also when it's an IO ivar" do
186
- it "doesn't fail" do
187
- notice[:params] = { obj: ObjectWithIoIvars.new }
188
- expect(notice.to_json).to match(/"obj":".+ObjectWithIoIvars.+"/)
189
- end
190
-
191
- context "and when it's deeply nested inside a hash" do
192
- it "doesn't fail" do
193
- notice[:params] = { a: { b: { c: ObjectWithIoIvars.new } } }
194
- expect(notice.to_json).to match(
195
- /"params":{"a":{"b":{"c":".+ObjectWithIoIvars.+"}}.*}/
196
- )
197
- end
198
- end
199
-
200
- context "and when it's deeply nested inside an array" do
201
- it "doesn't fail" do
202
- notice[:params] = { a: [[ObjectWithIoIvars.new]] }
203
- expect(notice.to_json).to match(
204
- /"params":{"a":\[\[".+ObjectWithIoIvars.+"\]\].*}/
205
- )
206
- end
207
- end
208
- end
209
-
210
- context "and also when it's a non-IO ivar, which contains an IO ivar itself" do
211
- it "doesn't fail" do
212
- notice[:params] = { obj: ObjectWithNestedIoIvars.new }
213
- expect(notice.to_json).to match(/"obj":".+ObjectWithNested.+"/)
214
- end
215
- end
216
- end
217
- end
218
-
219
- it "overwrites the 'notifier' payload with the default values" do
220
- notice[:notifier] = { name: 'bingo', bango: 'bongo' }
221
-
222
- expect(notice.to_json)
223
- .to match(/"notifier":{"name":"airbrake-ruby","version":".+","url":".+"}/)
224
- end
225
-
226
- it "always contains context/hostname" do
227
- expect(notice.to_json)
228
- .to match(/"context":{.*"hostname":".+".*}/)
229
- end
230
-
231
- it "defaults to the error severity" do
232
- expect(notice.to_json).to match(/"context":{.*"severity":"error".*}/)
233
- end
234
-
235
- it "always contains environment/program_name" do
236
- expect(notice.to_json)
237
- .to match(%r|"environment":{"program_name":.+/rspec.*|)
238
- end
239
-
240
- it "contains errors" do
241
- expect(notice.to_json)
242
- .to match(/"errors":\[{"type":"AirbrakeTestError","message":"App crash/)
243
- end
244
-
245
- it "contains a backtrace" do
246
- expect(notice.to_json)
247
- .to match(%r|"backtrace":\[{"file":"/home/.+/spec/spec_helper.rb"|)
248
- end
249
-
250
- it "contains params" do
251
- expect(notice.to_json).to match(/"params":{"bingo":"1"}/)
252
- end
253
- end
254
-
255
- describe "#[]" do
256
- it "accesses payload" do
257
- expect(notice[:params]).to eq(bingo: '1')
258
- end
259
-
260
- it "raises error if notice is ignored" do
261
- notice.ignore!
262
- expect { notice[:params] }
263
- .to raise_error(Airbrake::Error, 'cannot access ignored Airbrake::Notice')
264
- end
265
- end
266
-
267
- describe "#[]=" do
268
- it "sets a payload value" do
269
- hash = { bingo: 'bango' }
270
- notice[:params] = hash
271
- expect(notice[:params]).to equal(hash)
272
- end
273
-
274
- it "raises error if notice is ignored" do
275
- notice.ignore!
276
- expect { notice[:params] = {} }
277
- .to raise_error(Airbrake::Error, 'cannot access ignored Airbrake::Notice')
278
- end
279
-
280
- it "raises error when trying to assign unrecognized key" do
281
- expect { notice[:bingo] = 1 }
282
- .to raise_error(Airbrake::Error, /:bingo is not recognized among/)
283
- end
284
-
285
- it "raises when setting non-hash objects as the value" do
286
- expect { notice[:params] = Object.new }
287
- .to raise_error(Airbrake::Error, 'Got Object value, wanted a Hash')
288
- end
289
- end
290
-
291
- describe "#stash" do
292
- subject { described_class.new(AirbrakeTestError.new) }
293
-
294
- it { is_expected.to respond_to(:stash) }
295
- end
296
- end
@@ -1,12 +0,0 @@
1
- RSpec.describe Airbrake::PerformanceBreakdown do
2
- describe "#stash" do
3
- subject do
4
- described_class.new(
5
- method: 'GET', route: '/', response_type: '', groups: {},
6
- start_time: Time.now
7
- )
8
- end
9
-
10
- it { is_expected.to respond_to(:stash) }
11
- end
12
- end