honeybadger 5.19.1 → 5.22.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 845eb3bb6f21901ea870b5da7124decc51c01a1f9902330608eb7c9d7d0f0e89
4
- data.tar.gz: '0388e922e33e0b116d23df7c53ef3b4d9bf047f319ce60f2548881a8328df758'
3
+ metadata.gz: 40136d87c293fee9689b5f11926a15bc98c225f34f6a7b75e4fcd8ede1cacc5f
4
+ data.tar.gz: '028f8549e380de8c248013f0ed7846f5fea5018f71c8ac1e0bc310a72d695fdd'
5
5
  SHA512:
6
- metadata.gz: 17282da0e828893e7b3bee7b34d9da1566eb1eba7843491f8b036db5e846a8641adcef3d923a78d817e9ab5f465b495b5e37aaba87b2d9c78eb9b6c5ce2b8dec
7
- data.tar.gz: 6bf054b890c44226db7d4b9d3eed2b2ed5f848a59b882fa0cd1ce0b788d488c492f05b937f673007d41ef2f05298470664efe94531e5a1447ba21a127b7cb929
6
+ metadata.gz: 1404e62cbc7b74d49e3a3881791c5cada2ab820e447efb0c7d2c83994cd81d54b32ca614b52a9fc47606d368c65c950ab5159e7e9342e7214c9d891a132d12e6
7
+ data.tar.gz: 737dc2abee3fef27ecd93034e6914eb0a6439a6fdcb35e803ceeb2bb74161f0dd19b08fc1661ea78723b7ecd6a8b984c8a1f2733288c63d446ca1c68fa3b335f
data/CHANGELOG.md CHANGED
@@ -1,6 +1,44 @@
1
1
  # Change Log
2
2
 
3
3
 
