bugsnag 6.21.0 → 6.25.2

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/CHANGELOG.md +137 -0
  4. data/VERSION +1 -1
  5. data/bugsnag.gemspec +18 -1
  6. data/lib/bugsnag/breadcrumb_type.rb +14 -0
  7. data/lib/bugsnag/breadcrumbs/breadcrumb.rb +34 -1
  8. data/lib/bugsnag/breadcrumbs/breadcrumbs.rb +1 -0
  9. data/lib/bugsnag/breadcrumbs/on_breadcrumb_callback_list.rb +50 -0
  10. data/lib/bugsnag/cleaner.rb +31 -18
  11. data/lib/bugsnag/configuration.rb +240 -22
  12. data/lib/bugsnag/delivery/synchronous.rb +2 -2
  13. data/lib/bugsnag/delivery/thread_queue.rb +2 -2
  14. data/lib/bugsnag/endpoint_configuration.rb +11 -0
  15. data/lib/bugsnag/endpoint_validator.rb +80 -0
  16. data/lib/bugsnag/error.rb +25 -0
  17. data/lib/bugsnag/event.rb +7 -0
  18. data/lib/bugsnag/feature_flag.rb +74 -0
  19. data/lib/bugsnag/integrations/rack.rb +3 -3
  20. data/lib/bugsnag/integrations/rails/active_job.rb +102 -0
  21. data/lib/bugsnag/integrations/railtie.rb +36 -3
  22. data/lib/bugsnag/integrations/resque.rb +17 -3
  23. data/lib/bugsnag/middleware/active_job.rb +18 -0
  24. data/lib/bugsnag/middleware/delayed_job.rb +21 -2
  25. data/lib/bugsnag/middleware/exception_meta_data.rb +2 -0
  26. data/lib/bugsnag/middleware/rack_request.rb +84 -19
  27. data/lib/bugsnag/middleware/rails3_request.rb +2 -2
  28. data/lib/bugsnag/middleware/rake.rb +1 -1
  29. data/lib/bugsnag/middleware/session_data.rb +3 -1
  30. data/lib/bugsnag/middleware/sidekiq.rb +1 -1
  31. data/lib/bugsnag/middleware/suggestion_data.rb +9 -7
  32. data/lib/bugsnag/report.rb +204 -8
  33. data/lib/bugsnag/session_tracker.rb +52 -12
  34. data/lib/bugsnag/stacktrace.rb +13 -2
  35. data/lib/bugsnag/tasks/bugsnag.rake +1 -1
  36. data/lib/bugsnag/utility/duplicator.rb +124 -0
  37. data/lib/bugsnag/utility/feature_data_store.rb +41 -0
  38. data/lib/bugsnag/utility/feature_flag_delegate.rb +89 -0
  39. data/lib/bugsnag/utility/metadata_delegate.rb +102 -0
  40. data/lib/bugsnag.rb +143 -5
  41. metadata +24 -7
