bugsnag 6.22.1 → 6.24.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,6 +12,9 @@ require "bugsnag/middleware/session_data"
12
12
  require "bugsnag/middleware/breadcrumbs"
13
13
  require "bugsnag/utility/circular_buffer"
14
14
  require "bugsnag/breadcrumbs/breadcrumbs"
15
+ require "bugsnag/breadcrumbs/on_breadcrumb_callback_list"
16
+ require "bugsnag/endpoint_configuration"
17
+ require "bugsnag/endpoint_validator"
15
18
 
16
19
  module Bugsnag
17
20
  class Configuration
@@ -24,6 +27,7 @@ module Bugsnag
24
27
  attr_accessor :release_stage
25
28
 
26
29
  # A list of which release stages should cause notifications to be sent
30
+ # @deprecated Use {#enabled_release_stages} instead
27
31
  # @return [Array<String>, nil]
28
32
  attr_accessor :notify_release_stages
29
33
 
@@ -52,9 +56,20 @@ module Bugsnag
52
56
 
53
57
  # A list of keys that should be filtered out from the report and breadcrumb
54
58
  # metadata before sending them to Bugsnag
59
+ # @deprecated Use {#redacted_keys} instead
55
60
  # @return [Set<String, Regexp>]
56
61
  attr_accessor :meta_data_filters
57
62
 
63
+ # A set of keys that should be redacted from the report and breadcrumb
64
+ # metadata before sending them to Bugsnag
65
+ #
66
+ # When adding strings, keys that are equal to the string (ignoring case)
67
+ # will be redacted. When adding regular expressions, any keys which match
68
+ # the regular expression will be redacted
69
+ #
70
+ # @return [Set<String, Regexp>]
71
+ attr_accessor :redacted_keys
72
+
58
73
  # The logger to use for Bugsnag log messages
59
74
  # @return [Logger]
60
75
  attr_accessor :logger
@@ -104,6 +119,7 @@ module Bugsnag
104
119
  attr_accessor :discard_classes
105
120
 
106
121
  # Whether Bugsnag should automatically record sessions
122
+ # @deprecated Use {#auto_track_sessions} instead
107
123
  # @return [Boolean]
108
124
  attr_accessor :auto_capture_sessions
109
125
 
@@ -111,21 +127,23 @@ module Bugsnag
111
127
  # @return [Set<Class, Proc>]
112
128
  attr_accessor :ignore_classes
113
129
 
114
- # The URL error notifications will be delivered to
115
- # @return [String]
116
- attr_reader :notify_endpoint
117
- alias :endpoint :notify_endpoint
130
+ # The URLs to send events and sessions to
131
+ # @return [EndpointConfiguration]
132
+ attr_reader :endpoints
118
133
 
119
- # The URL session notifications will be delivered to
120
- # @return [String]
121
- attr_reader :session_endpoint
134
+ # Whether events will be delivered
135
+ # @api private
136
+ # @return [Boolean]
137
+ attr_reader :enable_events
122
138
 
123
139
  # Whether sessions will be delivered
140
+ # @api private
124
141
  # @return [Boolean]
125
142
  attr_reader :enable_sessions
126
143
 
127
144
  # A list of strings indicating allowable automatic breadcrumb types
128
- # @see Bugsnag::Breadcrumbs::VALID_BREADCRUMB_TYPES
145
+ # @deprecated Use {#enabled_breadcrumb_types} instead
146
+ # @see Bugsnag::BreadcrumbType
129
147
  # @return [Array<String>]
130
148
  attr_accessor :enabled_automatic_breadcrumb_types
131
149
 
@@ -137,14 +155,37 @@ module Bugsnag
137
155
  # @return [Integer]
138
156
  attr_reader :max_breadcrumbs
139
157
 
140
- #
158
+ # @deprecated Use {vendor_paths} instead
141
159
  # @return [Regexp]
142
160
  attr_accessor :vendor_path
143
161
 
