honeybadger 5.18.0 → 5.19.1

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.
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