@@ -0,0 +1,89 @@
1
+ module Bugsnag::Utility
2
+ # @api private
3
+ class FeatureFlagDelegate
4
+ def initialize
5
+ # feature flags are stored internally in a hash of "name" => <FeatureFlag>
6
+ # we don't use a Set because new feature flags should overwrite old ones
7
+ # that share a name, but FeatureFlag equality also uses the variant
8
+ @storage = {}
9
+ end
10
+
11
+ def initialize_dup(original)
12
+ super
13
+
14
+ # copy the internal storage when 'dup' is called
15
+ @storage = @storage.dup
16
+ end
17
+
18
+ # Add a feature flag with the given name & variant
19
+ #
20
+ # @param name [String]
21
+ # @param variant [String, nil]
22
+ # @return [void]
23
+ def add(name, variant)
24
+ flag = Bugsnag::FeatureFlag.new(name, variant)
25
+
26
+ return unless flag.valid?
27
+
28
+ @storage[flag.name] = flag
29
+ end
30
+
31
+ # Merge the given array of FeatureFlag instances into the stored feature
32
+ # flags
33
+ #
34
+ # New flags will be appended to the array. Flags with the same name will be
35
+ # overwritten, but their position in the array will not change
36
+ #
37
+ # @param feature_flags [Array<Bugsnag::FeatureFlag>]
38
+ # @return [void]
39
+ def merge(feature_flags)
40
+ feature_flags.each do |flag|
41
+ next unless flag.is_a?(Bugsnag::FeatureFlag)
42
+ next unless flag.valid?
43
+
44
+ @storage[flag.name] = flag
45
+ end
46
+ end
47
+
48
+ # Remove the stored flag with the given name
49
+ #
50
+ # @param name [String]
51
+ # @return [void]
52
+ def remove(name)
53
+ @storage.delete(name)
54
+ end
55
+
56
+ # Remove all the stored flags
57
+ #
58
+ # @return [void]
59
+ def clear
60
+ @storage.clear
61
+ end
62
+
63
+ # Get an array of FeatureFlag instances
64
+ #
65
+ # @example
66
+ # [
67
+ # <#Bugsnag::FeatureFlag>,
68
+ # <#Bugsnag::FeatureFlag>,
69
+ # ]
70
+ #
71
+ # @return [Array<Bugsnag::FeatureFlag>]
72
+ def to_a
73
+ @storage.values
74
+ end
75
+
76
+ # Get the feature flags in their JSON representation
77
+ #
78
+ # @example
79
+ # [
80
+ # { "featureFlag" => "name", "variant" => "variant" },
81
+ # { "featureFlag" => "another name" },
82
+ # ]
83
+ #
84
+ # @return [Array<Hash{String => String}>]
85
+ def as_json
86
+ to_a.map(&:to_h)
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,102 @@
1
+ module Bugsnag::Utility
2
+ # @api private
3
+ class MetadataDelegate
4
+ # nil is a valid metadata value, so we need a sentinel object so we can tell
5
+ # if the value parameter has been provided
6
+ NOT_PROVIDED = Object.new
7
+
8
+ ##
9
+ # Add values to metadata
10
+ #
11
+ # @overload add_metadata(metadata, section, data)
12
+ # Merges data into the given section of metadata
13
+ # @param metadata [Hash] The metadata hash to operate on
14
+ # @param section [String, Symbol]
15
+ # @param data [Hash]
16
+ #
17
+ # @overload add_metadata(metadata, section, key, value)
18
+ # Sets key to value in the given section of metadata. If the value is nil
19
+ # the key will be deleted
20
+ # @param metadata [Hash] The metadata hash to operate on
21
+ # @param section [String, Symbol]
22
+ # @param key [String, Symbol]
23
+ # @param value
24
+ #
25
+ # @return [void]
26
+ def add_metadata(metadata, section, key_or_data, value = NOT_PROVIDED)
27
+ case value
28
+ when NOT_PROVIDED
29
+ merge_metadata(metadata, section, key_or_data)
30
+ when nil
31
+ clear_metadata(metadata, section, key_or_data)
32
+ else
33
+ overwrite_metadata(metadata, section, key_or_data, value)
34
+ end
35
+ end
36
+
37
+ ##
38
+ # Clear values from metadata
39
+ #
40
+ # @overload clear_metadata(metadata, section)
41
+ # Clears the given section of metadata
42
+ # @param metadata [Hash] The metadata hash to operate on
43
+ # @param section [String, Symbol]
44
+ #
45
+ # @overload clear_metadata(metadata, section, key)
46
+ # Clears the key in the given section of metadata
47
+ # @param metadata [Hash] The metadata hash to operate on
48
+ # @param section [String, Symbol]
49
+ # @param key [String, Symbol]
50
+ #
51
+ # @return [void]
52
+ def clear_metadata(metadata, section, key = nil)
53
+ if key.nil?
54
+ metadata.delete(section)
55
+ elsif metadata[section]
56
+ metadata[section].delete(key)
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ ##
63
+ # Merge new metadata into the existing metadata
64
+ #
65
+ # Any keys with a 'nil' value in the new metadata will be deleted from the
66
+ # existing metadata
67
+ #
68
+ # @param existing_metadata [Hash]
69
+ # @param section [String, Symbol]
70
+ # @param new_metadata [Hash]
71
+ # @return [void]
72
+ def merge_metadata(existing_metadata, section, new_metadata)
73
+ return unless new_metadata.is_a?(Hash)
74
+
75
+ existing_metadata[section] ||= {}
76
+ data = existing_metadata[section]
77
+
78
+ new_metadata.each do |key, value|
79
+ if value.nil?
80
+ data.delete(key)
81
+ else
82
+ data[key] = value
83
+ end
84
+ end
85
+ end
86
+
87
+ ##
88
+ # Overwrite the value in metadata's section & key
89
+ #
90
+ # @param metadata [Hash]
91
+ # @param section [String, Symbol]
92
+ # @param key [String, Symbol]
93
+ # @param value
94
+ # @return [void]
95
+ def overwrite_metadata(metadata, section, key, value)
96
+ return unless key.is_a?(String) || key.is_a?(Symbol)
97
+
98
+ metadata[section] ||= {}
99
+ metadata[section][key] = value
100
+ end
101
+ end
102
+ end
data/lib/bugsnag.rb CHANGED
@@ -2,9 +2,11 @@ require "rubygems"
2
2
  require "thread"
