honeybadger 5.17.0 → 5.19.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: 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