honeybadger 5.18.0 → 5.19.1

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: 7ac625c10c4a54cedc7385e468f6c1ca58b6e70462d53569b0e06e7a71e05375
4
- data.tar.gz: 608e399be30c0193ec3423f9ce61d6a5a6e4c3c6409a48766d164f2c45d6ce50
3
+ metadata.gz: 845eb3bb6f21901ea870b5da7124decc51c01a1f9902330608eb7c9d7d0f0e89
4
+ data.tar.gz: '0388e922e33e0b116d23df7c53ef3b4d9bf047f319ce60f2548881a8328df758'
5
5
  SHA512:
6
- metadata.gz: e88fdc901c68e8ac52a3668eab830103ee57d1dd2180c52a21f22c4177d74d47495570682d0b7c60fa26560cbcbc083428d9274daa8fab9c8d608dea19cea59f
7
- data.tar.gz: 60f864a5799746ec90aba7576eed46d2321443114b9307bea759c314dc6783e7fc2361b2883d3c4662de3506649a9c151f19328f31a198c9a8f4e10fcf09e265
6
+ metadata.gz: 17282da0e828893e7b3bee7b34d9da1566eb1eba7843491f8b036db5e846a8641adcef3d923a78d817e9ab5f465b495b5e37aaba87b2d9c78eb9b6c5ce2b8dec
7
+ data.tar.gz: 6bf054b890c44226db7d4b9d3eed2b2ed5f848a59b882fa0cd1ce0b788d488c492f05b937f673007d41ef2f05298470664efe94531e5a1447ba21a127b7cb929
data/CHANGELOG.md CHANGED
@@ -1,6 +1,20 @@
1
1
  # Change Log
2
2
 
3
3
 