3
3
 
4
4
  require "bugsnag/version"
5
+ require "bugsnag/utility/feature_data_store"
5
6
  require "bugsnag/configuration"
6
7
  require "bugsnag/meta_data"
7
8
  require "bugsnag/report"
9
+ require "bugsnag/event"
8
10
  require "bugsnag/cleaner"
9
11
  require "bugsnag/helpers"
10
12
  require "bugsnag/session_tracker"
@@ -13,6 +15,8 @@ require "bugsnag/delivery"
13
15
  require "bugsnag/delivery/synchronous"
14
16
  require "bugsnag/delivery/thread_queue"
15
17
 
18
+ require "bugsnag/feature_flag"
19
+
16
20
  # Rack is not bundled with the other integrations
17
21
  # as it doesn't auto-configure when loaded
18
22
  require "bugsnag/integrations/rack"
@@ -28,10 +32,15 @@ require "bugsnag/middleware/rake"
28
32
  require "bugsnag/middleware/classify_error"
29
33
  require "bugsnag/middleware/delayed_job"
30
34
 
35
+ require "bugsnag/breadcrumb_type"
31
36
  require "bugsnag/breadcrumbs/validator"
32
37
  require "bugsnag/breadcrumbs/breadcrumb"
33
38
  require "bugsnag/breadcrumbs/breadcrumbs"
34
39
 
40
+ require "bugsnag/utility/duplicator"
41
+ require "bugsnag/utility/metadata_delegate"
42
+ require "bugsnag/utility/feature_flag_delegate"
43
+
35
44
  # rubocop:todo Metrics/ModuleLength
36
45
  module Bugsnag
37
46
  LOCK = Mutex.new
@@ -40,6 +49,8 @@ module Bugsnag
40
49
  NIL_EXCEPTION_DESCRIPTION = "'nil' was notified as an exception"
41
50
 
42
51
  class << self
52
+ include Utility::FeatureDataStore
53
+
43
54
  ##
44
55
  # Configure the Bugsnag notifier application-wide settings.
45
56
  #
@@ -67,7 +78,7 @@ module Bugsnag
67
78
  #
68
79
  # Optionally accepts a block to append metadata to the yielded report.
69
80
  def notify(exception, auto_notify=false, &block)
