airbrake-ruby 3.2.2-java

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