airbrake-ruby 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.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/lib/airbrake-ruby.rb +515 -0
  3. data/lib/airbrake-ruby/async_sender.rb +80 -0
  4. data/lib/airbrake-ruby/backtrace.rb +196 -0
  5. data/lib/airbrake-ruby/benchmark.rb +39 -0
  6. data/lib/airbrake-ruby/code_hunk.rb +51 -0
  7. data/lib/airbrake-ruby/config.rb +229 -0
  8. data/lib/airbrake-ruby/config/validator.rb +91 -0
  9. data/lib/airbrake-ruby/deploy_notifier.rb +36 -0
  10. data/lib/airbrake-ruby/file_cache.rb +54 -0
  11. data/lib/airbrake-ruby/filter_chain.rb +95 -0
  12. data/lib/airbrake-ruby/filters/context_filter.rb +29 -0
  13. data/lib/airbrake-ruby/filters/dependency_filter.rb +31 -0
  14. data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +46 -0
  15. data/lib/airbrake-ruby/filters/gem_root_filter.rb +33 -0
  16. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +92 -0
  17. data/lib/airbrake-ruby/filters/git_repository_filter.rb +64 -0
  18. data/lib/airbrake-ruby/filters/git_revision_filter.rb +66 -0
  19. data/lib/airbrake-ruby/filters/keys_blacklist.rb +49 -0
  20. data/lib/airbrake-ruby/filters/keys_filter.rb +140 -0
  21. data/lib/airbrake-ruby/filters/keys_whitelist.rb +48 -0
  22. data/lib/airbrake-ruby/filters/root_directory_filter.rb +28 -0
  23. data/lib/airbrake-ruby/filters/sql_filter.rb +125 -0
  24. data/lib/airbrake-ruby/filters/system_exit_filter.rb +23 -0
  25. data/lib/airbrake-ruby/filters/thread_filter.rb +92 -0
  26. data/lib/airbrake-ruby/hash_keyable.rb +37 -0
  27. data/lib/airbrake-ruby/ignorable.rb +44 -0
  28. data/lib/airbrake-ruby/inspectable.rb +39 -0
  29. data/lib/airbrake-ruby/loggable.rb +34 -0
  30. data/lib/airbrake-ruby/monotonic_time.rb +43 -0
  31. data/lib/airbrake-ruby/nested_exception.rb +38 -0
  32. data/lib/airbrake-ruby/notice.rb +162 -0
  33. data/lib/airbrake-ruby/notice_notifier.rb +134 -0
  34. data/lib/airbrake-ruby/performance_breakdown.rb +46 -0
  35. data/lib/airbrake-ruby/performance_notifier.rb +155 -0
  36. data/lib/airbrake-ruby/promise.rb +109 -0
  37. data/lib/airbrake-ruby/query.rb +54 -0
  38. data/lib/airbrake-ruby/request.rb +46 -0
  39. data/lib/airbrake-ruby/response.rb +74 -0
  40. data/lib/airbrake-ruby/stashable.rb +15 -0
  41. data/lib/airbrake-ruby/stat.rb +73 -0
  42. data/lib/airbrake-ruby/sync_sender.rb +113 -0
  43. data/lib/airbrake-ruby/tdigest.rb +393 -0
  44. data/lib/airbrake-ruby/thread_pool.rb +128 -0
  45. data/lib/airbrake-ruby/time_truncate.rb +17 -0
  46. data/lib/airbrake-ruby/timed_trace.rb +58 -0
  47. data/lib/airbrake-ruby/truncator.rb +115 -0
  48. data/lib/airbrake-ruby/version.rb +6 -0
  49. data/spec/airbrake_spec.rb +324 -0
  50. data/spec/async_sender_spec.rb +72 -0
  51. data/spec/backtrace_spec.rb +427 -0
  52. data/spec/benchmark_spec.rb +33 -0
  53. data/spec/code_hunk_spec.rb +115 -0
  54. data/spec/config/validator_spec.rb +184 -0
  55. data/spec/config_spec.rb +154 -0
  56. data/spec/deploy_notifier_spec.rb +48 -0
  57. data/spec/file_cache_spec.rb +34 -0
  58. data/spec/filter_chain_spec.rb +92 -0
  59. data/spec/filters/context_filter_spec.rb +23 -0
  60. data/spec/filters/dependency_filter_spec.rb +12 -0
  61. data/spec/filters/exception_attributes_filter_spec.rb +50 -0
  62. data/spec/filters/gem_root_filter_spec.rb +41 -0
  63. data/spec/filters/git_last_checkout_filter_spec.rb +46 -0
  64. data/spec/filters/git_repository_filter.rb +61 -0
  65. data/spec/filters/git_revision_filter_spec.rb +126 -0
  66. data/spec/filters/keys_blacklist_spec.rb +225 -0
  67. data/spec/filters/keys_whitelist_spec.rb +194 -0
  68. data/spec/filters/root_directory_filter_spec.rb +39 -0
  69. data/spec/filters/sql_filter_spec.rb +262 -0
  70. data/spec/filters/system_exit_filter_spec.rb +14 -0
  71. data/spec/filters/thread_filter_spec.rb +277 -0
  72. data/spec/fixtures/notroot.txt +7 -0
  73. data/spec/fixtures/project_root/code.rb +221 -0
  74. data/spec/fixtures/project_root/empty_file.rb +0 -0
  75. data/spec/fixtures/project_root/long_line.txt +1 -0
  76. data/spec/fixtures/project_root/short_file.rb +3 -0
  77. data/spec/fixtures/project_root/vendor/bundle/ignored_file.rb +5 -0
  78. data/spec/helpers.rb +9 -0
  79. data/spec/ignorable_spec.rb +14 -0
  80. data/spec/inspectable_spec.rb +45 -0
  81. data/spec/monotonic_time_spec.rb +12 -0
  82. data/spec/nested_exception_spec.rb +73 -0
  83. data/spec/notice_notifier/options_spec.rb +259 -0
  84. data/spec/notice_notifier_spec.rb +356 -0
  85. data/spec/notice_spec.rb +296 -0
  86. data/spec/performance_breakdown_spec.rb +12 -0
  87. data/spec/performance_notifier_spec.rb +491 -0
  88. data/spec/promise_spec.rb +197 -0
  89. data/spec/query_spec.rb +11 -0
  90. data/spec/request_spec.rb +11 -0
  91. data/spec/response_spec.rb +88 -0
  92. data/spec/spec_helper.rb +100 -0
  93. data/spec/stashable_spec.rb +23 -0
  94. data/spec/stat_spec.rb +47 -0
  95. data/spec/sync_sender_spec.rb +133 -0
  96. data/spec/tdigest_spec.rb +230 -0
  97. data/spec/thread_pool_spec.rb +158 -0
  98. data/spec/time_truncate_spec.rb +13 -0
  99. data/spec/timed_trace_spec.rb +125 -0
  100. data/spec/truncator_spec.rb +238 -0
  101. metadata +216 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a05b705bc951aed966742d0403f8c29f9e96949b