70
- unless auto_notify.is_a? TrueClass or auto_notify.is_a? FalseClass
81
+ unless false.equal? auto_notify or true.equal? auto_notify
71
82
  configuration.warn("Adding metadata/severity using a hash is no longer supported, please use block syntax instead")
72
83
  auto_notify = false
73
84
  end
@@ -132,6 +143,11 @@ module Bugsnag
132
143
  report.severity_reason = initial_reason
133
144
  end
134
145
 
146
+ if report.unhandled_overridden?
147
+ # let the dashboard know that the unhandled flag was overridden
148
+ report.severity_reason[:unhandledOverridden] = true
149
+ end
150
+
135
151
  deliver_notification(report)
136
152
  end
137
153
  end
@@ -187,13 +203,36 @@ module Bugsnag
187
203
  end
188
204
 
189
205
  ##
190
- # Starts a session.
206
+ # Starts a new session, which allows Bugsnag to track error rates across
207
+ # releases
191
208
  #
192
- # Allows Bugsnag to track error rates across releases.
209
+ # @return [void]
193
210
  def start_session
194
211
  session_tracker.start_session
195
212
  end
196
213
 
214
+ ##
215
+ # Stop any events being attributed to the current session until it is
216
+ # resumed or a new session is started
217
+ #
218
+ # @see resume_session
219
+ #
220
+ # @return [void]
221
+ def pause_session
222
+ session_tracker.pause_session
223
+ end
224
+
225
+ ##
226
+ # Resume the current session if it was previously paused. If there is no
227
+ # current session, a new session will be started
228
+ #
229
+ # @see pause_session
230
+ #
231
+ # @return [Boolean] true if a paused session was resumed
232
+ def resume_session
233
+ session_tracker.resume_session
234
+ end
235
+
197
236
  ##
198
237
  # Allow access to "before notify" callbacks as an array.
199
238
  #
@@ -237,7 +276,7 @@ module Bugsnag
237
276
  #
238
277
  # @param name [String] the main breadcrumb name/message
239
278
  # @param meta_data [Hash] String, Numeric, or Boolean meta data to attach
240
- # @param type [String] the breadcrumb type, from Bugsnag::Breadcrumbs::VALID_BREADCRUMB_TYPES
279
+ # @param type [String] the breadcrumb type, see {Bugsnag::BreadcrumbType}
241
280
  # @param auto [Symbol] set to :auto if the breadcrumb is automatically created
242
281
  # @return [void]
243
282
  def leave_breadcrumb(name, meta_data={}, type=Bugsnag::Breadcrumbs::MANUAL_BREADCRUMB_TYPE, auto=:manual)
@@ -250,7 +289,7 @@ module Bugsnag
250
289
  # Skip if it's already invalid
251
290
  return if breadcrumb.ignore?
252
291
 
253
- # Run callbacks
292
+ # Run before_breadcrumb_callbacks
254
293
  configuration.before_breadcrumb_callbacks.each do |c|
255
294
  c.arity > 0 ? c.call(breadcrumb) : c.call
256
295
  break if breadcrumb.ignore?
@@ -259,6 +298,10 @@ module Bugsnag
259
298
  # Return early if ignored
260
299
  return if breadcrumb.ignore?
261
300
 
301
+ # Run on_breadcrumb callbacks
302
+ configuration.on_breadcrumb_callbacks.call(breadcrumb)
303
+ return if breadcrumb.ignore?
304
+
262
305
  # Validate again in case of callback alteration
263
306
  validator.validate(breadcrumb)
264
307
 
@@ -293,6 +336,44 @@ module Bugsnag
293
336
  configuration.remove_on_error(callback)
294
337
  end
295
338
 