4
+ ## [5.22.0](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.21.0...v5.22.0) (2024-11-14)
5
+
6
+
7
+ ### Features
8
+
9
+ * only allow for insights to be enabled when public ([#642](https://github.com/honeybadger-io/honeybadger-ruby/issues/642)) ([2d3ab26](https://github.com/honeybadger-io/honeybadger-ruby/commit/2d3ab26ca3673b5b01082d55737bf7907c02e799))
10
+
11
+ ## [5.21.0](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.20.1...v5.21.0) (2024-11-14)
12
+
13
+
14
+ ### Features
15
+
16
+ * add event stats for sidekiq and sq ([#638](https://github.com/honeybadger-io/honeybadger-ruby/issues/638)) ([0d15bf5](https://github.com/honeybadger-io/honeybadger-ruby/commit/0d15bf543d4c425a2d9f6000d328dc0e71261647))
17
+ * disable all workers in rails console ([#636](https://github.com/honeybadger-io/honeybadger-ruby/issues/636)) ([d0bcb42](https://github.com/honeybadger-io/honeybadger-ruby/commit/d0bcb4278ad84d02e3706766269582067bc76e29))
18
+ * emit an event for karafka stats ([#637](https://github.com/honeybadger-io/honeybadger-ruby/issues/637)) ([e7e74b5](https://github.com/honeybadger-io/honeybadger-ruby/commit/e7e74b51324f7c718b1adc634cee4233d0c91813))
19
+
20
+ ## [5.20.1](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.20.0...v5.20.1) (2024-11-13)
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * cli test for rails 8 ([#639](https://github.com/honeybadger-io/honeybadger-ruby/issues/639)) ([ec74cfd](https://github.com/honeybadger-io/honeybadger-ruby/commit/ec74cfd95519cd49509ff63fb34a7673f5c76323))
26
+
27
+ ## [5.20.0](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.19.2...v5.20.0) (2024-11-08)
28
+
29
+
30
+ ### Features
31
+
32
+ * add aggregated metrics for rails and more ([#630](https://github.com/honeybadger-io/honeybadger-ruby/issues/630)) ([12db5a4](https://github.com/honeybadger-io/honeybadger-ruby/commit/12db5a4d44a9597c0999d32a150283799d856d66))
33
+
34
+ ## [5.19.2](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.19.1...v5.19.2) (2024-11-05)
35
+
36
+
37
+ ### Bug Fixes
38
+
39
+ * don't run middleware in Sinatra when not configured ([#629](https://github.com/honeybadger-io/honeybadger-ruby/issues/629)) ([d84c2b1](https://github.com/honeybadger-io/honeybadger-ruby/commit/d84c2b15f61b1a019be6329981d8f5323115d1e9))
40
+ * pin rspec-its gem to 1.3.1 ([#631](https://github.com/honeybadger-io/honeybadger-ruby/issues/631)) ([5f78b8a](https://github.com/honeybadger-io/honeybadger-ruby/commit/5f78b8adfb1b86c233bf9ad3ddb69dc702341e11))
41
+
4
42
  ## [5.19.1](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.19.0...v5.19.1) (2024-11-02)
5
43
 
6
44
 
@@ -377,6 +377,16 @@ module Honeybadger
377
377
  true
378
378
  end
379
379
 
380
+ # Stops the Honeybadger Insights related services.
381
+ #
382
+ # @example
383
+ # Honeybadger.stop_insights # => nil
384
+ def stop_insights(force = false)
385
+ events_worker&.shutdown(force)
386
+ metrics_worker&.shutdown(force)
387
+ true
388
+ end
389
+
380
390
  # Sends event to events backend
381
391
  #
382
392
  # @example
@@ -142,6 +142,7 @@ module Honeybadger
142
142
  end
143
143
  CONTROLLER
144
144
 
145
+ ::Rails.application.try(:reload_routes_unless_loaded)
145
146
  ::Rails.application.routes.tap do |r|
146
147
  # RouteSet#disable_clear_and_finalize prevents existing routes from
147
148
  # being cleared. We'll set it back to the original value when we're
@@ -32,6 +32,7 @@ module Honeybadger
32
32
  'Sidekiq::JobRetry::Skip'].map(&:freeze).freeze
33
33
 
34
34
  IGNORE_EVENTS_DEFAULT = [
35
+ { event_type: 'metric.hb', metric_name: 'duration.sql.active_record', query: /^(begin|commit)( transaction)?$/i },
35
36
  { event_type: 'sql.active_record', query: /^(begin|commit)( transaction)?$/i },
36
37
  { event_type: 'sql.active_record', query: /(solid_queue|good_job)/i },
37
38
  { event_type: 'sql.active_record', name: /^GoodJob/ },
@@ -343,6 +344,21 @@ module Honeybadger
343
344
  default: true,
344
345
  type: Boolean
345
346
  },
347
+ :'sidekiq.insights.enabled' => {
348
+ description: 'Enable automatic data collection for Sidekiq.',
349
+ default: true,
350
+ type: Boolean
351
+ },
352
+ :'sidekiq.insights.events' => {
353
+ description: 'Enable automatic event capturing for Sidekiq.',
354
+ default: true,
355
+ type: Boolean
356
+ },
357
+ :'sidekiq.insights.metrics' => {
358
+ description: 'Enable automatic metric data collection for Sidekiq.',
359
+ default: false,
360
+ type: Boolean
361
+ },
346
362
  :'sidekiq.insights.cluster_collection' => {
347
363
  description: 'Collect cluster based metrics for Sidekiq.',
348
364
  default: true,
@@ -350,9 +366,24 @@ module Honeybadger
350
366
  },
351
367
  :'sidekiq.insights.collection_interval' => {
352
368
  description: 'The frequency in which Sidekiq cluster metrics are sampled.',
353
- default: 60,
369
+ default: 5,
354
370
  type: Integer
355
371
  },
372
+ :'solid_queue.insights.enabled' => {
373
+ description: 'Enable automatic data collection for SolidQueue.',
374
+ default: true,
375
+ type: Boolean
376
+ },
377
+ :'solid_queue.insights.events' => {
378
+ description: 'Enable automatic event capturing for SolidQueue.',
379
+ default: true,
380
+ type: Boolean
381
+ },
382
+ :'solid_queue.insights.metrics' => {
383
+ description: 'Enable automatic metric data collection for SolidQueue.',
384
+ default: false,
385
+ type: Boolean
386
+ },
356
387
  :'solid_queue.insights.cluster_collection' => {
357
388
  description: 'Collect cluster based metrics for SolidQueue.',
358
389
  default: true,
@@ -360,9 +391,24 @@ module Honeybadger
360
391
  },
361
392
  :'solid_queue.insights.collection_interval' => {
362
393
  description: 'The frequency in which SolidQueue cluster metrics are sampled.',
363
- default: 60,
394
+ default: 5,
364
395
  type: Integer
365
396
  },
397
+ :'rails.insights.enabled' => {
398
+ description: 'Enable automatic data collection for Ruby on Rails.',
399
+ default: true,
400
+ type: Boolean
401
+ },
402
+ :'rails.insights.events' => {
403
+ description: 'Enable automatic event capturing for Ruby on Rails.',
404
+ default: true,
405
+ type: Boolean
406
+ },
407
+ :'rails.insights.metrics' => {
408
+ description: 'Enable automatic metric data collection for Ruby on Rails.',
409
+ default: false,
410
+ type: Boolean
411
+ },
366
412
  :'karafka.insights.enabled' => {
367
413
  description: 'Enable automatic data collection for Karafka.',
368
414
  default: true,
@@ -375,7 +421,7 @@ module Honeybadger
375
421
  },
376
422
  :'karafka.insights.metrics' => {
377
423
  description: 'Enable automatic metric data collection for Karafka.',
378
- default: true,
424
+ default: false,
379
425
  type: Boolean
380
426
  },
381
427
  :'net_http.insights.enabled' => {
@@ -383,6 +429,16 @@ module Honeybadger
383
429
  default: true,
384
430
  type: Boolean
385
431
  },
432
+ :'net_http.insights.events' => {
433
+ description: 'Enable automatic event capturing for Net::HTTP requests.',
434
+ default: true,
435
+ type: Boolean
436
+ },
437
+ :'net_http.insights.metrics' => {
438
+ description: 'Enable automatic metric data collection for Net::HTTP requests.',
439
+ default: false,
440
+ type: Boolean
441
+ },
386
442
  :'net_http.insights.full_url' => {
387
443
  description: 'Record the full request url during instrumentation.',
388
444
  default: false,
@@ -289,7 +289,7 @@ module Honeybadger
289
289
  end
290
290
 
291
291
  def insights_enabled?
292
- !!self[:'insights.enabled']
292
+ public? && !!self[:'insights.enabled']
293
293
  end
294
294
 
295
295
  def cluster_collection?(name)
@@ -19,6 +19,7 @@ module Honeybadger
19
19
  def payloads
20
20
  [
21
21
  {
22
+ total: @total,
22
23
  min: @min,
23
24
  max: @max,
24
25
  avg: @avg,
@@ -34,6 +34,7 @@ module Honeybadger
34
34
 
35
35
  def payloads
36
36
  [{
37
+ total: @total,
37
38
  min: @min,
38
39
  max: @max,
39
40
  avg: @avg,
@@ -34,7 +34,10 @@ module Honeybadger
34
34
  end
35
35
 
36
36
  console do
37
- Honeybadger::Agent.instance.config[:'insights.enabled'] = Honeybadger::Agent.instance.config[:'insights.console.enabled']
37
+ unless Honeybadger::Agent.instance.config[:'insights.enabled'] = Honeybadger::Agent.instance.config[:'insights.console.enabled']
38
+ Honeybadger::Agent.instance.config.logger.debug("Rails console detected, shutting down Honeybadger Insights workers.")
39
+ Honeybadger::Agent.instance.stop_insights
40
+ end
38
41
  end
39
42
  end
40
43
  end
@@ -31,8 +31,8 @@ module Honeybadger
31
31
  if config[:'exceptions.enabled']
32
32
  # These two must come before the ErrorNotifier, since an error/response
33
33
  # passes through middleware from inner to outer (bottom to top)
34
- install_honeybadger_middleware(Honeybadger::Rack::UserFeedback)
35
- install_honeybadger_middleware(Honeybadger::Rack::UserInformer)
34
+ install_honeybadger_middleware(Honeybadger::Rack::UserFeedback) if config[:'feedback.enabled']
35
+ install_honeybadger_middleware(Honeybadger::Rack::UserInformer) if config[:'user_informer.enabled']
36
36
  install_honeybadger_middleware(Honeybadger::Rack::ErrorNotifier)
37
37
  end
38
38
  end
@@ -134,7 +134,7 @@ module Honeybadger
134
134
  elsif block_given?
135
135
  value = yield
136
136
  else
137
- value = attributes.delete(:value)
137
+ value = attributes.delete(:duration) || attributes.delete(:value)
138
138
  end
139
139
 
140
140
  Honeybadger::Gauge.register(registry, name, attributes).tap do |gauge|
@@ -70,6 +70,10 @@ module Honeybadger
70
70
  #
71
71
  # @param event [Karafka::Core::Monitoring::Event]
72
72
  def on_statistics_emitted(event)
73
+ if Honeybadger.config.load_plugin_insights_events?(:karafka)
74
+ Honeybadger.event("statistics_emitted.karafka", event.payload)
75
+ end
76
+
73
77
  return unless Honeybadger.config.load_plugin_insights_metrics?(:karafka)
74
78
 
75
79
  statistics = event[:statistics]
@@ -138,9 +142,7 @@ module Honeybadger
138
142
  def on_connection_listener_fetch_loop_received(event)
139
143
  time_taken = event[:time]
140
144
  messages_count = event[:messages_buffer].size
141
-
142
145
  consumer_group_id = event[:subscription_group].consumer_group.id
143
-
144
146
  extra_tags = { consumer_group: consumer_group_id }
145
147
 
146
148
  if Honeybadger.config.load_plugin_insights_metrics?(:karafka)
@@ -191,9 +193,10 @@ module Honeybadger
191
193
  #
192
194
  # @param event [Karafka::Core::Monitoring::Event]
193
195
  def on_consumer_#{after}(event)
194
- tags = consumer_tags(event.payload[:caller])
195
-
196
- increment_counter('consumer_#{name}', value: 1, **tags)
196
+ if Honeybadger.config.load_plugin_insights_metrics?(:karafka)
197
+ tags = consumer_tags(event.payload[:caller])
198
+ increment_counter('consumer_#{name}', value: 1, **tags)
199
+ end
197
200
  end
198
201
  RUBY
199
202
  end
@@ -3,6 +3,8 @@ require 'honeybadger/util/sql'
3
3
 
4
4
  module Honeybadger
5
5
  class NotificationSubscriber
6
+ include Honeybadger::InstrumentationHelper
7
+
6
8
  def start(name, id, payload)
7
9
  @start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
8
10
  end
@@ -21,7 +23,29 @@ module Honeybadger
21
23
  end
22
24
 
23
25
  def record(name, payload)
24
- Honeybadger.event(name, payload)
26
+ if Honeybadger.config.load_plugin_insights_events?(:rails)
27
+ Honeybadger.event(name, payload)
28
+ end
29
+
30
+ if Honeybadger.config.load_plugin_insights_metrics?(:rails)
31
+ metric_source 'rails'
32
+ record_metrics(name, payload)
33
+ end
34
+ end
35
+
36
+ def record_metrics(name, payload)
37
+ case name
38
+ when 'sql.active_record'
39
+ gauge('duration.sql.active_record', value: payload[:duration], **payload.slice(:query))
40
+ when 'process_action.action_controller'
41
+ gauge('duration.process_action.action_controller', value: payload[:duration], **payload.slice(:method, :controller, :action, :format, :status))
42
+ gauge('db_runtime.process_action.action_controller', value: payload[:db_runtime], **payload.slice(:method, :controller, :action, :format, :status))
43
+ gauge('view_runtime.process_action.action_controller', value: payload[:view_runtime], **payload.slice(:method, :controller, :action, :format, :status))
44
+ when 'perform.active_job'
45
+ gauge('duration.perform.active_job', value: payload[:duration], **payload.slice(:job_class, :queue_name))
46
+ when /^cache_.*.active_support$/
47
+ gauge("duration.#{name}", value: payload[:duration], **payload.slice(:store, :key))
48
+ end
25
49
  end
26
50
 
27
51
  def process?(event, payload)
@@ -109,22 +133,6 @@ module Honeybadger
109
133
  end
110
134
  end
111
135
 
112
- class ActiveJobMetricsSubscriber < NotificationSubscriber
113
- include Honeybadger::InstrumentationHelper
114
-
115
- def format_payload(payload)
116
- {
117
- job_class: payload[:job].class.to_s,
118
- queue_name: payload[:job].queue_name
119
- }
120
- end
121
-
122
- def record(name, payload)
123
- metric_source 'active_job'
124
- histogram name, { bins: [30, 60, 120, 300, 1800, 3600, 21_600] }.merge(payload)
125
- end
126
- end
127
-
128
136
  class ActionMailerSubscriber < NotificationSubscriber
129
137
  end
130
138
 
@@ -55,7 +55,6 @@ module Honeybadger
55
55
 
56
56
  if config.load_plugin_insights?(:active_job)
57
57
  ::ActiveSupport::Notifications.subscribe(/(enqueue_at|enqueue|enqueue_retry|enqueue_all|perform|retry_stopped|discard)\.active_job/, Honeybadger::ActiveJobSubscriber.new)
58
- ::ActiveSupport::Notifications.subscribe('perform.active_job', Honeybadger::ActiveJobMetricsSubscriber.new)
59
58
  end
60
59
  end
61
60
  end
@@ -7,6 +7,12 @@ module Honeybadger
7
7
  module Plugins
8
8
  module Net
9
9
  module HTTP
10
+ @@hb_config = ::Honeybadger.config
11
+
12
+ def self.set_hb_config(config)
13
+ @@hb_config = config
14
+ end
15
+
10
16
  def request(request_data, body = nil, &block)
11
17
  return super unless started?
12
18
  return super if hb?
@@ -18,19 +24,26 @@ module Honeybadger
18
24
  status: response_data.code.to_i
19
25
  }.merge(parsed_uri_data(request_data))
20
26
 
21
- Honeybadger.event('request.net_http', context)
27
+ if @@hb_config.load_plugin_insights_events?(:net_http)
28
+ Honeybadger.event('request.net_http', context)
29
+ end
30
+
31
+ if @@hb_config.load_plugin_insights_metrics?(:net_http)
32
+ context.delete(:url)
33
+ Honeybadger.gauge('duration.request', context.merge(metric_source: 'net_http'))
34
+ end
22
35
  end[1] # return the response data only
23
36
  end
24
37
 
25
38
  def hb?
26
- address.to_s[/#{Honeybadger.config[:'connection.host'].to_s}/]
39
+ address.to_s[/#{@@hb_config[:'connection.host'].to_s}/]
27
40
  end
28
41
 
29
42
  def parsed_uri_data(request_data)
30
43
  uri = request_data.uri || build_uri(request_data)
31
44
  {}.tap do |uri_data|
32
45
  uri_data[:host] = uri.host
33
- uri_data[:url] = uri.to_s if Honeybadger.config[:'net_http.insights.full_url']
46
+ uri_data[:url] = uri.to_s if @@hb_config[:'net_http.insights.full_url']
34
47
  end
35
48
  end
36
49
 
@@ -43,6 +56,7 @@ module Honeybadger
43
56
  requirement { config.load_plugin_insights?(:net_http) }
44
57
 
45
58
  execution do
59
+ Honeybadger::Plugins::Net::HTTP.set_hb_config(config)
46
60
  ::Net::HTTP.send(:prepend, Honeybadger::Plugins::Net::HTTP)
47
61
  end
48
62
  end
@@ -38,10 +38,14 @@ module Honeybadger
38
38
  raise
39
39
  ensure
40
40
  context.merge!(duration: duration, status: status)
41
- Honeybadger.event('perform.sidekiq', context)
41
+ if Honeybadger.config.load_plugin_insights_events?(:sidekiq)
42
+ Honeybadger.event('perform.sidekiq', context)
43
+ end
42
44
 
43
- metric_source 'sidekiq'
44
- histogram 'perform', { bins: [30, 60, 120, 300, 1800, 3600, 21_600] }.merge(context.slice(:worker, :queue, :duration))
45
+ if Honeybadger.config.load_plugin_insights_metrics?(:sidekiq)
46
+ metric_source 'sidekiq'
47
+ gauge 'perform', context.slice(:worker, :queue, :duration)
48
+ end
45
49
  end
46
50
  end
47
51
  end
@@ -55,7 +59,9 @@ module Honeybadger
55
59
  queue: queue
56
60
  }
57
61
 
58
- Honeybadger.event('enqueue.sidekiq', context)
62
+ if Honeybadger.config.load_plugin_insights_events?(:sidekiq)
63
+ Honeybadger.event('enqueue.sidekiq', context)
64
+ end
59
65
 
60
66
  yield
61
67
  end
@@ -161,47 +167,67 @@ module Honeybadger
161
167
  end
162
168
  end
163
169
 
170
+ collect_sidekiq_stats = -> do
171
+ stats = ::Sidekiq::Stats.new
172
+ data = stats.as_json
173
+ data[:queues] = {}
174
+
175
+ ::Sidekiq::Queue.all.each do |queue|
176
+ data[:queues][queue.name] ||= {}
177
+ data[:queues][queue.name][:latency] = (queue.latency * 1000).ceil
178
+ data[:queues][queue.name][:depth] = queue.size
179
+ end
180
+
181
+ Hash.new(0).tap do |busy_counts|
182
+ ::Sidekiq::Workers.new.each do |_pid, _tid, work|
183
+ payload = work.respond_to?(:payload) ? work.payload : work["payload"]
184
+ payload = JSON.parse(payload) if payload.is_a?(String)
185
+ busy_counts[payload["queue"]] += 1
186
+ end
187
+ end.each do |queue_name, busy_count|
188
+ data[:queues][queue_name] ||= {}
189
+ data[:queues][queue_name][:busy] = busy_count
190
+ end
191
+
192
+ processes = ::Sidekiq::ProcessSet.new.to_enum(:each).to_a
193
+ data[:capacity] = processes.map { |process| process["concurrency"] }.sum
194
+
195
+ process_utilizations = processes.map do |process|
196
+ next unless process["concurrency"].to_f > 0
197
+ process["busy"] / process["concurrency"].to_f
198
+ end.compact
199
+
200
+ if process_utilizations.any?
201
+ utilization = process_utilizations.sum / process_utilizations.length.to_f
202
+ data[:utilization] = utilization
203
+ end
204
+
205
+ data
206
+ end
207
+
164
208
  collect do
165
209
  if config.cluster_collection?(:sidekiq) && (leader_checker.nil? || leader_checker.collect?)
166
- metric_source 'sidekiq'
167
-
168
- stats = ::Sidekiq::Stats.new
169
-
170
- gauge 'active_workers', ->{ stats.workers_size }
171
- gauge 'active_processes', ->{ stats.processes_size }
172
- gauge 'jobs_processed', ->{ stats.processed }
173
- gauge 'jobs_failed', ->{ stats.failed }
174
- gauge 'jobs_scheduled', ->{ stats.scheduled_size }
175
- gauge 'jobs_enqueued', ->{ stats.enqueued }
176
- gauge 'jobs_dead', ->{ stats.dead_size }
177
- gauge 'jobs_retry', ->{ stats.retry_size }
178
-
179
- ::Sidekiq::Queue.all.each do |queue|
180
- gauge 'queue_latency', { queue: queue.name }, ->{ (queue.latency * 1000).ceil }
181
- gauge 'queue_depth', { queue: queue.name }, ->{ queue.size }
182
- end
210
+ stats = collect_sidekiq_stats.call
183
211
 
184
- Hash.new(0).tap do |busy_counts|
185
- ::Sidekiq::Workers.new.each do |_pid, _tid, work|
186
- payload = work.respond_to?(:payload) ? work.payload : work["payload"]
187
- payload = JSON.parse(payload) if payload.is_a?(String)
188
- busy_counts[payload["queue"]] += 1
189
- end
190
- end.each do |queue_name, busy_count|
191
- gauge 'queue_busy', { queue: queue_name }, ->{ busy_count }
212
+ if Honeybadger.config.load_plugin_insights_events?(:sidekiq)
213
+ Honeybadger.event('stats.sidekiq', stats.except('stats').merge(stats['stats']))
192
214
  end
193
215
 
194
- processes = ::Sidekiq::ProcessSet.new.to_enum(:each).to_a
195
- gauge 'capacity', ->{ processes.map { |process| process["concurrency"] }.sum }
216
+ if Honeybadger.config.load_plugin_insights_metrics?(:sidekiq)
217
+ metric_source 'sidekiq'
218
+
219
+ stats['stats'].each do |name, value|
220
+ gauge name, value: value
221
+ end
196
222
 
197
- process_utilizations = processes.map do |process|
198
- next unless process["concurrency"].to_f > 0
199
- process["busy"] / process["concurrency"].to_f
200
- end.compact
223
+ stats[:queues].each do |queue_name, data|
224
+ data.each do |key, value|
225
+ gauge "queue_#{key}", queue: queue_name, value: value
226
+ end
227
+ end
201
228
 
202
- if process_utilizations.any?
203
- utilization = process_utilizations.sum / process_utilizations.length.to_f
204
- gauge 'utilization', ->{ utilization }
229
+ gauge 'capacity', value: stats[:capacity] if stats[:capacity]
230
+ gauge 'utilization', value: stats[:utilization] if stats[:utilization]
205
231
  end
206
232
  end
207
233
  end
@@ -4,20 +4,46 @@ module Honeybadger
4
4
  Plugin.register :solid_queue do
5
5
  requirement { config.load_plugin_insights?(:solid_queue) && defined?(::SolidQueue) }
6
6
 
7
+ collect_solid_queue_stats = -> do
8
+ data = {}
9
+ data[:stats] = {
10
+ jobs_in_progress: ::SolidQueue::ClaimedExecution.count,
11
+ jobs_blocked: ::SolidQueue::BlockedExecution.count,
12
+ jobs_failed: ::SolidQueue::FailedExecution.count,
13
+ jobs_scheduled: ::SolidQueue::ScheduledExecution.count,
14
+ jobs_processed: ::SolidQueue::Job.where.not(finished_at: nil).count,
15
+ active_workers: ::SolidQueue::Process.where(kind: "Worker").count,
16
+ active_dispatchers: ::SolidQueue::Process.where(kind: "Dispatcher").count
17
+ }
18
+
19
+ data[:queues] = {}
20
+
21
+ ::SolidQueue::Queue.all.each do |queue|
22
+ data[:queues][queue.name] = { depth: queue.size }
23
+ end
24
+
25
+ data
26
+ end
27
+
7
28
  collect do
29
+ stats = collect_solid_queue_stats.call
30
+
8
31
  if config.cluster_collection?(:solid_queue)
9
- metric_source 'solid_queue'
10
-
11
- gauge 'jobs_in_progress', ->{ ::SolidQueue::ClaimedExecution.count }
12
- gauge 'jobs_blocked', ->{ ::SolidQueue::BlockedExecution.count }
13
- gauge 'jobs_failed', ->{ ::SolidQueue::FailedExecution.count }
14
- gauge 'jobs_scheduled', ->{ ::SolidQueue::ScheduledExecution.count }
15
- gauge 'jobs_processed', ->{ ::SolidQueue::Job.where.not(finished_at: nil).count }
16
- gauge 'active_workers', ->{ ::SolidQueue::Process.where(kind: "Worker").count }
17
- gauge 'active_dispatchers', ->{ ::SolidQueue::Process.where(kind: "Dispatcher").count }
18
-
19
- ::SolidQueue::Queue.all.each do |queue|
20
- gauge 'queue_depth', { queue: queue.name }, ->{ queue.size }
32
+ if Honeybadger.config.load_plugin_insights_events?(:solid_queue)
33
+ Honeybadger.event('stats.solid_queue', stats.except(:stats).merge(stats[:stats]))
34
+ end
35
+
36
+ if Honeybadger.config.load_plugin_insights_metrics?(:solid_queue)
37
+ metric_source 'solid_queue'
38
+ stats[:stats].each do |stat_name, value|
39
+ gauge stat_name, value: value
40
+ end
41
+
42
+ stats[:queues].each do |queue_name, data|
43
+ data.each do |key, value|
44
+ gauge "queue_#{key}", queue: queue_name, value: value
45
+ end
46
+ end
21
47
  end
22
48
  end
23
49
  end
@@ -1,4 +1,4 @@
1
1
  module Honeybadger
2
2
  # The current String Honeybadger version.
3
- VERSION = '5.19.1'.freeze
3
+ VERSION = '5.22.0'.freeze
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: honeybadger
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.19.1
4
+ version: 5.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Honeybadger Industries LLC
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-02 00:00:00.000000000 Z
11
+ date: 2024-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logger
@@ -194,7 +194,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
194
  - !ruby/object:Gem::Version
195
195
  version: '0'
196
196
  requirements: []
197
- rubygems_version: 3.5.16
197
+ rubygems_version: 3.5.22
198
198
  signing_key:
199
199
  specification_version: 4
200
200
  summary: Error reports you can be happy about.