4
+ data.tar.gz: e629610d7eace9ddca72ab165636b7e91bd7b255
5
+ SHA512:
6
+ metadata.gz: 37c876fee2ce05781a18f76cddd9f9c16c70a0d49e9d473736859ecfa6af5de03f6b3d75efde455096a79f80be73afbdd0ea0db85d49aa351c6875df3e16eecf
7
+ data.tar.gz: 2bd3600c3cf8263c4cc8f8606ea7a8ee55a2347275d2122b47a6703b0c0864061dfbc5ffa29524f966c6457261c77b991d19e0df1a07bb263154a6d42b45e987
@@ -0,0 +1,515 @@
1
+ require 'net/https'
2
+ require 'logger'
3
+ require 'json'
4
+ require 'thread'
5
+ require 'set'
6
+ require 'socket'
7
+ require 'time'
8
+
9
+ require 'airbrake-ruby/version'
10
+ require 'airbrake-ruby/loggable'
11
+ require 'airbrake-ruby/stashable'
12
+ require 'airbrake-ruby/config'
13
+ require 'airbrake-ruby/config/validator'
14
+ require 'airbrake-ruby/promise'
15
+ require 'airbrake-ruby/thread_pool'
16
+ require 'airbrake-ruby/sync_sender'
17
+ require 'airbrake-ruby/async_sender'
18
+ require 'airbrake-ruby/response'
19
+ require 'airbrake-ruby/nested_exception'
20
+ require 'airbrake-ruby/ignorable'
21
+ require 'airbrake-ruby/inspectable'
22
+ require 'airbrake-ruby/notice'
23
+ require 'airbrake-ruby/backtrace'
24
+ require 'airbrake-ruby/truncator'
25
+ require 'airbrake-ruby/filters/keys_filter'
26
+ require 'airbrake-ruby/filters/keys_whitelist'
27
+ require 'airbrake-ruby/filters/keys_blacklist'
28
+ require 'airbrake-ruby/filters/gem_root_filter'
29
+ require 'airbrake-ruby/filters/system_exit_filter'
30
+ require 'airbrake-ruby/filters/root_directory_filter'
31
+ require 'airbrake-ruby/filters/thread_filter'
32
+ require 'airbrake-ruby/filters/context_filter'
33
+ require 'airbrake-ruby/filters/exception_attributes_filter'
34
+ require 'airbrake-ruby/filters/dependency_filter'
35
+ require 'airbrake-ruby/filters/git_revision_filter'
36
+ require 'airbrake-ruby/filters/git_repository_filter'
37
+ require 'airbrake-ruby/filters/git_last_checkout_filter'
38
+ require 'airbrake-ruby/filters/sql_filter'
39
+ require 'airbrake-ruby/filter_chain'
40
+ require 'airbrake-ruby/code_hunk'
41
+ require 'airbrake-ruby/file_cache'
42
+ require 'airbrake-ruby/hash_keyable'
43
+ require 'airbrake-ruby/performance_notifier'
44
+ require 'airbrake-ruby/notice_notifier'
45
+ require 'airbrake-ruby/deploy_notifier'
46
+ require 'airbrake-ruby/stat'
47
+ require 'airbrake-ruby/time_truncate'
48
+ require 'airbrake-ruby/tdigest'
49
+ require 'airbrake-ruby/query'
50
+ require 'airbrake-ruby/request'
51
+ require 'airbrake-ruby/performance_breakdown'
52
+ require 'airbrake-ruby/benchmark'
53
+ require 'airbrake-ruby/monotonic_time'
54
+ require 'airbrake-ruby/timed_trace'
55
+
56
+ # Airbrake is a thin wrapper around instances of the notifier classes (such as
57
+ # notice, performance & deploy notifiers). It creates a way to access them via a
58
+ # consolidated global interface.
59
+ #
60
+ # Prior to using it, you must {configure} it.
61
+ #
62
+ # @example
63
+ # Airbrake.configure do |c|
64
+ # c.project_id = 113743
65
+ # c.project_key = 'fd04e13d806a90f96614ad8e529b2822'
66
+ # end
67
+ #
68
+ # Airbrake.notify('Oops!')
69
+ #
70
+ # @since v1.0.0
71
+ # @api public
72
+ module Airbrake
73
+ # The general error that this library uses when it wants to raise.
74
+ Error = Class.new(StandardError)
75
+
76
+ # @return [String] the label to be prepended to the log output
77
+ LOG_LABEL = '**Airbrake:'.freeze
78
+
79
+ # @return [Boolean] true if current Ruby is JRuby. The result is used for
80
+ # special cases where we need to work around older implementations
81
+ JRUBY = (RUBY_ENGINE == 'jruby')
82
+
83
+ class << self
84
+ # @since v4.2.3
85
+ # @api private
86
+ attr_writer :performance_notifier
87
+
88
+ # @since v4.2.3
89
+ # @api private
90
+ attr_writer :notice_notifier
91
+
92
+ # @since v4.2.3
93
+ # @api private
94
+ attr_writer :deploy_notifier
95
+
96
+ # Configures the Airbrake notifier.
97
+ #
98
+ # @example
99
+ # Airbrake.configure do |c|
100
+ # c.project_id = 113743
101
+ # c.project_key = 'fd04e13d806a90f96614ad8e529b2822'
102
+ # end
103
+ #
104
+ # @yield [config]
105
+ # @yieldparam config [Airbrake::Config]
106
+ # @return [void]
107
+ def configure
108
+ yield config = Airbrake::Config.instance
109
+ Airbrake::Loggable.instance = config.logger
110
+ process_config_options(config)
111
+ end
112
+
113
+ # @since v4.2.3
114
+ # @api private
115
+ def performance_notifier
116
+ @performance_notifier ||= PerformanceNotifier.new
117
+ end
118
+
119
+ # @since v4.2.3
120
+ # @api private
121
+ def notice_notifier
122
+ @notice_notifier ||= NoticeNotifier.new
123
+ end
124
+
125
+ # @since v4.2.3
126
+ # @api private
127
+ def deploy_notifier
128
+ @deploy_notifier ||= DeployNotifier.new
129
+ end
130
+
131
+ # @return [Boolean] true if the notifier was configured, false otherwise
132
+ # @since v2.3.0
133
+ def configured?
134
+ notice_notifier.configured?
135
+ end
136
+
137
+ # Sends an exception to Airbrake asynchronously.
138
+ #
139
+ # @example Sending an exception
140
+ # Airbrake.notify(RuntimeError.new('Oops!'))
141
+ # @example Sending a string
142
+ # # Converted to RuntimeError.new('Oops!') internally
143
+ # Airbrake.notify('Oops!')
144
+ # @example Sending a Notice
145
+ # notice = airbrake.build_notice(RuntimeError.new('Oops!'))
146
+ # airbrake.notify(notice)
147
+ #
148
+ # @param [Exception, String, Airbrake::Notice] exception The exception to be
149
+ # sent to Airbrake
150
+ # @param [Hash] params The additional payload to be sent to Airbrake. Can
151
+ # contain any values. The provided values will be displayed in the Params
152
+ # tab in your project's dashboard
153
+ # @yield [notice] The notice to filter
154
+ # @yieldparam [Airbrake::Notice]
155
+ # @yieldreturn [void]
156
+ # @return [Airbrake::Promise]
157
+ # @see .notify_sync
158
+ def notify(exception, params = {}, &block)
159
+ notice_notifier.notify(exception, params, &block)
160
+ end
161
+
162
+ # Sends an exception to Airbrake synchronously.
163
+ #
164
+ # @example
165
+ # Airbrake.notify_sync('App crashed!')
166
+ # #=> {"id"=>"123", "url"=>"https://airbrake.io/locate/321"}
167
+ #
168
+ # @param [Exception, String, Airbrake::Notice] exception The exception to be
169
+ # sent to Airbrake
170
+ # @param [Hash] params The additional payload to be sent to Airbrake. Can
171
+ # contain any values. The provided values will be displayed in the Params
172
+ # tab in your project's dashboard
173
+ # @yield [notice] The notice to filter
174
+ # @yieldparam [Airbrake::Notice]
175
+ # @yieldreturn [void]
176
+ # @return [Airbrake::Promise] the reponse from the server
177
+ # @see .notify
178
+ def notify_sync(exception, params = {}, &block)
179
+ notice_notifier.notify_sync(exception, params, &block)
180
+ end
181
+
182
+ # Runs a callback before {.notify} or {.notify_sync} kicks in. This is
183
+ # useful if you want to ignore specific notices or filter the data the
184
+ # notice contains.
185
+ #
186
+ # @example Ignore all notices
187
+ # Airbrake.add_filter(&:ignore!)
188
+ # @example Ignore based on some condition
189
+ # Airbrake.add_filter do |notice|
190
+ # notice.ignore! if notice[:error_class] == 'StandardError'
191
+ # end
192
+ # @example Ignore with help of a class
193
+ # class MyFilter
194
+ # def call(notice)
195
+ # # ...
196
+ # end
197
+ # end
198
+ #
199
+ # Airbrake.add_filter(MyFilter.new)
200
+ #
201
+ # @param [#call] filter The filter object
202
+ # @yield [notice] The notice to filter
203
+ # @yieldparam [Airbrake::Notice]
204
+ # @yieldreturn [void]
205
+ # @return [void]
206
+ def add_filter(filter = nil, &block)
207
+ notice_notifier.add_filter(filter, &block)
208
+ end
209
+
210
+ # Deletes a filter added via {Airbrake#add_filter}.
211
+ #
212
+ # @example
213
+ # # Add a MyFilter filter (we pass an instance here).
214
+ # Airbrake.add_filter(MyFilter.new)
215
+ #
216
+ # # Delete the filter (we pass class name here).
217
+ # Airbrake.delete_filter(MyFilter)
218
+ #
219
+ # @param [Class] filter_class The class of the filter you want to delete
220
+ # @return [void]
221
+ # @since v3.1.0
222
+ # @note This method cannot delete filters assigned via the Proc form.
223
+ def delete_filter(filter_class)
224
+ notice_notifier.delete_filter(filter_class)
225
+ end
226
+
227
+ # Builds an Airbrake notice. This is useful, if you want to add or modify a
228
+ # value only for a specific notice. When you're done modifying the notice,
229
+ # send it with {.notify} or {.notify_sync}.
230
+ #
231
+ # @example
232
+ # notice = airbrake.build_notice('App crashed!')
233
+ # notice[:params][:username] = user.name
234
+ # airbrake.notify_sync(notice)
235
+ #
236
+ # @param [Exception] exception The exception on top of which the notice
237
+ # should be built
238
+ # @param [Hash] params The additional params attached to the notice
239
+ # @return [Airbrake::Notice] the notice built with help of the given
240
+ # arguments
241
+ def build_notice(exception, params = {})
242
+ notice_notifier.build_notice(exception, params)
243
+ end
244
+
245
+ # Makes the notice notifier a no-op, which means you cannot use the
246
+ # {.notify} and {.notify_sync} methods anymore. It also stops the notice
247
+ # notifier's worker threads.
248
+ #
249
+ # @example
250
+ # Airbrake.close
251
+ # Airbrake.notify('App crashed!') #=> raises Airbrake::Error
252
+ #
253
+ # @return [void]
254
+ def close
255
+ notice_notifier.close
256
+ performance_notifier.close
257
+ end
258
+
259
+ # Pings the Airbrake Deploy API endpoint about the occurred deploy.
260
+ #
261
+ # @param [Hash{Symbol=>String}] deploy_info The params for the API
262
+ # @option deploy_info [Symbol] :environment
263
+ # @option deploy_info [Symbol] :username
264
+ # @option deploy_info [Symbol] :repository
265
+ # @option deploy_info [Symbol] :revision
266
+ # @option deploy_info [Symbol] :version
267
+ # @return [void]
268
+ def notify_deploy(deploy_info)
269
+ deploy_notifier.notify(deploy_info)
270
+ end
271
+
272
+ # Merges +context+ with the current context.
273
+ #
274
+ # The context will be attached to the notice object upon a notify call and
275
+ # cleared after it's attached. The context data is attached to the
276
+ # `params/airbrake_context` key.
277
+ #
278
+ # @example
279
+ # class MerryGrocer
280
+ # def load_fruits(fruits)
281
+ # Airbrake.merge_context(fruits: fruits)
282
+ # end
283
+ #
284
+ # def deliver_fruits
285
+ # Airbrake.notify('fruitception')
286
+ # end
287
+ #
288
+ # def load_veggies(veggies)
289
+ # Airbrake.merge_context(veggies: veggies)
290
+ # end
291
+ #
292
+ # def deliver_veggies
293
+ # Airbrake.notify('veggieboom!')
294
+ # end
295
+ # end
296
+ #
297
+ # grocer = MerryGrocer.new
298
+ #
299
+ # # Load some fruits to the context.
300
+ # grocer.load_fruits(%w(mango banana apple))
301
+ #
302
+ # # Deliver the fruits. Note that we are not passing anything,
303
+ # # `deliver_fruits` knows that we loaded something.
304
+ # grocer.deliver_fruits
305
+ #
306
+ # # Load some vegetables and deliver them to Airbrake. Note that the
307
+ # # fruits have been delivered and therefore the grocer doesn't have them
308
+ # # anymore. We merge veggies with the new context.
309
+ # grocer.load_veggies(%w(cabbage carrot onion))
310
+ # grocer.deliver_veggies
311
+ #
312
+ # # The context is empty again, feel free to load more.
313
+ #
314
+ # @param [Hash{Symbol=>Object}] context
315
+ # @return [void]
316
+ def merge_context(context)
317
+ notice_notifier.merge_context(context)
318
+ end
319
+
320
+ # Increments request statistics of a certain +route+ that was invoked on
321
+ # +start_time+ and ended on +end_time+ with +method+, and returned
322
+ # +status_code+.
323
+ #
324
+ # After a certain amount of time (n seconds) the aggregated route
325
+ # information will be sent to Airbrake.
326
+ #
327
+ # @example
328
+ # Airbrake.notify_request(
329
+ # method: 'POST',
330
+ # route: '/thing/:id/create',
331
+ # status_code: 200,
332
+ # func: 'do_stuff',
333
+ # file: 'app/models/foo.rb',
334
+ # line: 452,
335
+ # start_time: timestamp,
336
+ # end_time: Time.now
337
+ # )
338
+ #
339
+ # @param [Hash{Symbol=>Object}] request_info
340
+ # @option request_info [String] :method The HTTP method that was invoked
341
+ # @option request_info [String] :route The route that was invoked
342
+ # @option request_info [Integer] :status_code The respose code that the
343
+ # route returned
344
+ # @option request_info [String] :func The function that called the query
345
+ # (optional)
346
+ # @option request_info [String] :file The file that has the function that
347
+ # called the query (optional)
348
+ # @option request_info [Integer] :line The line that executes the query
349
+ # (optional)
350
+ # @option request_info [Date] :start_time When the request started
351
+ # @option request_info [Time] :end_time When the request ended (optional)
352
+ # @param [Hash] stash What needs to be appeneded to the stash, so it's
353
+ # available in filters
354
+ # @return [void]
355
+ # @since v3.0.0
356
+ # @see Airbrake::PerformanceNotifier#notify
357
+ def notify_request(request_info, stash = {})
358
+ request = Request.new(request_info)
359
+ request.stash.merge!(stash)
360
+ performance_notifier.notify(request)
361
+ end
362
+
363
+ # Increments SQL statistics of a certain +query+ that was invoked on
364
+ # +start_time+ and finished on +end_time+. When +method+ and +route+ are
365
+ # provided, the query is grouped by these parameters.
366
+ #
367
+ # After a certain amount of time (n seconds) the aggregated query
368
+ # information will be sent to Airbrake.
369
+ #
370
+ # @example
371
+ # Airbrake.notify_query(
372
+ # method: 'GET',
373
+ # route: '/things',
374
+ # query: 'SELECT * FROM things',
375
+ # start_time: timestamp,
376
+ # end_time: Time.now
377
+ # )
378
+ #
379
+ # @param [Hash{Symbol=>Object}] query_info
380
+ # @option request_info [String] :method The HTTP method that triggered this
381
+ # SQL query (optional)
382
+ # @option request_info [String] :route The route that triggered this SQL
383
+ # query (optional)
384
+ # @option request_info [String] :query The query that was executed
385
+ # @option request_info [Date] :start_time When the query started executing
386
+ # @option request_info [Time] :end_time When the query finished (optional)
387
+ # @param [Hash] stash What needs to be appeneded to the stash, so it's
388
+ # available in filters
389
+ # @return [void]
390
+ # @since v3.2.0
391
+ # @see Airbrake::PerformanceNotifier#notify
392
+ def notify_query(query_info, stash = {})
393
+ query = Query.new(query_info)
394
+ query.stash.merge!(stash)
395
+ performance_notifier.notify(query)
396
+ end
397
+
398
+ # Increments performance breakdown statistics of a certain route.
399
+ #
400
+ # @example
401
+ # Airbrake.notify_request(
402
+ # method: 'POST',
403
+ # route: '/thing/:id/create',
404
+ # response_type: 'json',
405
+ # groups: { db: 24.0, view: 0.4 }, # ms
406
+ # start_time: timestamp,
407
+ # end_time: Time.now
408
+ # )
409
+ #
410
+ # @param [Hash{Symbol=>Object}] breakdown_info
411
+ # @option breakdown_info [String] :method HTTP method
412
+ # @option breakdown_info [String] :route
413
+ # @option breakdown_info [String] :response_type
414
+ # @option breakdown_info [Array<Hash{Symbol=>Float}>] :groups
415
+ # @option breakdown_info [Date] :start_time
416
+ # @param [Hash] stash What needs to be appeneded to the stash, so it's
417
+ # available in filters
418
+ # @return [void]
419
+ # @since v4.2.0
420
+ def notify_performance_breakdown(breakdown_info, stash = {})
421
+ performance_breakdown = PerformanceBreakdown.new(breakdown_info)
422
+ performance_breakdown.stash.merge!(stash)
423
+ performance_notifier.notify(performance_breakdown)
424
+ end
425
+
426
+ # Runs a callback before {.notify_request} or {.notify_query} kicks in. This
427
+ # is useful if you want to ignore specific resources or filter the data the
428
+ # resource contains.
429
+ #
430
+ # @example Ignore all resources
431
+ # Airbrake.add_performance_filter(&:ignore!)
432
+ # @example Filter sensitive data
433
+ # Airbrake.add_performance_filter do |resource|
434
+ # case resource
435
+ # when Airbrake::Query
436
+ # resource.route = '[Filtered]'
437
+ # when Airbrake::Request
438
+ # resource.query = '[Filtered]'
439
+ # end
440
+ # end
441
+ # @example Filter with help of a class
442
+ # class MyFilter
443
+ # def call(resource)
444
+ # # ...
445
+ # end
446
+ # end
447
+ #
448
+ # Airbrake.add_performance_filter(MyFilter.new)
449
+ #
450
+ # @param [#call] filter The filter object
451
+ # @yield [resource] The resource to filter
452
+ # @yieldparam [Airbrake::Query, Airbrake::Request]
453
+ # @yieldreturn [void]
454
+ # @return [void]
455
+ # @since v3.2.0
456
+ # @see Airbrake::PerformanceNotifier#add_filter
457
+ def add_performance_filter(filter = nil, &block)
458
+ performance_notifier.add_filter(filter, &block)
459
+ end
460
+
461
+ # Deletes a filter added via {Airbrake#add_performance_filter}.
462
+ #
463
+ # @example
464
+ # # Add a MyFilter filter (we pass an instance here).
465
+ # Airbrake.add_performance_filter(MyFilter.new)
466
+ #
467
+ # # Delete the filter (we pass class name here).
468
+ # Airbrake.delete_performance_filter(MyFilter)
469
+ #
470
+ # @param [Class] filter_class The class of the filter you want to delete
471
+ # @return [void]
472
+ # @since v3.2.0
473
+ # @note This method cannot delete filters assigned via the Proc form.
474
+ # @see Airbrake::PerformanceNotifier#delete_filter
475
+ def delete_performance_filter(filter_class)
476
+ performance_notifier.delete_filter(filter_class)
477
+ end
478
+
479
+ # Resets all notifiers, including its filters
480
+ # @return [void]
481
+ # @since v4.2.2
482
+ def reset
483
+ close if notice_notifier && configured?
484
+
485
+ self.performance_notifier = PerformanceNotifier.new
486
+ self.notice_notifier = NoticeNotifier.new
487
+ self.deploy_notifier = DeployNotifier.new
488
+ end
489
+
490
+ private
491
+
492
+ def process_config_options(config)
493
+ if config.blacklist_keys.any?
494
+ blacklist = Airbrake::Filters::KeysBlacklist.new(config.blacklist_keys)
495
+ notice_notifier.add_filter(blacklist)
496
+ end
497
+
498
+ if config.whitelist_keys.any?
499
+ whitelist = Airbrake::Filters::KeysWhitelist.new(config.whitelist_keys)
500
+ notice_notifier.add_filter(whitelist)
501
+ end
502
+
503
+ return unless config.root_directory
504
+
505
+ [
506
+ Airbrake::Filters::RootDirectoryFilter,
507
+ Airbrake::Filters::GitRevisionFilter,
508
+ Airbrake::Filters::GitRepositoryFilter,
509
+ Airbrake::Filters::GitLastCheckoutFilter
510
+ ].each do |filter|
511
+ notice_notifier.add_filter(filter.new(config.root_directory))
512
+ end
513
+ end
514
+ end
515
+ end