162
+ # An array of paths within the {project_root} that should not be considered
163
+ # as "in project"
164
+ #
165
+ # These paths should be relative to the {project_root} and will only match
166
+ # whole directory names
167
+ #
168
+ # @return [Array<String>]
169
+ attr_accessor :vendor_paths
170
+
171
+ # The default context for all future events
172
+ # Setting this will disable automatic context setting
173
+ # @return [String, nil]
174
+ attr_accessor :context
175
+
176
+ # Global metadata added to every event
177
+ # @return [Hash]
178
+ attr_reader :metadata
179
+
144
180
  # @api private
145
181
  # @return [Array<String>]
146
182
  attr_reader :scopes_to_filter
147
183
 
184
+ # Expose on_breadcrumb_callbacks internally for Bugsnag.leave_breadcrumb
185
+ # @api private
186
+ # @return [Breadcrumbs::OnBreadcrumbCallbackList]
187
+ attr_reader :on_breadcrumb_callbacks
188
+
148
189
  API_KEY_REGEX = /[0-9a-f]{32}/i
149
190
  THREAD_LOCAL_NAME = "bugsnag_req_data"
150
191
 
@@ -180,6 +221,7 @@ module Bugsnag
180
221
  self.send_environment = false
181
222
  self.send_code = true
182
223
  self.meta_data_filters = Set.new(DEFAULT_META_DATA_FILTERS)
224
+ @redacted_keys = Set.new
183
225
  self.scopes_to_filter = DEFAULT_SCOPES_TO_FILTER
184
226
  self.hostname = default_hostname
185
227
  self.runtime_versions = {}
@@ -193,16 +235,20 @@ module Bugsnag
193
235
  # All valid breadcrumb types should be allowable initially
194
236
  self.enabled_automatic_breadcrumb_types = Bugsnag::Breadcrumbs::VALID_BREADCRUMB_TYPES.dup
195
237
  self.before_breadcrumb_callbacks = []
238
+ @on_breadcrumb_callbacks = Breadcrumbs::OnBreadcrumbCallbackList.new(self)
196
239
 
197
240
  # Store max_breadcrumbs here instead of outputting breadcrumbs.max_items
198
241
  # to avoid infinite recursion when creating breadcrumb buffer
199
242
  @max_breadcrumbs = DEFAULT_MAX_BREADCRUMBS
200
243
 
201
- # These are set exclusively using the "set_endpoints" method
202
- @notify_endpoint = DEFAULT_NOTIFY_ENDPOINT
203
- @session_endpoint = DEFAULT_SESSION_ENDPOINT
244
+ @endpoints = EndpointConfiguration.new(DEFAULT_NOTIFY_ENDPOINT, DEFAULT_SESSION_ENDPOINT)
245
+
246
+ @enable_events = true
204
247
  @enable_sessions = true
205
248
 
249
+ @metadata = {}
250
+ @metadata_delegate = Utility::MetadataDelegate.new
251
+
206
252
  # SystemExit and SignalException are common Exception types seen with
207
253
  # successful exits and are not automatically reported to Bugsnag
208
254
  # TODO move these defaults into `discard_classes` when `ignore_classes`
@@ -222,6 +268,7 @@ module Bugsnag
222
268
  # Stacktrace lines that matches regex will be marked as "out of project"
223
269
  # will only appear in the full trace.
224
270
  self.vendor_path = DEFAULT_VENDOR_PATH
271
+ @vendor_paths = []
225
272
 
226
273
  # Set up logging
227
274
  self.logger = Logger.new(STDOUT)
@@ -389,15 +436,23 @@ module Bugsnag
389
436
  ##
390
437
  # Logs a warning level message
391
438
  #
392
- # @param (see info)
439
+ # @param message [String, #to_s] The message to log
393
440
  def warn(message)
394
441
  logger.warn(PROG_NAME) { message }
395
442
  end
396
443
 