4
+ ## [5.19.1](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.19.0...v5.19.1) (2024-11-02)
5
+
6
+
7
+ ### Bug Fixes
8
+
9
+ * don't raise errors in instrumentation metrics ([#627](https://github.com/honeybadger-io/honeybadger-ruby/issues/627)) ([1231dae](https://github.com/honeybadger-io/honeybadger-ruby/commit/1231dae0c48a2fab4cdaa14f7308ab3e0b44c287))
10
+
11
+ ## [5.19.0](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.18.0...v5.19.0) (2024-10-29)
12
+
13
+
14
+ ### Features
15
+
16
+ * improved karafka plugin for insights ([#625](https://github.com/honeybadger-io/honeybadger-ruby/issues/625)) ([21880fc](https://github.com/honeybadger-io/honeybadger-ruby/commit/21880fc92493abb044ba3c0d64299ad8b92ad5f3))
17
+
4
18
  ## [5.18.0](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.17.0...v5.18.0) (2024-10-25)
5
19
 
6
20
 
@@ -363,6 +363,21 @@ module Honeybadger
363
363
  default: 60,
364
364
  type: Integer
365
365
  },
366
+ :'karafka.insights.enabled' => {
367
+ description: 'Enable automatic data collection for Karafka.',
368
+ default: true,
369
+ type: Boolean
370
+ },
371
+ :'karafka.insights.events' => {
372
+ description: 'Enable automatic event capturing for Karafka.',
373
+ default: true,
374
+ type: Boolean
375
+ },
376
+ :'karafka.insights.metrics' => {
377
+ description: 'Enable automatic metric data collection for Karafka.',
378
+ default: true,
379
+ type: Boolean
380
+ },
366
381
  :'net_http.insights.enabled' => {
367
382
  description: 'Allow automatic instrumentation of Net::HTTP requests.',
368
383
  default: true,
@@ -309,6 +309,20 @@ module Honeybadger
309
309
  !!self[:"#{name}.insights.enabled"]
310
310
  end
311
311
 
312
+ def load_plugin_insights_events?(name)
313
+ return false unless insights_enabled?
314
+ return false unless load_plugin_insights?(name)
315
+ return true if self[:"#{name}.insights.events"].nil?
316
+ !!self[:"#{name}.insights.events"]
317
+ end
318
+
319
+ def load_plugin_insights_metrics?(name)
320
+ return false unless insights_enabled?
321
+ return false unless load_plugin_insights?(name)
322
+ return true if self[:"#{name}.insights.metrics"].nil?
323
+ !!self[:"#{name}.insights.metrics"]
324
+ end
325
+
312
326
  def root_regexp
313
327
  return @root_regexp if @root_regexp
314
328
  return nil if @no_root
@@ -9,6 +9,15 @@ module Honeybadger
9
9
  return unless value
10
10
 
11
11
  @samples += 1
12
+
13
+ @total ||= 0
14
+ @total = @total + value
15
+
16
+ @min = value if @min.nil? || @min > value
17
+ @max = value if @max.nil? || @max < value
18
+ @avg = @total.to_f / @samples
19
+ @latest = value
20
+
12
21
  @bin_counts ||= Hash.new(0)
13
22
  @bin_counts[find_bin(value)] += 1
14
23
  end
@@ -25,6 +34,10 @@ module Honeybadger
25
34
 
26
35
  def payloads
27
36
  [{
37
+ min: @min,
38
+ max: @max,
39
+ avg: @avg,
40
+ latest: @latest,
28
41
  bins: (bins + [INFINITY]).map { |bin| [bin.to_f, @bin_counts[bin]] }
29
42
  }]
30
43
  end
@@ -47,66 +47,102 @@ module Honeybadger
47
47
  def time(name, *args)
48
48
  attributes = extract_attributes(args)
49
49
  callable = extract_callable(args)
50
- duration = attributes.delete(:duration)
50
+ value = nil
51
51
 
52
52
  if callable
53
- duration = monotonic_timer{ callable.call }[0]
53
+ value = monotonic_timer{ callable.call }[0]
54
54
  elsif block_given?
55
- duration = monotonic_timer{ yield }[0]
55
+ value = monotonic_timer{ yield }[0]
56
+ else
57
+ value = attributes.delete(:duration) || attributes.delete(:value)
56
58
  end
57
59
 
58
- raise 'No duration found' if duration.nil?
59
-
60
60
  Honeybadger::Timer.register(registry, name, attributes).tap do |timer|
61
- timer.record(duration)
61
+ if value.nil?
62
+ agent.config.logger.warn("No value found for timer #{name}. Must specify either duration or value. Skipping.")
63
+ else
64
+ timer.record(value)
65
+ end
62
66
  end
63
67
  end
64
68
 
65
69
  def histogram(name, *args)
66
70
  attributes = extract_attributes(args)
67
71
  callable = extract_callable(args)
68
- duration = attributes.delete(:duration)
72
+ value = nil
69
73
 
70
74
  if callable
71
- duration = monotonic_timer{ callable.call }[0]
75
+ value = monotonic_timer{ callable.call }[0]
72
76
  elsif block_given?
73
- duration = monotonic_timer{ yield }[0]
77
+ value = monotonic_timer{ yield }[0]
78
+ else
79
+ value = attributes.delete(:duration) || attributes.delete(:value)
74
80
  end
75
81
 
76
- raise 'No duration found' if duration.nil?
77
-
78
82
  Honeybadger::Histogram.register(registry, name, attributes).tap do |histogram|
79
- histogram.record(duration)
83
+ if value.nil?
84
+ agent.config.logger.warn("No value found for histogram #{name}. Must specify either duration or value. Skipping.")
85
+ else
86
+ histogram.record(value)
87
+ end
80
88
  end
81
89
  end
82
90
 
83
91
  def increment_counter(name, *args)
84
92
  attributes = extract_attributes(args)
85
- by = extract_callable(args)&.call || attributes.delete(:by) || 1
86
- by = yield if block_given?
93
+ callable = extract_callable(args)
94
+ value = nil
95
+
96
+ if callable
97
+ value = callable.call
98
+ elsif block_given?
99
+ value = yield
100
+ else
101
+ value = attributes.delete(:by) || attributes.delete(:value) || 1
102
+ end
87
103
 
88
104
  Honeybadger::Counter.register(registry, name, attributes).tap do |counter|
89
- counter.count(by)
105
+ counter.count(value)
90
106
  end
91
107
  end
92
108
 
93
109
  def decrement_counter(name, *args)
94
110
  attributes = extract_attributes(args)
95
- by = extract_callable(args)&.call || attributes.delete(:by) || 1
96
- by = yield if block_given?
111
+ callable = extract_callable(args)
112
+ value = nil
113
+
114
+ if callable
115
+ value = callable.call
116
+ elsif block_given?
117
+ value = yield
118
+ else
119
+ value = attributes.delete(:by) || attributes.delete(:value) || 1
120
+ end
97
121
 
98
122
  Honeybadger::Counter.register(registry, name, attributes).tap do |counter|
99
- counter.count(by * -1)
123
+ counter.count(value * -1)
100
124
  end
101
125
  end
102
126
 
103
127
  def gauge(name, *args)
104
128
  attributes = extract_attributes(args)
105
- value = extract_callable(args)&.call || attributes.delete(:value)
106
- value = yield if block_given?
129
+ callable = extract_callable(args)
130
+ value = nil
131
+
132
+ if callable
133
+ value = callable.call
134
+ elsif block_given?
135
+ value = yield
136
+ else
137
+ value = attributes.delete(:value)
138
+ end
107
139
 
108
140
  Honeybadger::Gauge.register(registry, name, attributes).tap do |gauge|
109
- gauge.record(value)
141
+ if value.nil?
142
+ agent.config.logger.warn("No value found for gauge #{name}. Must specify value. Skipping.")
143
+ else
144
+ gauge.record(value)
145
+ end
110
146
  end
111
147
  end
112
148
 
@@ -56,7 +56,7 @@ module Honeybadger
56
56
  metric_instrumentation.time(name, attributes, ->{ callable.call })
57
57
  elsif block_given?
58
58
  metric_instrumentation.time(name, attributes, ->{ yield })
59
- elsif attributes.keys.include?(:duration)
59
+ else
60
60
  metric_instrumentation.time(name, attributes)
61
61
  end
62
62
  end
@@ -68,38 +68,44 @@ module Honeybadger
68
68
  metric_instrumentation.histogram(name, attributes, ->{ callable.call })
69
69
  elsif block_given?
70
70
  metric_instrumentation.histogram(name, attributes, ->{ yield })
71
- elsif attributes.keys.include?(:duration)
71
+ else
72
72
  metric_instrumentation.histogram(name, attributes)
73
73
  end
74
74
  end
75
75
 
76
76
  def increment_counter(name, *args)
77
77
  attributes = extract_attributes(args)
78
- by = extract_callable(args)&.call || attributes.delete(:by) || 1
79
- if block_given?
78
+ callable = extract_callable(args)
79
+ if callable
80
+ metric_instrumentation.increment_counter(name, attributes, ->{ callable.call })
81
+ elsif block_given?
80
82
  metric_instrumentation.increment_counter(name, attributes, ->{ yield })
81
83
  else
82
- metric_instrumentation.increment_counter(name, attributes.merge(by: by))
84
+ metric_instrumentation.increment_counter(name, attributes)
83
85
  end
84
86
  end
85
87
 
86
88
  def decrement_counter(name, *args)
87
89
  attributes = extract_attributes(args)
88
- by = extract_callable(args)&.call || attributes.delete(:by) || 1
89
- if block_given?
90
+ callable = extract_callable(args)
91
+ if callable
92
+ metric_instrumentation.decrement_counter(name, attributes, ->{ callable.call })
93
+ elsif block_given?
90
94
  metric_instrumentation.decrement_counter(name, attributes, ->{ yield })
91
95
  else
92
- metric_instrumentation.decrement_counter(name, attributes.merge(by: by))
96
+ metric_instrumentation.decrement_counter(name, attributes)
93
97
  end
94
98
  end
95
99
 
96
100
  def gauge(name, *args)
97
101
  attributes = extract_attributes(args)
98
- value = extract_callable(args)&.call || attributes.delete(:value)
99
- if block_given?
102
+ callable = extract_callable(args)
103
+ if callable
104
+ metric_instrumentation.gauge(name, attributes, ->{ callable.call })
105
+ elsif block_given?
100
106
  metric_instrumentation.gauge(name, attributes, ->{ yield })
101
107
  else
102
- metric_instrumentation.gauge(name, attributes.merge(value: value))
108
+ metric_instrumentation.gauge(name, attributes)
103
109
  end
104
110
  end
105
111
 
@@ -0,0 +1,298 @@
1
+ require 'honeybadger/instrumentation_helper'
2
+
3
+ module Honeybadger
4
+ module Karafka
5
+ class ErrorsListener
6
+ # Sends error details to Honeybadger
7
+ #
8
+ # @param event [Karafka::Core::Monitoring::Event]
9
+ def on_error_occurred(event)
10
+ context = {
11
+ type: event[:type]
12
+ }
13
+ tags = ["type:#{event[:type]}"]
14
+
15
+ if (consumer = event.payload[:caller]).respond_to?(:messages)
16
+ messages = consumer.messages
17
+ metadata = messages.metadata
18
+ consumer_group_id = consumer.topic.consumer_group.id
19
+
20
+ context[:topic] = metadata.topic
21
+ context[:partition] = metadata.partition
22
+ context[:consumer_group] = consumer_group_id
23
+ end
24
+
25
+ Honeybadger.notify(event[:error], context: context)
26
+ end
27
+ end
28
+
29
+ class InsightsListener
30
+ include ::Honeybadger::InstrumentationHelper
31
+
32
+ # Value object for storing a single rdkafka metric publishing details
33
+ RdKafkaMetric = Struct.new(:type, :scope, :name, :key_location)
34
+
35
+ # All the rdkafka metrics we want to publish
36
+ #
37
+ # By default we publish quite a lot so this can be tuned
38
+ # Note, that the once with `_d` come from Karafka, not rdkafka or Kafka
39
+ RD_KAFKA_METRICS = [
40
+ # Client metrics
41
+ RdKafkaMetric.new(:increment_counter, :root, 'messages_consumed', 'rxmsgs_d'),
42
+ RdKafkaMetric.new(:increment_counter, :root, 'messages_consumed_bytes', 'rxmsg_bytes'),
43
+
44
+ # Broker metrics
45
+ RdKafkaMetric.new(:increment_counter, :brokers, 'consume_attempts', 'txretries_d'),
46
+ RdKafkaMetric.new(:increment_counter, :brokers, 'consume_errors', 'txerrs_d'),
47
+ RdKafkaMetric.new(:increment_counter, :brokers, 'receive_errors', 'rxerrs_d'),
48
+ RdKafkaMetric.new(:increment_counter, :brokers, 'connection_connects', 'connects_d'),
49
+ RdKafkaMetric.new(:increment_counter, :brokers, 'connection_disconnects', 'disconnects_d'),
50
+ RdKafkaMetric.new(:gauge, :brokers, 'network_latency_avg', %w[rtt avg]),
51
+ RdKafkaMetric.new(:gauge, :brokers, 'network_latency_p95', %w[rtt p95]),
52
+ RdKafkaMetric.new(:gauge, :brokers, 'network_latency_p99', %w[rtt p99]),
53
+
54
+ # Topics metrics
55
+ RdKafkaMetric.new(:gauge, :topics, 'consumer_lags', 'consumer_lag_stored'),
56
+ RdKafkaMetric.new(:gauge, :topics, 'consumer_lags_delta', 'consumer_lag_stored_d')
57
+ ].freeze
58
+
59
+ # Metrics that sum values on topics levels and not on partition levels
60
+ AGGREGATED_RD_KAFKA_METRICS = [
61
+ # Topic aggregated metrics
62
+ RdKafkaMetric.new(:gauge, :topics, 'consumer_aggregated_lag', 'consumer_lag_stored')
63
+ ].freeze
64
+
65
+ def initialize
66
+ metric_source("karafka")
67
+ end
68
+
69
+ # Hooks up to Karafka instrumentation for emitted statistics
70
+ #
71
+ # @param event [Karafka::Core::Monitoring::Event]
72
+ def on_statistics_emitted(event)
73
+ return unless Honeybadger.config.load_plugin_insights_metrics?(:karafka)
74
+
75
+ statistics = event[:statistics]
76
+ consumer_group_id = event[:consumer_group_id]
77
+
78
+ base_tags = { consumer_group: consumer_group_id }
79
+
80
+ RD_KAFKA_METRICS.each do |metric|
81
+ report_metric(metric, statistics, base_tags)
82
+ end
83
+
84
+ report_aggregated_topics_metrics(statistics, consumer_group_id)
85
+ end
86
+
87
+ # Publishes aggregated topic-level metrics that are sum of per partition metrics
88
+ #
89
+ # @param statistics [Hash] hash with all the statistics emitted
90
+ # @param consumer_group_id [String] cg in context which we operate
91
+ def report_aggregated_topics_metrics(statistics, consumer_group_id)
92
+ AGGREGATED_RD_KAFKA_METRICS.each do |metric|
93
+ statistics.fetch('topics').each do |topic_name, topic_values|
94
+ sum = 0
95
+
96
+ topic_values['partitions'].each do |partition_name, partition_statistics|
97
+ next if partition_name == '-1'
98
+ # Skip until lag info is available
99
+ next if partition_statistics['consumer_lag'] == -1
100
+ next if partition_statistics['consumer_lag_stored'] == -1
101
+
102
+ sum += partition_statistics.dig(*metric.key_location)
103
+ end
104
+
105
+ public_send(
106
+ metric.type,
107
+ metric.name,
108
+ value: sum,
109
+ consumer_group: consumer_group_id,
110
+ topic: topic_name
111
+ )
112
+ end
113
+ end
114
+ end
115
+
116
+ # Increases the errors count by 1
117
+ #
118
+ # @param event [Karafka::Core::Monitoring::Event]
119
+ def on_error_occurred(event)
120
+ extra_tags = { type: event[:type] }
121
+
122
+ if event.payload[:caller].respond_to?(:messages)
123
+ extra_tags.merge!(consumer_tags(event.payload[:caller]))
124
+ end
125
+
126
+ if Honeybadger.config.load_plugin_insights_events?(:karafka)
127
+ Honeybadger.event("error.occurred.karafka", error: event[:error], **extra_tags)
128
+ end
129
+
130
+ if Honeybadger.config.load_plugin_insights_metrics?(:karafka)
131
+ increment_counter('error_occurred', value: 1, **extra_tags)
132
+ end
133
+ end
134
+
135
+ # Reports how many messages we've polled and how much time did we spend on it
136
+ #
137
+ # @param event [Karafka::Core::Monitoring::Event]
138
+ def on_connection_listener_fetch_loop_received(event)
139
+ time_taken = event[:time]
140
+ messages_count = event[:messages_buffer].size
141
+
142
+ consumer_group_id = event[:subscription_group].consumer_group.id
143
+
144
+ extra_tags = { consumer_group: consumer_group_id }
145
+
146
+ if Honeybadger.config.load_plugin_insights_metrics?(:karafka)
147
+ histogram('listener_polling_time_taken', value: time_taken, **extra_tags)
148
+ histogram('listener_polling_messages', value: messages_count, **extra_tags)
149
+ end
150
+ end
151
+
152
+ # Here we report majority of things related to processing as we have access to the
153
+ # consumer
154
+ # @param event [Karafka::Core::Monitoring::Event]
155
+ def on_consumer_consumed(event)
156
+ consumer = event.payload[:caller]
157
+ messages = consumer.messages
158
+ metadata = messages.metadata
159
+
160
+ tags = consumer_tags(consumer)
161
+
162
+ if Honeybadger.config.load_plugin_insights_events?(:karafka)
163
+ event_context = tags.merge({
164
+ consumer: consumer.class.name,
165
+ duration: event[:time],
166
+ processing_lag: metadata.processing_lag,
167
+ consumption_lag: metadata.consumption_lag,
168
+ processed: messages.count
169
+ })
170
+ Honeybadger.event("consumer.consumed.karafka", event_context)
171
+ end
172
+
173
+ if Honeybadger.config.load_plugin_insights_metrics?(:karafka)
174
+ increment_counter('consumer_messages', value: messages.count, **tags)
175
+ increment_counter('consumer_batches', value: 1, **tags)
176
+ gauge('consumer_offset', value: metadata.last_offset, **tags)
177
+ histogram('consumer_consumed_time_taken', value: event[:time], **tags)
178
+ histogram('consumer_batch_size', value: messages.count, **tags)
179
+ histogram('consumer_processing_lag', value: metadata.processing_lag, **tags)
180
+ histogram('consumer_consumption_lag', value: metadata.consumption_lag, **tags)
181
+ end
182
+ end
183
+
184
+ {
185
+ revoked: :revoked,
186
+ shutdown: :shutdown,
187
+ ticked: :tick
188
+ }.each do |after, name|
189
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
190
+ # Keeps track of user code execution
191
+ #
192
+ # @param event [Karafka::Core::Monitoring::Event]
193
+ def on_consumer_#{after}(event)
194
+ tags = consumer_tags(event.payload[:caller])
195
+
196
+ increment_counter('consumer_#{name}', value: 1, **tags)
197
+ end
198
+ RUBY
199
+ end
200
+
201
+ # Worker related metrics
202
+ # @param event [Karafka::Core::Monitoring::Event]
203
+ def on_worker_process(event)
204
+ jq_stats = event[:jobs_queue].statistics
205
+
206
+ if Honeybadger.config.load_plugin_insights_metrics?(:karafka)
207
+ gauge('worker_total_threads', value: ::Karafka::App.config.concurrency)
208
+ histogram('worker_processing', value: jq_stats[:busy])
209
+ histogram('worker_enqueued_jobs', value: jq_stats[:enqueued])
210
+ end
211
+ end
212
+
213
+ # We report this metric before and after processing for higher accuracy
214
+ # Without this, the utilization would not be fully reflected
215
+ # @param event [Karafka::Core::Monitoring::Event]
216
+ def on_worker_processed(event)
217
+ jq_stats = event[:jobs_queue].statistics
218
+
219
+ if Honeybadger.config.load_plugin_insights_metrics?(:karafka)
220
+ histogram('worker_processing', value: jq_stats[:busy])
221
+ end
222
+ end
223
+
224
+ private
225
+
226
+ # Reports a given metric statistics to Honeybadger
227
+ # @param metric [RdKafkaMetric] metric value object
228
+ # @param statistics [Hash] hash with all the statistics emitted
229
+ # @param base_tags [Array<String>] base tags we want to start with
230
+ def report_metric(metric, statistics, base_tags)
231
+ case metric.scope
232
+ when :root
233
+ public_send(
234
+ metric.type,
235
+ metric.name,
236
+ value: statistics.fetch(*metric.key_location),
237
+ **base_tags
238
+ )
239
+ when :brokers
240
+ statistics.fetch('brokers').each_value do |broker_statistics|
241
+ # Skip bootstrap nodes
242
+ # Bootstrap nodes have nodeid -1, other nodes have positive
243
+ # node ids
244
+ next if broker_statistics['nodeid'] == -1
245
+
246
+ public_send(
247
+ metric.type,
248
+ metric.name,
249
+ value: broker_statistics.dig(*metric.key_location),
250
+ **base_tags.merge(broker: broker_statistics['nodename'])
251
+ )
252
+ end
253
+ when :topics
254
+ statistics.fetch('topics').each do |topic_name, topic_values|
255
+ topic_values['partitions'].each do |partition_name, partition_statistics|
256
+ next if partition_name == '-1'
257
+ # Skip until lag info is available
258
+ next if partition_statistics['consumer_lag'] == -1
259
+ next if partition_statistics['consumer_lag_stored'] == -1
260
+
261
+ # Skip if we do not own the fetch assignment
262
+ next if partition_statistics['fetch_state'] == 'stopped'
263
+ next if partition_statistics['fetch_state'] == 'none'
264
+
265
+ public_send(
266
+ metric.type,
267
+ metric.name,
268
+ value: partition_statistics.dig(*metric.key_location),
269
+ **base_tags.merge({
270
+ topic: topic_name,
271
+ partition: partition_name
272
+ })
273
+ )
274
+ end
275
+ end
276
+ else
277
+ raise ArgumentError, metric.scope
278
+ end
279
+ end
280
+
281
+ # Builds basic per consumer tags for publication
282
+ #
283
+ # @param consumer [Karafka::BaseConsumer]
284
+ # @return [Array<String>]
285
+ def consumer_tags(consumer)
286
+ messages = consumer.messages
287
+ metadata = messages.metadata
288
+ consumer_group_id = consumer.topic.consumer_group.id
289
+
290
+ {
291
+ topic: metadata.topic,
292
+ partition: metadata.partition,
293
+ consumer_group: consumer_group_id
294
+ }
295
+ end
296
+ end
297
+ end
298
+ end
@@ -6,25 +6,14 @@ module Honeybadger
6
6
  requirement { defined?(::Karafka) && ::Karafka.respond_to?(:monitor) }
7
7
 
8
8
  execution do
9
- ::Karafka.monitor.subscribe("error.occurred") do |event|
10
- Honeybadger.notify(event[:error])
11
- Honeybadger.event("error.occurred.karafka", error: event[:error]) if config.load_plugin_insights?(:karafka)
12
- end
9
+ require 'honeybadger/karafka'
13
10
 
14
- if config.load_plugin_insights?(:karafka)
15
- ::Karafka.monitor.subscribe("consumer.consumed") do |event|
16
- context = {
17
- duration: event.payload[:time],
18
- consumer: event.payload[:caller].class.to_s,
19
- id: event.payload[:caller].id,
20
- topic: event.payload[:caller].messages.metadata.topic,
21
- messages_count: event.payload[:caller].messages.metadata.size,
22
- processing_lag: event.payload[:caller].messages.metadata.processing_lag,
23
- partition: event.payload[:caller].messages.metadata.partition
24
- }
11
+ errors_listener = ::Honeybadger::Karafka::ErrorsListener.new
12
+ ::Karafka.monitor.subscribe(errors_listener)
13
+ ::Karafka.producer.monitor.subscribe(errors_listener) if ::Karafka.respond_to?(:producer)
25
14
 
26
- Honeybadger.event("consumer.consumed.karafka", context)
27
- end
15
+ if config.load_plugin_insights?(:karafka)
16
+ ::Karafka.monitor.subscribe(::Honeybadger::Karafka::InsightsListener.new)
28
17
  end
29
18
  end
30
19
  end
@@ -19,6 +19,7 @@ module Honeybadger
19
19
 
20
20
  def call
21
21
  @registry.metrics.each do |metric|
22
+ next if metric.samples == 0
22
23
  metric.event_payloads.each do |payload|
23
24
  Honeybadger.event(payload.merge(interval: @interval))
24
25
  end
@@ -1,4 +1,4 @@
1
1
  module Honeybadger
2
2
  # The current String Honeybadger version.
3
- VERSION = '5.18.0'.freeze
3
+ VERSION = '5.19.1'.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.18.0
4
+ version: 5.19.1
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-10-25 00:00:00.000000000 Z
11
+ date: 2024-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logger
@@ -81,6 +81,7 @@ files:
81
81
  - lib/honeybadger/init/sinatra.rb
82
82
  - lib/honeybadger/instrumentation.rb
83
83
  - lib/honeybadger/instrumentation_helper.rb
84
+ - lib/honeybadger/karafka.rb
84
85
  - lib/honeybadger/logging.rb
85
86
  - lib/honeybadger/metric.rb
86
87
  - lib/honeybadger/metrics_worker.rb