celerbrake-ruby 0.1.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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/lib/celerbrake-ruby/async_sender.rb +57 -0
  3. data/lib/celerbrake-ruby/backlog.rb +123 -0
  4. data/lib/celerbrake-ruby/backtrace.rb +197 -0
  5. data/lib/celerbrake-ruby/benchmark.rb +39 -0
  6. data/lib/celerbrake-ruby/code_hunk.rb +51 -0
  7. data/lib/celerbrake-ruby/config/processor.rb +77 -0
  8. data/lib/celerbrake-ruby/config/validator.rb +97 -0
  9. data/lib/celerbrake-ruby/config.rb +291 -0
  10. data/lib/celerbrake-ruby/context.rb +51 -0
  11. data/lib/celerbrake-ruby/deploy_notifier.rb +36 -0
  12. data/lib/celerbrake-ruby/file_cache.rb +54 -0
  13. data/lib/celerbrake-ruby/filter_chain.rb +112 -0
  14. data/lib/celerbrake-ruby/filters/context_filter.rb +28 -0
  15. data/lib/celerbrake-ruby/filters/dependency_filter.rb +32 -0
  16. data/lib/celerbrake-ruby/filters/exception_attributes_filter.rb +46 -0
  17. data/lib/celerbrake-ruby/filters/gem_root_filter.rb +34 -0
  18. data/lib/celerbrake-ruby/filters/git_last_checkout_filter.rb +92 -0
  19. data/lib/celerbrake-ruby/filters/git_repository_filter.rb +73 -0
  20. data/lib/celerbrake-ruby/filters/git_revision_filter.rb +68 -0
  21. data/lib/celerbrake-ruby/filters/keys_allowlist.rb +48 -0
  22. data/lib/celerbrake-ruby/filters/keys_blocklist.rb +49 -0
  23. data/lib/celerbrake-ruby/filters/keys_filter.rb +159 -0
  24. data/lib/celerbrake-ruby/filters/root_directory_filter.rb +29 -0
  25. data/lib/celerbrake-ruby/filters/sql_filter.rb +128 -0
  26. data/lib/celerbrake-ruby/filters/system_exit_filter.rb +24 -0
  27. data/lib/celerbrake-ruby/filters/thread_filter.rb +93 -0
  28. data/lib/celerbrake-ruby/grouppable.rb +12 -0
  29. data/lib/celerbrake-ruby/hash_keyable.rb +37 -0
  30. data/lib/celerbrake-ruby/ignorable.rb +43 -0
  31. data/lib/celerbrake-ruby/inspectable.rb +39 -0
  32. data/lib/celerbrake-ruby/loggable.rb +34 -0
  33. data/lib/celerbrake-ruby/mergeable.rb +12 -0
  34. data/lib/celerbrake-ruby/monotonic_time.rb +48 -0
  35. data/lib/celerbrake-ruby/nested_exception.rb +59 -0
  36. data/lib/celerbrake-ruby/notice.rb +157 -0
  37. data/lib/celerbrake-ruby/notice_notifier.rb +142 -0
  38. data/lib/celerbrake-ruby/performance_breakdown.rb +52 -0
  39. data/lib/celerbrake-ruby/performance_notifier.rb +177 -0
  40. data/lib/celerbrake-ruby/promise.rb +110 -0
  41. data/lib/celerbrake-ruby/query.rb +59 -0
  42. data/lib/celerbrake-ruby/queue.rb +65 -0
  43. data/lib/celerbrake-ruby/remote_settings/callback.rb +44 -0
  44. data/lib/celerbrake-ruby/remote_settings/settings_data.rb +116 -0
  45. data/lib/celerbrake-ruby/remote_settings.rb +128 -0
  46. data/lib/celerbrake-ruby/request.rb +48 -0
  47. data/lib/celerbrake-ruby/response.rb +125 -0
  48. data/lib/celerbrake-ruby/stashable.rb +15 -0
  49. data/lib/celerbrake-ruby/stat.rb +66 -0
  50. data/lib/celerbrake-ruby/sync_sender.rb +145 -0
  51. data/lib/celerbrake-ruby/tdigest.rb +379 -0
  52. data/lib/celerbrake-ruby/thread_pool.rb +139 -0
  53. data/lib/celerbrake-ruby/time_truncate.rb +17 -0
  54. data/lib/celerbrake-ruby/timed_trace.rb +56 -0
  55. data/lib/celerbrake-ruby/truncator.rb +121 -0
  56. data/lib/celerbrake-ruby/version.rb +16 -0
  57. data/lib/celerbrake-ruby.rb +592 -0
  58. metadata +251 -0