444
+ ##
445
+ # Logs an error level message
446
+ #
447
+ # @param message [String, #to_s] The message to log
448
+ def error(message)
449
+ logger.error(PROG_NAME) { message }
450
+ end
451
+
397
452
  ##
398
453
  # Logs a debug level message
399
454
  #
400
- # @param (see info)
455
+ # @param message [String, #to_s] The message to log
401
456
  def debug(message)
402
457
  logger.debug(PROG_NAME) { message }
403
458
  end
@@ -426,33 +481,54 @@ module Bugsnag
426
481
  end
427
482
 
428
483
  ##
429
- # Returns the breadcrumb circular buffer
484
+ # Returns the current list of breadcrumbs
485
+ #
486
+ # This is a per-thread circular buffer, containing at most 'max_breadcrumbs'
487
+ # breadcrumbs
430
488
  #
431
- # @return [Bugsnag::Utility::CircularBuffer] a thread based circular buffer containing breadcrumbs
489
+ # @return [Bugsnag::Utility::CircularBuffer]
432
490
  def breadcrumbs
433
491
  request_data[:breadcrumbs] ||= Bugsnag::Utility::CircularBuffer.new(@max_breadcrumbs)
434
492
  end
435
493
 
494
+ # The URL error notifications will be delivered to
495
+ # @!attribute notify_endpoint
496
+ # @return [String]
497
+ # @deprecated Use {#endpoints} instead
498
+ def notify_endpoint
499
+ @endpoints.notify
500
+ end
501
+
502
+ alias :endpoint :notify_endpoint
503
+
436
504
  # Sets the notification endpoint
437
505
  #
438
- # @deprecated Use {#set_endpoints} instead
506
+ # @deprecated Use {#endpoints} instead
439
507
  #
440
508
  # @param new_notify_endpoint [String] The URL to deliver error notifications to
441
509
  # @return [void]
442
510
  def endpoint=(new_notify_endpoint)
443
- warn("The 'endpoint' configuration option is deprecated. The 'set_endpoints' method should be used instead")
511
+ warn("The 'endpoint' configuration option is deprecated. Set both endpoints with the 'endpoints=' method instead")
444
512
  set_endpoints(new_notify_endpoint, session_endpoint) # Pass the existing session_endpoint through so it doesn't get overwritten
445
513
  end
446
514
 
515
+ # The URL session notifications will be delivered to
516
+ # @!attribute session_endpoint
517
+ # @return [String]
518
+ # @deprecated Use {#endpoints} instead
519
+ def session_endpoint
520
+ @endpoints.sessions
521
+ end
522
+
447
523
  ##
448
524
  # Sets the sessions endpoint
449
525
  #
450
- # @deprecated Use {#set_endpoints} instead
526
+ # @deprecated Use {#endpoints} instead
451
527
  #
452
528
  # @param new_session_endpoint [String] The URL to deliver session notifications to
453
529
  # @return [void]
454
530
  def session_endpoint=(new_session_endpoint)
455
- warn("The 'session_endpoint' configuration option is deprecated. The 'set_endpoints' method should be used instead")
531
+ warn("The 'session_endpoint' configuration option is deprecated. Set both endpoints with the 'endpoints=' method instead")
456
532
  set_endpoints(notify_endpoint, new_session_endpoint) # Pass the existing notify_endpoint through so it doesn't get overwritten
457
533
  end
458
534
 
@@ -462,9 +538,26 @@ module Bugsnag
462
538
  # @param new_notify_endpoint [String] The URL to deliver error notifications to
463
539
  # @param new_session_endpoint [String] The URL to deliver session notifications to
464
540
  # @return [void]
541
+ # @deprecated Use {#endpoints} instead
465
542
  def set_endpoints(new_notify_endpoint, new_session_endpoint)
