honeybadger 5.17.0 → 5.19.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9c6c96b4525b6497fd3376651cab2d8f4aadaee94bd6b44ea7c7e0f29db16af
4
- data.tar.gz: 03e4454abbe0c2c0fe3c00ed36b08208e778955af16d73b1d18d7be10f8c5309
3
+ metadata.gz: bf4c3296c72440877caccd2ada861f4060af897ed517688fb838cd57ae0a58ff
4
+ data.tar.gz: 25d45250d1f2d2b0fadfa37637446316f12588f3dd134695803c3a068a0513d8
5
5
  SHA512:
6
- metadata.gz: 1e05a64d8163974c1de5afc9df5db1cfc798076cccb09859f3e734d34a419f8bf03c3eac5ca89510d30c443677b3ca86a2fb58fc3b0643b77c71f3b08d3df651
7
- data.tar.gz: 5678d4ff50a14f8d9f63d17443b96c36ecaa93362ecb7412c01bc4a24600700f336056f4960e56376e9195aafc42b9a4e1187d761b6d508fc09d651507dead02
6
+ metadata.gz: 3c66b0c6fa819e716b18a710c1e11fe8c95d25e06ca69216efb93fb2d4bffd1d65c46e7b00b658c0321ac6608817dec2c894eb68bcc0bf39da858c37c0b96302
7
+ data.tar.gz: 6ef30a79138840ade5fef06ef5771f96c4a94ea942b6154b322632f73d71f8c72745be940e25c6aa19187411897c528e5f3e0325c3605cce0861cc4a6aa73a9b
data/CHANGELOG.md CHANGED
@@ -1,6 +1,20 @@
1
1
  # Change Log
2
2
 
3
3
 
4
+ ## [5.19.0](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.18.0...v5.19.0) (2024-10-29)
5
+
6
+
7
+ ### Features
8
+
9
+ * 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))
10
+
11
+ ## [5.18.0](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.17.0...v5.18.0) (2024-10-25)
12
+
13
+
14
+ ### Features
15
+
16
+ * add a separate configuration for Insights in a console ([#623](https://github.com/honeybadger-io/honeybadger-ruby/issues/623)) ([a89488e](https://github.com/honeybadger-io/honeybadger-ruby/commit/a89488e535ff04ec2e362807f0001471ba5c6fe3))
17
+
4
18
  ## [5.17.0](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.16.0...v5.17.0) (2024-10-22)
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,
@@ -411,6 +426,11 @@ module Honeybadger
411
426
  default: false,
412
427
  type: Boolean
413
428
  },
429
+ :'insights.console.enabled' => {
430
+ description: "Enable/Disable Honeybadger Insights built-in instrumentation in a Rails console.",
431
+ default: false,
432
+ type: Boolean
433
+ },
414
434
  :'insights.registry_flush_interval' => {
415
435
  description: "Number of seconds between registry flushes.",
416
436
  default: 60,
@@ -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
@@ -34,7 +34,7 @@ module Honeybadger
34
34
  end
35
35
 
36
36
  console do
37
- Honeybadger::Agent.instance.config[:'insights.enabled'] = false unless Honeybadger::Agent.instance.config.env.has_key?(:'insights.enabled')
37
+ Honeybadger::Agent.instance.config[:'insights.enabled'] = Honeybadger::Agent.instance.config[:'insights.console.enabled']
38
38
  end
39
39
  end
40
40
  end
@@ -47,63 +47,91 @@ 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?
60
+ raise 'No value found' if value.nil?
59
61
 
60
62
  Honeybadger::Timer.register(registry, name, attributes).tap do |timer|
61
- timer.record(duration)
63
+ timer.record(value)
62
64
  end
63
65
  end
64
66
 
65
67
  def histogram(name, *args)
66
68
  attributes = extract_attributes(args)
67
69
  callable = extract_callable(args)
68
- duration = attributes.delete(:duration)
70
+ value = nil
69
71
 
70
72
  if callable
71
- duration = monotonic_timer{ callable.call }[0]
73
+ value = monotonic_timer{ callable.call }[0]
72
74
  elsif block_given?
73
- duration = monotonic_timer{ yield }[0]
75
+ value = monotonic_timer{ yield }[0]
76
+ else
77
+ value = attributes.delete(:duration) || attributes.delete(:value)
74
78
  end
75
79
 
76
- raise 'No duration found' if duration.nil?
80
+ raise 'No value found' if value.nil?
77
81
 
78
82
  Honeybadger::Histogram.register(registry, name, attributes).tap do |histogram|
79
- histogram.record(duration)
83
+ histogram.record(value)
80
84
  end
81
85
  end
82
86
 
83
87
  def increment_counter(name, *args)
84
88
  attributes = extract_attributes(args)
85
- by = extract_callable(args)&.call || attributes.delete(:by) || 1
86
- by = yield if block_given?
89
+ callable = extract_callable(args)
90
+ value = nil
91
+
92
+ if callable
93
+ value = callable.call
94
+ elsif block_given?
95
+ value = yield
96
+ else
97
+ value = attributes.delete(:by) || attributes.delete(:value) || 1
98
+ end
87
99
 
88
100
  Honeybadger::Counter.register(registry, name, attributes).tap do |counter|
89
- counter.count(by)
101
+ counter.count(value)
90
102
  end
91
103
  end
92
104
 
93
105
  def decrement_counter(name, *args)
94
106
  attributes = extract_attributes(args)
95
- by = extract_callable(args)&.call || attributes.delete(:by) || 1
96
- by = yield if block_given?
107
+ callable = extract_callable(args)
108
+ value = nil
109
+
110
+ if callable
111
+ value = callable.call
112
+ elsif block_given?
113
+ value = yield
114
+ else
115
+ value = attributes.delete(:by) || attributes.delete(:value) || 1
116
+ end
97
117
 
98
118
  Honeybadger::Counter.register(registry, name, attributes).tap do |counter|
99
- counter.count(by * -1)
119
+ counter.count(value * -1)
100
120
  end
101
121
  end
102
122
 
103
123
  def gauge(name, *args)
104
124
  attributes = extract_attributes(args)
105
- value = extract_callable(args)&.call || attributes.delete(:value)
106
- value = yield if block_given?
125
+ callable = extract_callable(args)
126
+ value = nil
127
+
128
+ if callable
129
+ value = callable.call
130
+ elsif block_given?
131
+ value = yield
132
+ else
133
+ value = attributes.delete(:value)
134
+ end
107
135
 
108
136
  Honeybadger::Gauge.register(registry, name, attributes).tap do |gauge|
109
137
  gauge.record(value)
@@ -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
@@ -1,4 +1,4 @@
1
1
  module Honeybadger
2
2
  # The current String Honeybadger version.
3
- VERSION = '5.17.0'.freeze
3
+ VERSION = '5.19.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.17.0
4
+ version: 5.19.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-10-24 00:00:00.000000000 Z
11
+ date: 2024-10-29 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