honeybadger 5.27.4 → 5.29.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: 792e12e3901c164ddd146d74d0c1db7dc1978f2ea4804c7e8c35ccee9e864906
4
- data.tar.gz: 92cb3e3455e09a2a9f708f645f22b06599626b5e0fe5e858362969b31133f65a
3
+ metadata.gz: 60e0469389628b0aac4876a067dcdd195b7ac92e46545c1efe4abaf60b85bfeb
4
+ data.tar.gz: 6829c83ceab8d7e1e731beeca047d427eff33713968b3dc71643562a66a05e36
5
5
  SHA512:
6
- metadata.gz: f26123e1ccd7cfc7ed146a4e31b99ec2b835cfd9825ad9dd8813941a0b781765e26007de5c38f4761628859d10d9d44f881f864c561648afe873e477e0b4cc10
7
- data.tar.gz: bcd09b18473e8d4839c68e54d7862fdf27a3bce4b01fc05b638a76e500eb55fd04be3b9268334ffa27e4737b002b383709bf6dda077801203704527007b4d19c
6
+ metadata.gz: 2aaa649a67f0757ddc75a8f951b3c44e2d03e4b55725fdd858f90108f01e1036a3f6b1f19c167194e871e37d62bc6081c24d93200f65a321a6fc918dd37aaa84
7
+ data.tar.gz: 29569d4d2a230d9b1c83bfac13d1b945cd36092a9b5b45fdcbcec85d2d03308af436864f745c9d6383fb8ed30c432b334c4c4d33520c955cfbaed4b2e9ed24e0
data/CHANGELOG.md CHANGED
@@ -1,6 +1,27 @@
1
1
  # Change Log
2
2
 
3
3
 