466
- @notify_endpoint = new_notify_endpoint
467
- @session_endpoint = new_session_endpoint
543
+ self.endpoints = EndpointConfiguration.new(new_notify_endpoint, new_session_endpoint)
544
+ end
545
+
546
+ def endpoints=(endpoint_configuration)
547
+ result = EndpointValidator.validate(endpoint_configuration)
548
+
549
+ if result.valid?
550
+ @enable_events = true
551
+ @enable_sessions = true
552
+ else
553
+ warn(result.reason)
554
+
555
+ @enable_events = result.keep_events_enabled_for_backwards_compatibility?
556
+ @enable_sessions = false
557
+ end
558
+
559
+ # use the given endpoints even if they are invalid
560
+ @endpoints = endpoint_configuration
468
561
  end
469
562
 
470
563
  ##
@@ -503,6 +596,131 @@ module Bugsnag
503
596
  middleware.remove(callback)
504
597
  end
505
598
 
599
+ ##
600
+ # Add the given callback to the list of on_breadcrumb callbacks
601
+ #
602
+ # The on_breadcrumb callbacks will be called when a breadcrumb is left and
603
+ # are passed the {Breadcrumbs::Breadcrumb Breadcrumb} object
604
+ #
605
+ # Returning false from an on_breadcrumb callback will cause the breadcrumb
606
+ # to be ignored and will prevent any remaining callbacks from being called
607
+ #
608
+ # @param callback [Proc, Method, #call]
609
+ # @return [void]
610
+ def add_on_breadcrumb(callback)
611
+ @on_breadcrumb_callbacks.add(callback)
612
+ end
613
+
614
+ ##
615
+ # Remove the given callback from the list of on_breadcrumb callbacks
616
+ #
617
+ # Note that this must be the same instance that was passed to
618
+ # {add_on_breadcrumb}, otherwise it will not be removed
619
+ #
620
+ # @param callback [Proc, Method, #call]
621
+ # @return [void]
622
+ def remove_on_breadcrumb(callback)
623
+ @on_breadcrumb_callbacks.remove(callback)
624
+ end
625
+
626
+ ##
627
+ # Add values to metadata
628
+ #
629
+ # @overload add_metadata(section, data)
630
+ # Merges data into the given section of metadata
631
+ # @param section [String, Symbol]
632
+ # @param data [Hash]
633
+ #
634
+ # @overload add_metadata(section, key, value)
635
+ # Sets key to value in the given section of metadata. If the value is nil
636
+ # the key will be deleted
637
+ # @param section [String, Symbol]
638
+ # @param key [String, Symbol]
639
+ # @param value
640
+ #
641
+ # @return [void]
642
+ def add_metadata(section, key_or_data, *args)
643
+ @mutex.synchronize do
644
+ @metadata_delegate.add_metadata(@metadata, section, key_or_data, *args)
645
+ end
646
+ end
647
+
648
+ ##
649
+ # Clear values from metadata
650
+ #
651
+ # @overload clear_metadata(section)
652
+ # Clears the given section of metadata
653
+ # @param section [String, Symbol]
654
+ #
655
+ # @overload clear_metadata(section, key)
656
+ # Clears the key in the given section of metadata
657
+ # @param section [String, Symbol]
658
+ # @param key [String, Symbol]
659
+ #
660
+ # @return [void]
661
+ def clear_metadata(section, *args)
662
+ @mutex.synchronize do
663
+ @metadata_delegate.clear_metadata(@metadata, section, *args)
664
+ end
665
+ end
666
+
667
+ ##
668
+ # Has the context been explicitly set?
669
+ #
670
+ # This is necessary to differentiate between the context not being set and
671
+ # the context being set to 'nil' explicitly
672
+ #
673
+ # @api private
674
+ # @return [Boolean]
675
+ def context_set?
676
+ defined?(@context) != nil
677
+ end
678
+
679
+ # TODO: These methods can be a simple attr_accessor when they replace the
680
+ # methods they are aliasing
681
+ # NOTE: they are not aliases as YARD doesn't allow documenting the non-alias
682
+ # as deprecated without also marking the alias as deprecated
683
+
684
+ # A list of which release stages should cause notifications to be sent
685
+ # @!attribute enabled_release_stages
686
+ # @return [Array<String>, nil]
687
+ def enabled_release_stages
688
+ @notify_release_stages
689
+ end
690
+
691
+ # @param release_stages [Array<String>, nil]
692
+ # @return [void]
693
+ def enabled_release_stages=(release_stages)
694
+ @notify_release_stages = release_stages
695
+ end
696
+
697
+ # A list of breadcrumb types that Bugsnag will collect automatically
698
+ # @!attribute enabled_breadcrumb_types
699
+ # @see Bugsnag::BreadcrumbType
700
+ # @return [Array<String>]
701
+ def enabled_breadcrumb_types
702
+ @enabled_automatic_breadcrumb_types
703
+ end
704
+
705
+ # @param breadcrumb_types [Array<String>]
706
+ # @return [void]
707
+ def enabled_breadcrumb_types=(breadcrumb_types)
708
+ @enabled_automatic_breadcrumb_types = breadcrumb_types
709
+ end
710
+
711
+ # Whether sessions should be tracked automatically
712
+ # @!attribute auto_track_sessions
713
+ # @return [Boolean]
714
+ def auto_track_sessions
715
+ @auto_capture_sessions
716
+ end
717
+
718
+ # @param track_sessions [Boolean]
719
+ # @return [void]
720
+ def auto_track_sessions=(track_sessions)
721
+ @auto_capture_sessions = track_sessions
722
+ end
723
+
506
724
  private