@@ -0,0 +1,16 @@
1
+ # We use Semantic Versioning v2.0.0
2
+ # More information: http://semver.org/
3
+ module Celerbrake
4
+ # @return [String] the library version
5
+ # @api public
6
+ CELERBRAKE_RUBY_VERSION = '0.1.0'.freeze
7
+
8
+ # @return [Hash{Symbol=>String}] the information about the notifier library
9
+ # @since v5.0.0
10
+ # @api public
11
+ NOTIFIER_INFO = {
12
+ name: 'celerbrake-ruby'.freeze,
13
+ version: Celerbrake::CELERBRAKE_RUBY_VERSION,
14
+ url: 'https://github.com/celerbrake/celerbrake-ruby'.freeze,
15
+ }.freeze
16
+ end
@@ -0,0 +1,592 @@
1
+ require 'net/https'
2
+ require 'logger'
3
+ require 'json'
4
+ require 'set'
5
+ require 'socket'
6
+ require 'time'
7
+
8
+ require 'celerbrake-ruby/version'
9
+ require 'celerbrake-ruby/loggable'
10
+ require 'celerbrake-ruby/stashable'
11
+ require 'celerbrake-ruby/mergeable'
12
+ require 'celerbrake-ruby/grouppable'
13
+ require 'celerbrake-ruby/config'
14
+ require 'celerbrake-ruby/config/validator'
15
+ require 'celerbrake-ruby/config/processor'
16
+ require 'celerbrake-ruby/remote_settings/callback'
17
+ require 'celerbrake-ruby/remote_settings/settings_data'
18
+ require 'celerbrake-ruby/remote_settings'
19
+ require 'celerbrake-ruby/promise'
20
+ require 'celerbrake-ruby/thread_pool'
21
+ require 'celerbrake-ruby/response'
22
+ require 'celerbrake-ruby/sync_sender'
23
+ require 'celerbrake-ruby/async_sender'
24
+ require 'celerbrake-ruby/nested_exception'
25
+ require 'celerbrake-ruby/ignorable'
26
+ require 'celerbrake-ruby/inspectable'
27
+ require 'celerbrake-ruby/notice'
28
+ require 'celerbrake-ruby/backtrace'
29
+ require 'celerbrake-ruby/truncator'
30
+ require 'celerbrake-ruby/filters/keys_filter'
31
+ require 'celerbrake-ruby/filters/keys_allowlist'
32
+ require 'celerbrake-ruby/filters/keys_blocklist'
33
+ require 'celerbrake-ruby/filters/gem_root_filter'
34
+ require 'celerbrake-ruby/filters/system_exit_filter'
35
+ require 'celerbrake-ruby/filters/root_directory_filter'
36
+ require 'celerbrake-ruby/filters/thread_filter'
37
+ require 'celerbrake-ruby/filters/context_filter'
38
+ require 'celerbrake-ruby/filters/exception_attributes_filter'
39
+ require 'celerbrake-ruby/filters/dependency_filter'
40
+ require 'celerbrake-ruby/filters/git_revision_filter'
41
+ require 'celerbrake-ruby/filters/git_repository_filter'
42
+ require 'celerbrake-ruby/filters/git_last_checkout_filter'
43
+ require 'celerbrake-ruby/filters/sql_filter'
44
+ require 'celerbrake-ruby/filter_chain'
45
+ require 'celerbrake-ruby/code_hunk'
46
+ require 'celerbrake-ruby/file_cache'
47
+ require 'celerbrake-ruby/hash_keyable'
48
+ require 'celerbrake-ruby/performance_notifier'
49
+ require 'celerbrake-ruby/notice_notifier'
50
+ require 'celerbrake-ruby/deploy_notifier'
51
+ require 'celerbrake-ruby/stat'
52
+ require 'celerbrake-ruby/time_truncate'
53
+ require 'celerbrake-ruby/tdigest'
54
+ require 'celerbrake-ruby/query'
55
+ require 'celerbrake-ruby/request'
56
+ require 'celerbrake-ruby/performance_breakdown'
57
+ require 'celerbrake-ruby/benchmark'
58
+ require 'celerbrake-ruby/monotonic_time'
59
+ require 'celerbrake-ruby/timed_trace'
60
+ require 'celerbrake-ruby/queue'
61
+ require 'celerbrake-ruby/context'
62
+ require 'celerbrake-ruby/backlog'
63
+
64
+ # Celerbrake is a thin wrapper around instances of the notifier classes (such as
65
+ # notice, performance & deploy notifiers). It creates a way to access them via a
66
+ # consolidated global interface.
67
+ #
68
+ # Prior to using it, you must {configure} it.
69
+ #
70
+ # @example
71
+ # Celerbrake.configure do |c|
72
+ # c.project_id = 113743
73
+ # c.project_key = 'fd04e13d806a90f96614ad8e529b2822'
74
+ # end
75
+ #
76
+ # Celerbrake.notify('Oops!')
77
+ #
78
+ # @since v1.0.0
79
+ # @api public
80
+ # rubocop:disable Metrics/ModuleLength
81
+ module Celerbrake
82
+ # The general error that this library uses when it wants to raise.
83
+ Error = Class.new(StandardError)
84
+
85
+ # @return [String] the label to be prepended to the log output
86
+ LOG_LABEL = '**Celerbrake:'.freeze
87
+
88
+ # @return [Boolean] true if current Ruby is JRuby. The result is used for
89
+ # special cases where we need to work around older implementations
90
+ JRUBY = (RUBY_ENGINE == 'jruby')
91
+
92
+ # @return [Boolean] true if this Ruby supports safe levels and tainting,
93
+ # to guard against using deprecated or unsupported features.
94
+ HAS_SAFE_LEVEL = (
95
+ RUBY_ENGINE == 'ruby' &&
96
+ Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7')
97
+ )
98
+
99
+ class << self
100
+ # @since v4.2.3
101
+ # @api private
102
+ attr_writer :performance_notifier
103
+
104
+ # @since v4.2.3
105
+ # @api private
106
+ attr_writer :notice_notifier
107
+
108
+ # @since v4.2.3
109
+ # @api private
110
+ attr_writer :deploy_notifier
111
+
112
+ # Configures the Celerbrake notifier.
113
+ #
114
+ # @example
115
+ # Celerbrake.configure do |c|
116
+ # c.project_id = 113743
117
+ # c.project_key = 'fd04e13d806a90f96614ad8e529b2822'
118
+ # end
119
+ #
120
+ # @yield [config]
121
+ # @yieldparam config [Celerbrake::Config]
122
+ # @return [void]
123
+ def configure
124
+ yield config = Celerbrake::Config.instance
125
+ Celerbrake::Loggable.instance = config.logger
126
+
127
+ config_processor = Celerbrake::Config::Processor.new(config)
128
+
129
+ config_processor.process_blocklist(notice_notifier)
130
+ config_processor.process_allowlist(notice_notifier)
131
+
132
+ @remote_settings ||= config_processor.process_remote_configuration
133
+
134
+ config_processor.add_filters(notice_notifier)
135
+ end
136
+
137
+ # @since v4.2.3
138
+ # @api private
139
+ def performance_notifier
140
+ @performance_notifier ||= PerformanceNotifier.new
141
+ end
142
+
143
+ # @since v4.2.3
144
+ # @api private
145
+ def notice_notifier
146
+ @notice_notifier ||= NoticeNotifier.new
147
+ end
148
+
149
+ # @since v4.2.3
150
+ # @api private
151
+ def deploy_notifier
152
+ @deploy_notifier ||= DeployNotifier.new
153
+ end
154
+
155
+ # @return [Boolean] true if the notifier was configured, false otherwise
156
+ # @since v2.3.0
157
+ def configured?
158
+ @notice_notifier && @notice_notifier.configured?
159
+ end
160
+
161
+ # Sends an exception to Celerbrake asynchronously.
162
+ #
163
+ # @example Sending an exception
164
+ # Celerbrake.notify(RuntimeError.new('Oops!'))
165
+ # @example Sending a string
166
+ # # Converted to RuntimeError.new('Oops!') internally
167
+ # Celerbrake.notify('Oops!')
168
+ # @example Sending a Notice
169
+ # notice = celerbrake.build_notice(RuntimeError.new('Oops!'))
170
+ # celerbrake.notify(notice)
171
+ #
172
+ # @param [Exception, String, Celerbrake::Notice] exception The exception to be
173
+ # sent to Celerbrake
174
+ # @param [Hash] params The additional payload to be sent to Celerbrake. Can
175
+ # contain any values. The provided values will be displayed in the Params
176
+ # tab in your project's dashboard
177
+ # @yield [notice] The notice to filter
178
+ # @yieldparam [Celerbrake::Notice]
179
+ # @yieldreturn [void]
180
+ # @return [Celerbrake::Promise]
181
+ # @see .notify_sync
182
+ def notify(exception, params = {}, &block)
183
+ notice_notifier.notify(exception, params, &block)
184
+ end
185
+
186
+ # Sends an exception to Celerbrake synchronously.
187
+ #
188
+ # @example
189
+ # Celerbrake.notify_sync('App crashed!')
190
+ # #=> {"id"=>"123", "url"=>"https://celerbrake.com/locate/321"}
191
+ #
192
+ # @param [Exception, String, Celerbrake::Notice] exception The exception to be
193
+ # sent to Celerbrake
194
+ # @param [Hash] params The additional payload to be sent to Celerbrake. Can
195
+ # contain any values. The provided values will be displayed in the Params
196
+ # tab in your project's dashboard
197
+ # @yield [notice] The notice to filter
198
+ # @yieldparam [Celerbrake::Notice]
199
+ # @yieldreturn [void]
200
+ # @return [Celerbrake::Promise] the reponse from the server
201
+ # @see .notify
202
+ def notify_sync(exception, params = {}, &block)
203
+ notice_notifier.notify_sync(exception, params, &block)
204
+ end
205
+
206
+ # Runs a callback before {.notify} or {.notify_sync} kicks in. This is
207
+ # useful if you want to ignore specific notices or filter the data the
208
+ # notice contains.
209
+ #
210
+ # @example Ignore all notices
211
+ # Celerbrake.add_filter(&:ignore!)
212
+ # @example Ignore based on some condition
213
+ # Celerbrake.add_filter do |notice|
214
+ # notice.ignore! if notice[:error_class] == 'StandardError'
215
+ # end
216
+ # @example Ignore with help of a class
217
+ # class MyFilter
218
+ # def call(notice)
219
+ # # ...
220
+ # end
221
+ # end
222
+ #
223
+ # Celerbrake.add_filter(MyFilter.new)
224
+ #
225
+ # @param [#call] filter The filter object
226
+ # @yield [notice] The notice to filter
227
+ # @yieldparam [Celerbrake::Notice]
228
+ # @yieldreturn [void]
229
+ # @return [void]
230
+ def add_filter(filter = nil, &block)
231
+ notice_notifier.add_filter(filter, &block)
232
+ end
233
+
234
+ # Deletes a filter added via {Celerbrake#add_filter}.
235
+ #
236
+ # @example
237
+ # # Add a MyFilter filter (we pass an instance here).
238
+ # Celerbrake.add_filter(MyFilter.new)
239
+ #
240
+ # # Delete the filter (we pass class name here).
241
+ # Celerbrake.delete_filter(MyFilter)
242
+ #
243
+ # @param [Class] filter_class The class of the filter you want to delete
244
+ # @return [void]
245
+ # @since v3.1.0
246
+ # @note This method cannot delete filters assigned via the Proc form.
247
+ def delete_filter(filter_class)
248
+ notice_notifier.delete_filter(filter_class)
249
+ end
250
+
251
+ # Builds an Celerbrake notice. This is useful, if you want to add or modify a
252
+ # value only for a specific notice. When you're done modifying the notice,
253
+ # send it with {.notify} or {.notify_sync}.
254
+ #
255
+ # @example
256
+ # notice = celerbrake.build_notice('App crashed!')
257
+ # notice[:params][:username] = user.name
258
+ # celerbrake.notify_sync(notice)
259
+ #
260
+ # @param [Exception] exception The exception on top of which the notice
261
+ # should be built
262
+ # @param [Hash] params The additional params attached to the notice
263
+ # @return [Celerbrake::Notice] the notice built with help of the given
264
+ # arguments
265
+ def build_notice(exception, params = {})
266
+ notice_notifier.build_notice(exception, params)
267
+ end
268
+
269
+ # Makes the notice notifier a no-op, which means you cannot use the
270
+ # {.notify} and {.notify_sync} methods anymore. It also stops the notice
271
+ # notifier's worker threads.
272
+ #
273
+ # @example
274
+ # Celerbrake.close
275
+ # Celerbrake.notify('App crashed!') #=> raises Celerbrake::Error
276
+ #
277
+ # @return [nil]
278
+ # rubocop:disable Style/IfUnlessModifier
279
+ def close
280
+ if defined?(@notice_notifier) && @notice_notifier
281
+ @notice_notifier.close
282
+ end
283
+
284
+ if defined?(@performance_notifier) && @performance_notifier
285
+ @performance_notifier.close
286
+ end
287
+
288
+ if defined?(@remote_settings) && @remote_settings
289
+ @remote_settings.stop_polling
290
+ end
291
+
292
+ nil
293
+ end
294
+ # rubocop:enable Style/IfUnlessModifier
295
+
296
+ # Pings the Celerbrake Deploy API endpoint about the occurred deploy.
297
+ #
298
+ # @param [Hash{Symbol=>String}] deploy_info The params for the API
299
+ # @option deploy_info [Symbol] :environment
300
+ # @option deploy_info [Symbol] :username
301
+ # @option deploy_info [Symbol] :repository
302
+ # @option deploy_info [Symbol] :revision
303
+ # @option deploy_info [Symbol] :version
304
+ # @return [void]
305
+ def notify_deploy(deploy_info)
306
+ deploy_notifier.notify(deploy_info)
307
+ end
308
+
309
+ # Merges +context+ with the current context.
310
+ #
311
+ # The context will be attached to the notice object upon a notify call and
312
+ # cleared after it's attached. The context data is attached to the
313
+ # `params/celerbrake_context` key.
314
+ #
315
+ # @example
316
+ # class MerryGrocer
317
+ # def load_fruits(fruits)
318
+ # Celerbrake.merge_context(fruits: fruits)
319
+ # end
320
+ #
321
+ # def deliver_fruits
322
+ # Celerbrake.notify('fruitception')
323
+ # end
324
+ #
325
+ # def load_veggies(veggies)
326
+ # Celerbrake.merge_context(veggies: veggies)
327
+ # end
328
+ #
329
+ # def deliver_veggies
330
+ # Celerbrake.notify('veggieboom!')
331
+ # end
332
+ # end
333
+ #
334
+ # grocer = MerryGrocer.new
335
+ #
336
+ # # Load some fruits to the context.
337
+ # grocer.load_fruits(%w(mango banana apple))
338
+ #
339
+ # # Deliver the fruits. Note that we are not passing anything,
340
+ # # `deliver_fruits` knows that we loaded something.
341
+ # grocer.deliver_fruits
342
+ #
343
+ # # Load some vegetables and deliver them to Celerbrake. Note that the
344
+ # # fruits have been delivered and therefore the grocer doesn't have them
345
+ # # anymore. We merge veggies with the new context.
346
+ # grocer.load_veggies(%w(cabbage carrot onion))
347
+ # grocer.deliver_veggies
348
+ #
349
+ # # The context is empty again, feel free to load more.
350
+ #
351
+ # @param [Hash{Symbol=>Object}] context
352
+ # @return [void]
353
+ def merge_context(context)
354
+ notice_notifier.merge_context(context)
355
+ end
356
+
357
+ # Increments request statistics of a certain +route+ invoked with +method+,
358
+ # which returned +status_code+.
359
+ #
360
+ # After a certain amount of time (n seconds) the aggregated route
361
+ # information will be sent to Celerbrake.
362
+ #
363
+ # @example
364
+ # Celerbrake.notify_request(
365
+ # method: 'POST',
366
+ # route: '/thing/:id/create',
367
+ # status_code: 200,
368
+ # timing: 123.45 # ms
369
+ # )
370
+ #
371
+ # @param [Hash{Symbol=>Object}] request_info
372
+ # @option request_info [String] :method The HTTP method that was invoked
373
+ # @option request_info [String] :route The route that was invoked
374
+ # @option request_info [Integer] :status_code The response code that the
375
+ # route returned
376
+ # @option request_info [Float] :timing How much time it took to process the
377
+ # request (in ms)
378
+ # @param [Hash] stash What needs to be appeneded to the stash, so it's
379
+ # available in filters
380
+ # @return [void]
381
+ # @since v3.0.0
382
+ # @see Celerbrake::PerformanceNotifier#notify
383
+ def notify_request(request_info, stash = {})
384
+ request = Request.new(**request_info)
385
+ request.stash.merge!(stash)
386
+ performance_notifier.notify(request)
387
+ end
388
+
389
+ # Synchronously increments request statistics of a certain +route+ invoked
390
+ # with +method+, which returned +status_code+.
391
+ # @since v4.10.0
392
+ # @see .notify_request
393
+ def notify_request_sync(request_info, stash = {})
394
+ request = Request.new(**request_info)
395
+ request.stash.merge!(stash)
396
+ performance_notifier.notify_sync(request)
397
+ end
398
+
399
+ # Increments SQL statistics of a certain +query+. When +method+ and +route+
400
+ # are provided, the query is grouped by these parameters.
401
+ #
402
+ # After a certain amount of time (n seconds) the aggregated query
403
+ # information will be sent to Celerbrake.
404
+ #
405
+ # @example
406
+ # Celerbrake.notify_query(
407
+ # method: 'GET',
408
+ # route: '/things',
409
+ # query: 'SELECT * FROM things',
410
+ # func: 'do_stuff',
411
+ # file: 'app/models/foo.rb',
412
+ # line: 452,
413
+ # timing: 123.45 # ms
414
+ # )
415
+ #
416
+ # @param [Hash{Symbol=>Object}] query_info
417
+ # @option query_info [String] :method The HTTP method that triggered this
418
+ # SQL query (optional)
419
+ # @option query_info [String] :route The route that triggered this SQL
420
+ # query (optional)
421
+ # @option query_info [String] :query The query that was executed
422
+ # @option request_info [String] :func The function that called the query
423
+ # (optional)
424
+ # @option request_info [String] :file The file that has the function that
425
+ # called the query (optional)
426
+ # @option request_info [Integer] :line The line that executes the query
427
+ # (optional)
428
+ # @option query_info [Float] :timing How much time it took to process the
429
+ # query (in ms)
430
+ # @param [Hash] stash What needs to be appeneded to the stash, so it's
431
+ # available in filters
432
+ # @return [void]
433
+ # @since v3.2.0
434
+ # @see Celerbrake::PerformanceNotifier#notify
435
+ def notify_query(query_info, stash = {})
436
+ query = Query.new(**query_info)
437
+ query.stash.merge!(stash)
438
+ performance_notifier.notify(query)
439
+ end
440
+
441
+ # Synchronously increments SQL statistics of a certain +query+. When
442
+ # +method+ and +route+ are provided, the query is grouped by these
443
+ # parameters.
444
+ # @since v4.10.0
445
+ # @see .notify_query
446
+ def notify_query_sync(query_info, stash = {})
447
+ query = Query.new(**query_info)
448
+ query.stash.merge!(stash)
449
+ performance_notifier.notify_sync(query)
450
+ end
451
+
452
+ # Increments performance breakdown statistics of a certain route.
453
+ #
454
+ # @example
455
+ # Celerbrake.notify_performance_breakdown(
456
+ # method: 'POST',
457
+ # route: '/thing/:id/create',
458
+ # response_type: 'json',
459
+ # groups: { db: 24.0, view: 0.4 }, # ms
460
+ # timing: 123.45 # ms
461
+ # )
462
+ #
463
+ # @param [Hash{Symbol=>Object}] breakdown_info
464
+ # @option breakdown_info [String] :method HTTP method
465
+ # @option breakdown_info [String] :route
466
+ # @option breakdown_info [String] :response_type
467
+ # @option breakdown_info [Array<Hash{Symbol=>Float}>] :groups
468
+ # @option breakdown_info [Float] :timing How much time it took to process
469
+ # the performance breakdown (in ms)
470
+ # @param [Hash] stash What needs to be appeneded to the stash, so it's
471
+ # available in filters
472
+ # @return [void]
473
+ # @since v4.2.0
474
+ def notify_performance_breakdown(breakdown_info, stash = {})
475
+ performance_breakdown = PerformanceBreakdown.new(**breakdown_info)
476
+ performance_breakdown.stash.merge!(stash)
477
+ performance_notifier.notify(performance_breakdown)
478
+ end
479
+
480
+ # Increments performance breakdown statistics of a certain route
481
+ # synchronously.
482
+ # @since v4.10.0
483
+ # @see .notify_performance_breakdown
484
+ def notify_performance_breakdown_sync(breakdown_info, stash = {})
485
+ performance_breakdown = PerformanceBreakdown.new(**breakdown_info)
486
+ performance_breakdown.stash.merge!(stash)
487
+ performance_notifier.notify_sync(performance_breakdown)
488
+ end
489
+
490
+ # Increments statistics of a certain queue (worker).
491
+ #
492
+ # @example
493
+ # Celerbrake.notify_queue(
494
+ # queue: 'emails',
495
+ # error_count: 1,
496
+ # groups: { redis: 24.0, sql: 0.4 } # ms
497
+ # )
498
+ #
499
+ # @param [Hash{Symbol=>Object}] queue_info
500
+ # @option queue_info [String] :queue The name of the queue/worker
501
+ # @option queue_info [Integer] :error_count How many times this worker
502
+ # failed
503
+ # @option queue_info [Array<Hash{Symbol=>Float}>] :groups Where the job
504
+ # spent its time
505
+ # @option breakdown_info [Float] :timing How much time it took to process
506
+ # the queue (in ms)
507
+ # @param [Hash] stash What needs to be appended to the stash, so it's
508
+ # available in filters
509
+ # @return [void]
510
+ # @since v4.9.0
511
+ # @see .notify_queue_sync
512
+ def notify_queue(queue_info, stash = {})
513
+ queue = Queue.new(**queue_info)
514
+ queue.stash.merge!(stash)
515
+ performance_notifier.notify(queue)
516
+ end
517
+
518
+ # Increments statistics of a certain queue (worker) synchronously.
519
+ # @since v4.10.0
520
+ # @see .notify_queue
521
+ def notify_queue_sync(queue_info, stash = {})
522
+ queue = Queue.new(**queue_info)
523
+ queue.stash.merge!(stash)
524
+ performance_notifier.notify_sync(queue)
525
+ end
526
+
527
+ # Runs a callback before {.notify_request}, {.notify_query}, {.notify_queue}
528
+ # or {.notify_performance_breakdown} kicks in. This is useful if you want to
529
+ # ignore specific metrics or filter the data the metric contains.
530
+ #
531
+ # @example Ignore all metrics
532
+ # Celerbrake.add_performance_filter(&:ignore!)
533
+ # @example Filter sensitive data
534
+ # Celerbrake.add_performance_filter do |metric|
535
+ # case metric
536
+ # when Celerbrake::Query
537
+ # metric.route = '[Filtered]'
538
+ # when Celerbrake::Request
539
+ # metric.query = '[Filtered]'
540
+ # end
541
+ # end
542
+ # @example Filter with help of a class
543
+ # class MyFilter
544
+ # def call(metric)
545
+ # # ...
546
+ # end
547
+ # end
548
+ #
549
+ # Celerbrake.add_performance_filter(MyFilter.new)
550
+ #
551
+ # @param [#call] filter The filter object
552
+ # @yield [metric] The metric to filter
553
+ # @yieldparam [Celerbrake::Query, Celerbrake::Request]
554
+ # @yieldreturn [void]
555
+ # @return [void]
556
+ # @since v3.2.0
557
+ # @see Celerbrake::PerformanceNotifier#add_filter
558
+ def add_performance_filter(filter = nil, &block)
559
+ performance_notifier.add_filter(filter, &block)
560
+ end
561
+
562
+ # Deletes a filter added via {Celerbrake#add_performance_filter}.
563
+ #
564
+ # @example
565
+ # # Add a MyFilter filter (we pass an instance here).
566
+ # Celerbrake.add_performance_filter(MyFilter.new)
567
+ #
568
+ # # Delete the filter (we pass class name here).
569
+ # Celerbrake.delete_performance_filter(MyFilter)
570
+ #
571
+ # @param [Class] filter_class The class of the filter you want to delete
572
+ # @return [void]
573
+ # @since v3.2.0
574
+ # @note This method cannot delete filters assigned via the Proc form.
575
+ # @see Celerbrake::PerformanceNotifier#delete_filter
576
+ def delete_performance_filter(filter_class)
577
+ performance_notifier.delete_filter(filter_class)
578
+ end
579
+
580
+ # Resets all notifiers, including its filters
581
+ # @return [void]
582
+ # @since v4.2.2
583
+ def reset
584
+ close
585
+
586
+ self.performance_notifier = PerformanceNotifier.new
587
+ self.notice_notifier = NoticeNotifier.new
588
+ self.deploy_notifier = DeployNotifier.new
589
+ end
590
+ end
591
+ end
592
+ # rubocop:enable Metrics/ModuleLength