airbrake-ruby 4.6.0

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