507
725
 
508
726
  attr_writer :scopes_to_filter
@@ -18,8 +18,8 @@ module Bugsnag
18
18
  # KLUDGE: Since we don't re-raise http exceptions, this breaks rspec
19
19
  raise if e.class.to_s == "RSpec::Expectations::ExpectationNotMetError"
20
20
 
21
- configuration.warn("Notification to #{url} failed, #{e.inspect}")
22
- configuration.warn(e.backtrace)
21
+ configuration.error("Unable to send information to Bugsnag (#{url}), #{e.inspect}")
22
+ configuration.error(e.backtrace)
23
23
  end
24
24
  end
25
25
 
@@ -31,8 +31,8 @@ module Bugsnag
31
31
  begin
32
32
  payload = get_payload.call
33
33
  rescue StandardError => e
34
- configuration.warn("Notification to #{url} failed, #{e.inspect}")
35
- configuration.warn(e.backtrace)
34
+ configuration.error("Unable to send information to Bugsnag (#{url}), #{e.inspect}")
35
+ configuration.error(e.backtrace)
36
36
  end
37
37
 
38
38
  Synchronous.deliver(url, payload, configuration, options) unless payload.nil?
@@ -0,0 +1,11 @@
1
+ module Bugsnag
2
+ class EndpointConfiguration
3
+ attr_reader :notify
4
+ attr_reader :sessions
5
+
6
+ def initialize(notify, sessions)
7
+ @notify = notify
8
+ @sessions = sessions
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,80 @@
1
+ module Bugsnag
2
+ # @api private
3
+ class EndpointValidator
4
+ def self.validate(endpoints)
5
+ # ensure we have an EndpointConfiguration object
6
+ return Result.missing_urls unless endpoints.is_a?(EndpointConfiguration)
7
+
8
+ # check for missing URLs
9
+ return Result.missing_urls if endpoints.notify.nil? && endpoints.sessions.nil?
10
+ return Result.missing_notify if endpoints.notify.nil?
11
+ return Result.missing_session if endpoints.sessions.nil?
12
+
13
+ # check for empty URLs
14
+ return Result.invalid_urls if endpoints.notify.empty? && endpoints.sessions.empty?
15
+ return Result.invalid_notify if endpoints.notify.empty?
16
+ return Result.invalid_session if endpoints.sessions.empty?
17
+
18
+ Result.valid
19
+ end
20
+
21
+ # @api private
22
+ class Result
23
+ # rubocop:disable Layout/LineLength
24
+ MISSING_URLS = "Invalid configuration. endpoints must be set with both a notify and session URL. Bugsnag will not send any requests.".freeze
25
+ MISSING_NOTIFY_URL = "Invalid configuration. endpoints.sessions cannot be set without also setting endpoints.notify. Bugsnag will not send any requests.".freeze
26
+ MISSING_SESSION_URL = "Invalid configuration. endpoints.notify cannot be set without also setting endpoints.sessions. Bugsnag will not send any sessions.".freeze
27
+
28
+ INVALID_URLS = "Invalid configuration. endpoints should be valid URLs, got empty strings. Bugsnag will not send any requests.".freeze
29
+ INVALID_NOTIFY_URL = "Invalid configuration. endpoints.notify should be a valid URL, got empty string. Bugsnag will not send any requests.".freeze
30
+ INVALID_SESSION_URL = "Invalid configuration. endpoints.sessions should be a valid URL, got empty string. Bugsnag will not send any sessions.".freeze
31
+ # rubocop:enable Layout/LineLength
32
+
33
+ attr_reader :reason
34
+
35
+ def initialize(valid, keep_events_enabled_for_backwards_compatibility = true, reason = nil)
36
+ @valid = valid
37
+ @keep_events_enabled_for_backwards_compatibility = keep_events_enabled_for_backwards_compatibility
38
+ @reason = reason
39
+ end
40
+
41
+ def valid?
42
+ @valid
43
+ end
44
+
45
+ def keep_events_enabled_for_backwards_compatibility?
46
+ @keep_events_enabled_for_backwards_compatibility
47
+ end
48
+
49
+ # factory functions
50
+
51
+ def self.valid
52
+ new(true)
53
+ end
54
+
55
+ def self.missing_urls
56
+ new(false, false, MISSING_URLS)
57
+ end
58
+
59
+ def self.missing_notify
60
+ new(false, false, MISSING_NOTIFY_URL)
61
+ end
62
+
63
+ def self.missing_session
64
+ new(false, true, MISSING_SESSION_URL)
65
+ end
66
+
67
+ def self.invalid_urls
68
+ new(false, false, INVALID_URLS)
69
+ end
70
+
71
+ def self.invalid_notify
72
+ new(false, false, INVALID_NOTIFY_URL)
73
+ end
74
+
75
+ def self.invalid_session
76
+ new(false, true, INVALID_SESSION_URL)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,25 @@
1
+ module Bugsnag
2
+ class Error
3
+ # @return [String] the error's class name
4
+ attr_accessor :error_class
5
+
6
+ # @return [String] the error's message
7
+ attr_accessor :error_message
8
+
9
+ # @return [Hash] the error's processed stacktrace
10
+ attr_reader :stacktrace
11
+
12
+ # @return [String] the type of error (always "ruby")
13
+ attr_accessor :type
14
+
15
+ # @api private
16
+ TYPE = "ruby".freeze
17
+
18
+ def initialize(error_class, error_message, stacktrace)
19
+ @error_class = error_class
20
+ @error_message = error_message
21
+ @stacktrace = stacktrace
22
+ @type = TYPE
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ require "bugsnag/report"
2
+
3
+ module Bugsnag
4
+ # For now Event is just an alias of Report. This points to the same object so
5
+ # any changes to Report will also affect Event
6
+ Event = Report
7
+ end
@@ -47,6 +47,29 @@ module Bugsnag
47
47
  end
