airbrake-ruby 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
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