Skip to content

Commit 12db5a4

Browse files
authored
feat: add aggregated metrics for rails and more (#630)
* feat: add aggregated metrics for rails and more This adds aggregated metrics for the following plugins: * rails * net_http * sidekiq Similar to the Karafka plugin, there is now more configuration: * `rails.insights.events` * `rails.insights.metrics` * `sidekiq.insights.events` * `sidekiq.insights.metrics` * `net_http.insights.events` * `net_http.insights.metrics` Other miscellaneous changes: * Switch Sidekiq histogram metric to gauge instead. * Send totals so we can get proper averages across events.
1 parent 0efe109 commit 12db5a4

File tree

12 files changed

+124
-31
lines changed

12 files changed

+124
-31
lines changed

lib/honeybadger/config/defaults.rb

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class Boolean; end
3232
'Sidekiq::JobRetry::Skip'].map(&:freeze).freeze
3333

3434
IGNORE_EVENTS_DEFAULT = [
35+
{ event_type: 'metric.hb', metric_name: 'duration.sql.active_record', query: /^(begin|commit)( transaction)?$/i },
3536
{ event_type: 'sql.active_record', query: /^(begin|commit)( transaction)?$/i },
3637
{ event_type: 'sql.active_record', query: /(solid_queue|good_job)/i },
3738
{ event_type: 'sql.active_record', name: /^GoodJob/ },
@@ -363,6 +364,36 @@ class Boolean; end
363364
default: 60,
364365
type: Integer
365366
},
367+
:'sidekiq.insights.enabled' => {
368+
description: 'Enable automatic data collection for Sidekiq.',
369+
default: true,
370+
type: Boolean
371+
},
372+
:'sidekiq.insights.events' => {
373+
description: 'Enable automatic event capturing for Sidekiq.',
374+
default: true,
375+
type: Boolean
376+
},
377+
:'sidekiq.insights.metrics' => {
378+
description: 'Enable automatic metric data collection for Sidekiq.',
379+
default: false,
380+
type: Boolean
381+
},
382+
:'rails.insights.enabled' => {
383+
description: 'Enable automatic data collection for Ruby on Rails.',
384+
default: true,
385+
type: Boolean
386+
},
387+
:'rails.insights.events' => {
388+
description: 'Enable automatic event capturing for Ruby on Rails.',
389+
default: true,
390+
type: Boolean
391+
},
392+
:'rails.insights.metrics' => {
393+
description: 'Enable automatic metric data collection for Ruby on Rails.',
394+
default: false,
395+
type: Boolean
396+
},
366397
:'karafka.insights.enabled' => {
367398
description: 'Enable automatic data collection for Karafka.',
368399
default: true,
@@ -375,14 +406,24 @@ class Boolean; end
375406
},
376407
:'karafka.insights.metrics' => {
377408
description: 'Enable automatic metric data collection for Karafka.',
378-
default: true,
409+
default: false,
379410
type: Boolean
380411
},
381412
:'net_http.insights.enabled' => {
382413
description: 'Allow automatic instrumentation of Net::HTTP requests.',
383414
default: true,
384415
type: Boolean
385416
},
417+
:'net_http.insights.events' => {
418+
description: 'Enable automatic event capturing for Net::HTTP requests.',
419+
default: true,
420+
type: Boolean
421+
},
422+
:'net_http.insights.metrics' => {
423+
description: 'Enable automatic metric data collection for Net::HTTP requests.',
424+
default: false,
425+
type: Boolean
426+
},
386427
:'net_http.insights.full_url' => {
387428
description: 'Record the full request url during instrumentation.',
388429
default: false,

lib/honeybadger/gauge.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def record(value)
1919
def payloads
2020
[
2121
{
22+
total: @total,
2223
min: @min,
2324
max: @max,
2425
avg: @avg,

lib/honeybadger/histogram.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def bins
3434

3535
def payloads
3636
[{
37+
total: @total,
3738
min: @min,
3839
max: @max,
3940
avg: @avg,

lib/honeybadger/instrumentation.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def gauge(name, *args)
134134
elsif block_given?
135135
value = yield
136136
else
137-
value = attributes.delete(:value)
137+
value = attributes.delete(:duration) || attributes.delete(:value)
138138
end
139139

140140
Honeybadger::Gauge.register(registry, name, attributes).tap do |gauge|

lib/honeybadger/notification_subscriber.rb

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
module Honeybadger
55
class NotificationSubscriber
6+
include Honeybadger::InstrumentationHelper
7+
68
def start(name, id, payload)
79
@start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
810
end
@@ -21,7 +23,29 @@ def finish(name, id, payload)
2123
end
2224

2325
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
2549
end
2650

2751
def process?(event, payload)
@@ -109,22 +133,6 @@ def format_payload(payload)
109133
end
110134
end
111135

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-
128136
class ActionMailerSubscriber < NotificationSubscriber
129137
end
130138

lib/honeybadger/plugins/active_job.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ def context(job) # rubocop:disable Metrics/MethodLength
5555

5656
if config.load_plugin_insights?(:active_job)
5757
::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)
5958
end
6059
end
6160
end

lib/honeybadger/plugins/net_http.rb

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ module Honeybadger
77
module Plugins
88
module Net
99
module HTTP
10+
@@hb_config = ::Honeybadger.config
11+
12+
def self.set_hb_config(config)
13+
@@hb_config = config
14+
end
15+
1016
def request(request_data, body = nil, &block)
1117
return super unless started?
1218
return super if hb?
@@ -18,19 +24,26 @@ def request(request_data, body = nil, &block)
1824
status: response_data.code.to_i
1925
}.merge(parsed_uri_data(request_data))
2026

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
2235
end[1] # return the response data only
2336
end
2437

2538
def hb?
26-
address.to_s[/#{Honeybadger.config[:'connection.host'].to_s}/]
39+
address.to_s[/#{@@hb_config[:'connection.host'].to_s}/]
2740
end
2841

2942
def parsed_uri_data(request_data)
3043
uri = request_data.uri || build_uri(request_data)
3144
{}.tap do |uri_data|
3245
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']
3447
end
3548
end
3649

@@ -43,6 +56,7 @@ def build_uri(request_data)
4356
requirement { config.load_plugin_insights?(:net_http) }
4457

4558
execution do
59+
Honeybadger::Plugins::Net::HTTP.set_hb_config(config)
4660
::Net::HTTP.send(:prepend, Honeybadger::Plugins::Net::HTTP)
4761
end
4862
end

lib/honeybadger/plugins/sidekiq.rb

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,14 @@ def call(worker, msg, queue, &block)
3838
raise
3939
ensure
4040
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
4244

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
4549
end
4650
end
4751
end
@@ -55,7 +59,9 @@ def call(worker, msg, queue, _redis)
5559
queue: queue
5660
}
5761

58-
Honeybadger.event('enqueue.sidekiq', context)
62+
if Honeybadger.config.load_plugin_insights_events?(:sidekiq)
63+
Honeybadger.event('enqueue.sidekiq', context)
64+
end
5965

6066
yield
6167
end

spec/unit/honeybadger/gauge_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010

1111
before { metric.record(1) }
1212

13-
it { should eq [{ avg: 1.0, latest: 1, max: 1, min: 1 }] }
13+
it { should eq [{ total: 1, avg: 1.0, latest: 1, max: 1, min: 1 }] }
1414
end
1515
end

spec/unit/honeybadger/histogram_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
it do
1414
should eq [
1515
{
16+
total: 1,
1617
avg: 1.0,
1718
latest: 1,
1819
max: 1,

0 commit comments

Comments
 (0)