48
48
  end
49
49
 
50
+ ##
51
+ # Do we need to rescue (& notify) in Active Record callbacks?
52
+ #
53
+ # On Rails versions < 4.2, Rails did not raise errors in AR callbacks
54
+ # On Rails version 4.2, a config option was added to control this
55
+ # On Rails version 5.0, the config option was removed and errors in callbacks
56
+ # always bubble up
57
+ #
58
+ # @api private
59
+ def self.rescue_in_active_record_callbacks?
60
+ # Rails 5+ will re-raise errors in callbacks, so we don't need to rescue them
61
+ return false if ::Rails::VERSION::MAJOR > 4
62
+
63
+ # before 4.2, errors were always swallowed, so we need to rescue them
64
+ return true if ::Rails::VERSION::MAJOR < 4
65
+
66
+ # a config option was added in 4.2 to control this, but won't exist in 4.0 & 4.1
67
+ return true unless ActiveRecord::Base.respond_to?(:raise_in_transactional_callbacks)
68
+
69
+ # if the config option is false, we need to rescue and notify
70
+ ActiveRecord::Base.raise_in_transactional_callbacks == false
71
+ end
72
+
50
73
  rake_tasks do
51
74
  require "bugsnag/integrations/rake"
52
75
  load "bugsnag/tasks/bugsnag.rake"