339
+ ##
340
+ # Add the given callback to the list of on_breadcrumb callbacks
341
+ #
342
+ # The on_breadcrumb callbacks will be called when a breadcrumb is left and
343
+ # are passed the {Breadcrumbs::Breadcrumb Breadcrumb} object
344
+ #
345
+ # Returning false from an on_breadcrumb callback will cause the breadcrumb
346
+ # to be ignored and will prevent any remaining callbacks from being called
347
+ #
348
+ # @param callback [Proc, Method, #call]
349
+ # @return [void]
350
+ def add_on_breadcrumb(callback)
351
+ configuration.add_on_breadcrumb(callback)
352
+ end
353
+
354
+ ##
355
+ # Remove the given callback from the list of on_breadcrumb callbacks
356
+ #
357
+ # Note that this must be the same instance that was passed to
358
+ # {add_on_breadcrumb}, otherwise it will not be removed
359
+ #
360
+ # @param callback [Proc, Method, #call]
361
+ # @return [void]
362
+ def remove_on_breadcrumb(callback)
363
+ configuration.remove_on_breadcrumb(callback)
364
+ end
365
+
366
+ ##
367
+ # Returns the current list of breadcrumbs
368
+ #
369
+ # This is a per-thread circular buffer, containing at most 'max_breadcrumbs'
370
+ # breadcrumbs
371
+ #
372
+ # @return [Bugsnag::Utility::CircularBuffer]
373
+ def breadcrumbs
374
+ configuration.breadcrumbs
375
+ end
376
+
296
377
  ##
297
378
  # Returns the client's Cleaner object, or creates one if not yet created.
298
379
  #
@@ -306,9 +387,66 @@ module Bugsnag
306
387
  end
307
388
  end
308
389
 
390
+ ##
391
+ # Global metadata added to every event
392
+ #
393
+ # @return [Hash]
394
+ def metadata
395
+ configuration.metadata
396
+ end
397
+
398
+ ##
399
+ # Add values to metadata
400
+ #
401
+ # @overload add_metadata(section, data)
402
+ # Merges data into the given section of metadata
403
+ # @param section [String, Symbol]
404
+ # @param data [Hash]
405
+ #
406
+ # @overload add_metadata(section, key, value)
407
+ # Sets key to value in the given section of metadata. If the value is nil
408
+ # the key will be deleted
409
+ # @param section [String, Symbol]
410
+ # @param key [String, Symbol]
411
+ # @param value
412
+ #
413
+ # @return [void]
414
+ def add_metadata(section, key_or_data, *args)
415
+ configuration.add_metadata(section, key_or_data, *args)
416
+ end
417
+
418
+ ##
419
+ # Clear values from metadata
420
+ #
421
+ # @overload clear_metadata(section)
422
+ # Clears the given section of metadata
423
+ # @param section [String, Symbol]
424
+ #
425
+ # @overload clear_metadata(section, key)
426
+ # Clears the key in the given section of metadata
427
+ # @param section [String, Symbol]
428
+ # @param key [String, Symbol]
429
+ #
430
+ # @return [void]
431
+ def clear_metadata(section, *args)
432
+ configuration.clear_metadata(section, *args)
433
+ end
434
+
435
+ # Expose the feature flag delegate internally for use when creating new Events
436
+ #
437
+ # The Bugsnag module's feature_flag_delegate is request-specific
438
+ #
439
+ # @return [Bugsnag::Utility::FeatureFlagDelegate]
440
+ # @api private
441
+ def feature_flag_delegate
442
+ configuration.request_data[:feature_flag_delegate] ||= Utility::FeatureFlagDelegate.new
443
+ end
444
+
309
445
  private
310
446
 
311
447
  def should_deliver_notification?(exception, auto_notify)
448
+ return false unless configuration.enable_events
449
+
312
450
  reason = abort_reason(exception, auto_notify)
313
451
  configuration.debug(reason) unless reason.nil?
314
452
  reason.nil?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bugsnag
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.21.0
4
+ version: 6.25.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Smith
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-23 00:00:00.000000000 Z
11
+ date: 2023-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -40,8 +40,10 @@ files:
40
40
  - VERSION
41
41
  - bugsnag.gemspec
42
42
  - lib/bugsnag.rb