4
+ ## [5.29.0](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.28.0...v5.29.0) (2025-06-27)
5
+
6
+
7
+ ### Features
8
+
9
+ * add event context ([#700](https://github.com/honeybadger-io/honeybadger-ruby/issues/700)) ([36abc18](https://github.com/honeybadger-io/honeybadger-ruby/commit/36abc1826a62954b83b11b10d7e91d41f3052524))
10
+ * exclude insights from rake tasks config ([#697](https://github.com/honeybadger-io/honeybadger-ruby/issues/697)) ([118034c](https://github.com/honeybadger-io/honeybadger-ruby/commit/118034c8395dd79fada9979f9f519ded8e81234a))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * avoid database connections during asset precompilation ([#695](https://github.com/honeybadger-io/honeybadger-ruby/issues/695)) ([14ae485](https://github.com/honeybadger-io/honeybadger-ruby/commit/14ae4858da865cb6f95d16e1a12faf3ecc2caedd))
16
+
17
+ ## [5.28.0](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.27.4...v5.28.0) (2025-05-02)
18
+
19
+
20
+ ### Features
21
+
22
+ * add sampling ([#689](https://github.com/honeybadger-io/honeybadger-ruby/issues/689)) ([0692ab0](https://github.com/honeybadger-io/honeybadger-ruby/commit/0692ab07d33843dc2612c36713b0f126ecba6b35))
23
+
24
+
4
25
  ## [5.27.4](https://github.com/honeybadger-io/honeybadger-ruby/compare/v5.27.3...v5.27.4) (2025-04-30)
5
26
 
6
27
 
@@ -1,4 +1,5 @@
1
1
  require 'forwardable'
2
+ require 'zlib'
2
3
 
3
4
  require 'honeybadger/version'
4
5
  require 'honeybadger/config'
@@ -412,6 +413,7 @@ module Honeybadger
412
413
  extra_payload = {}.tap do |p|
413
414
  p[:request_id] = context_manager.get_request_id if context_manager.get_request_id
414
415
  p[:hostname] = config[:hostname].to_s if config[:'events.attach_hostname']
416
+ p.update(context_manager.get_event_context || {})
415
417
  end
416
418
 
417
419
  event = Event.new(event_type, extra_payload.merge(payload))
@@ -434,9 +436,61 @@ module Honeybadger
434
436
 
435
437
  return if event.halted?
436
438
 
439
+ return unless sample_event?(event)
440
+
441
+ strip_metadata(event)
442
+
437
443
  events_worker.push(event.as_json)
438
444
  end
439
445
 
446
+ # Save event-specific context for the current request.
447
+ #
448
+ # @example
449
+ # Honeybadger.event_context({user_id: current_user.id})
450
+ #
451
+ # # Inside a Rails controller:
452
+ # before_action do
453
+ # Honeybadger.event_context({user_id: current_user.id})
454
+ # end
455
+ #
456
+ # # Explicit conversion
457
+ # class User < ActiveRecord::Base
458
+ # def to_honeybadger_context
459
+ # { user_id: id, user_email: email }
460
+ # end
461
+ # end
462
+ #
463
+ # user = User.first
464
+ # Honeybadger.event_context(user)
465
+ #
466
+ # # Clearing event context:
467
+ # Honeybadger.clear_event_context
468
+ #
469
+ # @param [Hash] context A Hash of data which will be sent to Honeybadger
470
+ # when an event occurs. If the object responds to +#to_honeybadger_context+,
471
+ # the return value of that method will be used (explicit conversion). Can
472
+ # include any key/value, but a few keys have a special meaning in
473
+ # Honeybadger.
474
+ #
475
+ # @return [Object, self] value of the block if passed, otherwise self
476
+ def event_context(context = nil, &block)
477
+ block_result = context_manager.set_event_context(context, &block) unless context.nil?
478
+ return block_result if block_given?
479
+
480
+ self
481
+ end
482
+
483
+ # Get event-specific context for the current request.
484
+ #
485
+ # @example
486
+ # Honeybadger.event_context({my_data: 'my value'})
487
+ # Honeybadger.get_event_context # => {my_data: 'my value'}
488
+ #
489
+ # @return [Hash, nil]
490
+ def get_event_context
491
+ context_manager.get_event_context
492
+ end
493
+
440
494
  # @api private
441
495
  def collect(collector)
442
496
  return unless config.insights_enabled?
@@ -570,6 +624,26 @@ module Honeybadger
570
624
 
571
625
  private
572
626
 
627
+ def strip_metadata(event)
628
+ event.delete(:_hb)
629
+ end
630
+
631
+ def sample_event?(event)
632
+ # Always send metrics events
633
+ return true if event[:event_type] == "metric.hb"
634
+
635
+ sample_rate = config[:'events.sample_rate']
636
+ sample_rate = event.dig(:_hb, :sample_rate) if event.dig(:_hb, :sample_rate).is_a?(Numeric)
637
+
638
+ return true if sample_rate >= 100
639
+
640
+ if event[:request_id] # Send all events for a given request
641
+ Zlib.crc32(event[:request_id].to_s) % 100 < sample_rate
642
+ else # Otherwise just take a random sample
643
+ rand(100) < sample_rate
644
+ end
645
+ end
646
+
573
647
  def validate_notify_opts!(opts)
574
648
  return if opts.has_key?(:exception)
575
649
  return if opts.has_key?(:error_message)
@@ -129,6 +129,11 @@ module Honeybadger
129
129
  default: nil,
130
130
  type: Array
131
131
  },
132
+ :'events.sample_rate' => {
133
+ description: 'Percentage of events to send to the API (0-100). A value of 0 means no events are sent, 100 means all events are sent.',
134
+ default: 100,
135
+ type: Integer
136
+ },
132
137
  plugins: {
133
138
  description: 'An optional list of plugins to load. Default is to load all plugins.',
134
139
  default: nil,
@@ -492,6 +497,11 @@ module Honeybadger
492
497
  default: 60,
493
498
  type: Integer
494
499
  },
500
+ :'insights.exclude_rake_tasks' => {
501
+ description: "List of Rake tasks to exclude from Insights instrumentation.",
502
+ default: ['assets:precompile'],
503
+ type: Array
504
+ },
495
505
  :'puma.insights.events' => {
496
506
  description: 'Enable automatic event capturing for Puma stats.',
497
507
  default: true,
@@ -289,7 +289,18 @@ module Honeybadger
289
289
  end
290
290
 
291
291
  def insights_enabled?
292
- public? && !!self[:'insights.enabled']
292
+ return false unless public?
293
+ return false if insights_exclude_for_rake_tasks?
294
+ !!self[:'insights.enabled']
295
+ end
296
+
297
+ def insights_exclude_for_rake_tasks?
298
+ return false unless defined?(Rake) && Rake.application&.top_level_tasks
299
+
300
+ current_tasks = Array(Rake.application.top_level_tasks)
301
+ excluded_tasks = Array(self[:'insights.exclude_rake_tasks'])
302
+
303
+ (current_tasks & excluded_tasks).any?
293
304
  end
294
305
 
295
306
  def cluster_collection?(name)
@@ -53,6 +53,52 @@ module Honeybadger
53
53
  end
54
54
  end
55
55
 
56
+ def clear_context
57
+ @mutex.synchronize do
58
+ @global_context = nil
59
+ @local_context = nil
60
+ end
61
+ end
62
+
63
+ def set_event_context(hash, &block)
64
+ local = block_given?
65
+ @mutex.synchronize do
66
+ @global_event_context ||= {}
67
+ @local_event_context ||= []
68
+
69
+ new_context = Context(hash)
70
+
71
+ if local
72
+ @local_event_context << new_context
73
+ else
74
+ @global_event_context.update(new_context)
75
+ end
76
+ end
77
+
78
+ if local
79
+ begin
80
+ yield
81
+ ensure
82
+ @mutex.synchronize { @local_event_context&.pop }
83
+ end
84
+ end
85
+ end
86
+
87
+ def get_event_context
88
+ @mutex.synchronize do
89
+ return @global_event_context unless @local_event_context
90
+
91
+ @global_event_context.merge(@local_event_context.inject({}, :merge))
92
+ end
93
+ end
94
+
95
+ def clear_event_context
96
+ @mutex.synchronize do
97
+ @global_event_context = nil
98
+ @local_event_context = nil
99
+ end
100
+ end
101
+
56
102
  def set_rack_env(env)
57
103
  @mutex.synchronize { @rack_env = env }
58
104
  end
@@ -77,6 +123,8 @@ module Honeybadger
77
123
  @mutex.synchronize do
78
124
  @global_context = nil
79
125
  @local_context = nil
126
+ @global_event_context = nil
127
+ @local_event_context = nil
80
128
  @rack_env = nil
81
129
  @request_id = nil
82
130
  end
@@ -15,7 +15,7 @@ module Honeybadger
15
15
  # The payload data of the event
16
16
  attr_reader :payload
17
17
 
18
- def_delegators :payload, :dig, :[], :[]=
18
+ def_delegators :payload, :dig, :[], :[]=, :delete
19
19
 
20
20
  # @api private
21
21
  def initialize(event_type_or_payload, payload={})
@@ -3,6 +3,7 @@ module Honeybadger
3
3
  module SolidQueue
4
4
  Plugin.register :solid_queue do
5
5
  requirement { config.load_plugin_insights?(:solid_queue) && defined?(::SolidQueue) }
6
+ requirement { defined?(ActiveRecord::Base) && ActiveRecord::Base.connected? }
6
7
 
7
8
  collect_solid_queue_stats = -> do
8
9
  data = {}
@@ -26,9 +27,9 @@ module Honeybadger
26
27
  end
27
28
 
28
29
  collect do
29
- stats = collect_solid_queue_stats.call
30
-
31
30
  if config.cluster_collection?(:solid_queue)
31
+ stats = collect_solid_queue_stats.call
32
+
32
33
  if Honeybadger.config.load_plugin_insights_events?(:solid_queue)
33
34
  Honeybadger.event('stats.solid_queue', stats.except(:stats).merge(stats[:stats]))
34
35
  end
@@ -27,8 +27,10 @@ module Honeybadger
27
27
  # @see Agent#$2
28
28
  def_delegator :'Honeybadger::Agent.instance', :check_in
29
29
  def_delegator :'Honeybadger::Agent.instance', :context
30
+ def_delegator :'Honeybadger::Agent.instance', :event_context
30
31
  def_delegator :'Honeybadger::Agent.instance', :configure
31
32
  def_delegator :'Honeybadger::Agent.instance', :get_context
33
+ def_delegator :'Honeybadger::Agent.instance', :get_event_context
32
34
  def_delegator :'Honeybadger::Agent.instance', :flush
33
35
  def_delegator :'Honeybadger::Agent.instance', :stop
34
36
  def_delegator :'Honeybadger::Agent.instance', :exception_filter
@@ -1,4 +1,4 @@
1
1
  module Honeybadger
2
2
  # The current String Honeybadger version.
3
- VERSION = '5.27.4'.freeze
3
+ VERSION = '5.29.0'.freeze
4
4
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: honeybadger
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.27.4
4
+ version: 5.29.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Honeybadger Industries LLC
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
10
+ date: 2025-06-30 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: logger