@@ -70,8 +93,10 @@ module Bugsnag
70
93
  end
71
94
 
72
95
  ActiveSupport.on_load(:active_record) do
73
- require "bugsnag/integrations/rails/active_record_rescue"
74
- include Bugsnag::Rails::ActiveRecordRescue
96
+ if Bugsnag::Railtie.rescue_in_active_record_callbacks?
97
+ require "bugsnag/integrations/rails/active_record_rescue"
98
+ include Bugsnag::Rails::ActiveRecordRescue
99
+ end
75
100
  end
76
101
 
77
102
  ActiveSupport.on_load(:active_job) do
@@ -45,18 +45,22 @@ module Bugsnag
45
45
  }
46
46
 
47
47
  metadata = payload
48
- class_name = payload['class']
48
+ class_name = metadata['class']
49
49
 
50
50
  # when using Active Job the payload "class" will always be the Resque
51
- # "JobWrapper", not the actual job class so we need to fix this here
52
- if metadata['args'] && metadata['args'][0] && metadata['args'][0]['job_class']
53
- class_name = metadata['args'][0]['job_class']
54
- metadata['wrapped'] ||= class_name
51
+ # "JobWrapper", so we need to unwrap the actual class name
52
+ if class_name == "ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper"
53
+ unwrapped_class_name = metadata['args'][0]['job_class'] rescue nil
54
+
55
+ if unwrapped_class_name
56
+ class_name = unwrapped_class_name
57
+ metadata['wrapped'] ||= unwrapped_class_name
58
+ end
55
59
  end
56
60
 
57
61
  context = "#{class_name}@#{queue}"
58
62
  report.meta_data.merge!({ context: context, payload: metadata })
59
- report.context = context
63
+ report.automatic_context = context
60
64
  end
61
65
  end
62
66
  end
@@ -9,7 +9,7 @@ module Bugsnag::Middleware
9
9
 
10
10
  if data
11
11
  report.add_tab(:active_job, data)
12
- report.context = "#{data[:job_name]}@#{data[:queue]}"
12
+ report.automatic_context = "#{data[:job_name]}@#{data[:queue]}"
13
13
  end
14
14
 
15
15
  @bugsnag.call(report)
@@ -30,7 +30,7 @@ module Bugsnag::Middleware
30
30
  payload_data = construct_job_payload(job.payload_object)
31
31
 
32
32
  context = get_context(payload_data, job_data[:active_job])
33
- report.context = context unless context.nil?
33
+ report.automatic_context = context unless context.nil?
34
34
 
35
35
  job_data[:payload] = payload_data
36
36
  end
@@ -16,6 +16,8 @@ module Bugsnag::Middleware
16
16
 
17
17
  if exception.respond_to?(:bugsnag_context)
18
18
  context = exception.bugsnag_context
19
+ # note: this should set 'context' not 'automatic_context' as it's a
20
+ # user-supplied value
19
21
  report.context = context if context.is_a?(String)
20
22
  end
21
23