43
+ - lib/bugsnag/breadcrumb_type.rb
43
44
  - lib/bugsnag/breadcrumbs/breadcrumb.rb
44
45
  - lib/bugsnag/breadcrumbs/breadcrumbs.rb
46
+ - lib/bugsnag/breadcrumbs/on_breadcrumb_callback_list.rb
45
47
  - lib/bugsnag/breadcrumbs/validator.rb
46
48
  - lib/bugsnag/cleaner.rb
47
49
  - lib/bugsnag/code_extractor.rb
@@ -49,12 +51,18 @@ files:
49
51
  - lib/bugsnag/delivery.rb
50
52
  - lib/bugsnag/delivery/synchronous.rb
51
53
  - lib/bugsnag/delivery/thread_queue.rb
54
+ - lib/bugsnag/endpoint_configuration.rb
55
+ - lib/bugsnag/endpoint_validator.rb
56
+ - lib/bugsnag/error.rb
57
+ - lib/bugsnag/event.rb
58
+ - lib/bugsnag/feature_flag.rb
52
59
  - lib/bugsnag/helpers.rb
53
60
  - lib/bugsnag/integrations/delayed_job.rb
54
61
  - lib/bugsnag/integrations/mailman.rb
55
62
  - lib/bugsnag/integrations/mongo.rb
56
63
  - lib/bugsnag/integrations/que.rb
57
64
  - lib/bugsnag/integrations/rack.rb
65
+ - lib/bugsnag/integrations/rails/active_job.rb
58
66
  - lib/bugsnag/integrations/rails/active_record_rescue.rb
59
67
  - lib/bugsnag/integrations/rails/controller_methods.rb
60
68
  - lib/bugsnag/integrations/rails/rails_breadcrumbs.rb
@@ -64,6 +72,7 @@ files:
64
72
  - lib/bugsnag/integrations/shoryuken.rb
65
73
  - lib/bugsnag/integrations/sidekiq.rb
66
74
  - lib/bugsnag/meta_data.rb
75
+ - lib/bugsnag/middleware/active_job.rb
67
76
  - lib/bugsnag/middleware/breadcrumbs.rb
68
77
  - lib/bugsnag/middleware/callbacks.rb
69
78
  - lib/bugsnag/middleware/classify_error.rb
@@ -88,13 +97,21 @@ files:
88
97
  - lib/bugsnag/tasks.rb
89
98
  - lib/bugsnag/tasks/bugsnag.rake
90
99
  - lib/bugsnag/utility/circular_buffer.rb
100
+ - lib/bugsnag/utility/duplicator.rb
101
+ - lib/bugsnag/utility/feature_data_store.rb
102
+ - lib/bugsnag/utility/feature_flag_delegate.rb
103
+ - lib/bugsnag/utility/metadata_delegate.rb
91
104
  - lib/bugsnag/version.rb
92
105
  - lib/generators/bugsnag/bugsnag_generator.rb
93
106
  homepage: https://github.com/bugsnag/bugsnag-ruby
94
107
  licenses:
95
108
  - MIT
96
- metadata: {}
97
- post_install_message:
109
+ metadata:
110
+ changelog_uri: https://github.com/bugsnag/bugsnag-ruby/blob/HEAD/CHANGELOG.md
111
+ documentation_uri: https://docs.bugsnag.com/platforms/ruby/
112
+ source_code_uri: https://github.com/bugsnag/bugsnag-ruby/
113
+ rubygems_mfa_required: 'true'
114
+ post_install_message:
98
115
  rdoc_options: []
99
116
  require_paths:
100
117
  - lib
@@ -109,8 +126,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
126
  - !ruby/object:Gem::Version
110
127
  version: '0'
111
128
  requirements: []
112
- rubygems_version: 3.2.11
113
- signing_key:
129
+ rubygems_version: 3.3.7
130
+ signing_key:
114
131
  specification_version: 4
115
132
  summary: Ruby notifier for bugsnag.com
116
133
  test_files: []