bugsnag 6.20.0 → 6.24.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 +4 -4
- data/CHANGELOG.md +110 -0
- data/VERSION +1 -1
- data/lib/bugsnag/breadcrumb_type.rb +14 -0
- data/lib/bugsnag/breadcrumbs/breadcrumb.rb +34 -1
- data/lib/bugsnag/breadcrumbs/breadcrumbs.rb +1 -0
- data/lib/bugsnag/breadcrumbs/on_breadcrumb_callback_list.rb +50 -0
- data/lib/bugsnag/cleaner.rb +31 -18
- data/lib/bugsnag/configuration.rb +243 -25
- data/lib/bugsnag/delivery/synchronous.rb +2 -2
- data/lib/bugsnag/delivery/thread_queue.rb +2 -2
- data/lib/bugsnag/endpoint_configuration.rb +11 -0
- data/lib/bugsnag/endpoint_validator.rb +80 -0
- data/lib/bugsnag/error.rb +25 -0
- data/lib/bugsnag/event.rb +7 -0
- data/lib/bugsnag/integrations/rack.rb +3 -3
- data/lib/bugsnag/integrations/rails/active_job.rb +102 -0
- data/lib/bugsnag/integrations/railtie.rb +43 -36
- data/lib/bugsnag/integrations/resque.rb +13 -3
- data/lib/bugsnag/middleware/active_job.rb +18 -0
- data/lib/bugsnag/middleware/delayed_job.rb +21 -2
- data/lib/bugsnag/middleware/exception_meta_data.rb +2 -0
- data/lib/bugsnag/middleware/rack_request.rb +84 -19
- data/lib/bugsnag/middleware/rails3_request.rb +2 -2
- data/lib/bugsnag/middleware/rake.rb +1 -1
- data/lib/bugsnag/middleware/session_data.rb +3 -1
- data/lib/bugsnag/middleware/sidekiq.rb +1 -1
- data/lib/bugsnag/middleware_stack.rb +6 -6
- data/lib/bugsnag/report.rb +166 -6
- data/lib/bugsnag/session_tracker.rb +52 -12
- data/lib/bugsnag/stacktrace.rb +10 -1
- data/lib/bugsnag/tasks/bugsnag.rake +1 -1
- data/lib/bugsnag/utility/duplicator.rb +124 -0
- data/lib/bugsnag/utility/metadata_delegate.rb +102 -0
- data/lib/bugsnag.rb +139 -7
- metadata +12 -2
@@ -34,16 +34,20 @@ module Bugsnag
|
|
34
34
|
# Starts a new session, storing it on the current thread.
|
35
35
|
#
|
36
36
|
# This allows Bugsnag to track error rates for a release.
|
37
|
+
#
|
38
|
+
# @return [void]
|
37
39
|
def start_session
|
38
|
-
return unless Bugsnag.configuration.enable_sessions
|
40
|
+
return unless Bugsnag.configuration.enable_sessions && Bugsnag.configuration.should_notify_release_stage?
|
41
|
+
|
39
42
|
start_delivery_thread
|
40
43
|
start_time = Time.now().utc().strftime('%Y-%m-%dT%H:%M:00')
|
41
44
|
new_session = {
|
42
|
-
:
|
43
|
-
:
|
44
|
-
|
45
|
-
|
46
|
-
:
|
45
|
+
id: SecureRandom.uuid,
|
46
|
+
startedAt: start_time,
|
47
|
+
paused?: false,
|
48
|
+
events: {
|
49
|
+
handled: 0,
|
50
|
+
unhandled: 0
|
47
51
|
}
|
48
52
|
}
|
49
53
|
SessionTracker.set_current_session(new_session)
|
@@ -52,6 +56,47 @@ module Bugsnag
|
|
52
56
|
|
53
57
|
alias_method :create_session, :start_session
|
54
58
|
|
59
|
+
##
|
60
|
+
# Stop any events being attributed to the current session until it is
|
61
|
+
# resumed or a new session is started
|
62
|
+
#
|
63
|
+
# @see resume_session
|
64
|
+
#
|
65
|
+
# @return [void]
|
66
|
+
def pause_session
|
67
|
+
current_session = SessionTracker.get_current_session
|
68
|
+
|
69
|
+
return unless current_session
|
70
|
+
|
71
|
+
current_session[:paused?] = true
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Resume the current session if it was previously paused. If there is no
|
76
|
+
# current session, a new session will be started
|
77
|
+
#
|
78
|
+
# @see pause_session
|
79
|
+
#
|
80
|
+
# @return [Boolean] true if a paused session was resumed
|
81
|
+
def resume_session
|
82
|
+
current_session = SessionTracker.get_current_session
|
83
|
+
|
84
|
+
if current_session
|
85
|
+
# if the session is paused then resume it, otherwise we don't need to
|
86
|
+
# do anything
|
87
|
+
if current_session[:paused?]
|
88
|
+
current_session[:paused?] = false
|
89
|
+
|
90
|
+
return true
|
91
|
+
end
|
92
|
+
else
|
93
|
+
# if there's no current session, start a new one
|
94
|
+
start_session
|
95
|
+
end
|
96
|
+
|
97
|
+
false
|
98
|
+
end
|
99
|
+
|
55
100
|
##
|
56
101
|
# Delivers the current session_counts lists to the session endpoint.
|
57
102
|
def send_sessions
|
@@ -83,7 +128,7 @@ module Bugsnag
|
|
83
128
|
end
|
84
129
|
end
|
85
130
|
end
|
86
|
-
@delivery_thread = Concurrent::TimerTask.execute(execution_interval:
|
131
|
+
@delivery_thread = Concurrent::TimerTask.execute(execution_interval: 10) do
|
87
132
|
if @session_counts.size > 0
|
88
133
|
send_sessions
|
89
134
|
end
|
@@ -106,11 +151,6 @@ module Bugsnag
|
|
106
151
|
return
|
107
152
|
end
|
108
153
|
|
109
|
-
if !Bugsnag.configuration.should_notify_release_stage?
|
110
|
-
Bugsnag.configuration.debug("Not delivering sessions due to notify_release_stages :#{Bugsnag.configuration.notify_release_stages.inspect}")
|
111
|
-
return
|
112
|
-
end
|
113
|
-
|
114
154
|
body = {
|
115
155
|
:notifier => {
|
116
156
|
:name => Bugsnag::Report::NOTIFIER_NAME,
|
data/lib/bugsnag/stacktrace.rb
CHANGED
@@ -43,7 +43,7 @@ module Bugsnag
|
|
43
43
|
if defined?(configuration.project_root) && configuration.project_root.to_s != ''
|
44
44
|
trace_hash[:inProject] = true if file.start_with?(configuration.project_root.to_s)
|
45
45
|
file.sub!(/#{configuration.project_root}\//, "")
|
46
|
-
trace_hash.delete(:inProject) if
|
46
|
+
trace_hash.delete(:inProject) if vendor_path?(configuration, file)
|
47
47
|
end
|
48
48
|
|
49
49
|
# Strip common gem path prefixes
|
@@ -67,5 +67,14 @@ module Bugsnag
|
|
67
67
|
|
68
68
|
processed_backtrace
|
69
69
|
end
|
70
|
+
|
71
|
+
# @api private
|
72
|
+
def self.vendor_path?(configuration, file_path)
|
73
|
+
return true if configuration.vendor_path && file_path.match(configuration.vendor_path)
|
74
|
+
|
75
|
+
configuration.vendor_paths.any? do |vendor_path|
|
76
|
+
file_path.start_with?("#{vendor_path.sub(/\/$/, '')}/")
|
77
|
+
end
|
78
|
+
end
|
70
79
|
end
|
71
80
|
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Bugsnag::Utility
|
2
|
+
# @api private
|
3
|
+
class Duplicator
|
4
|
+
class << self
|
5
|
+
##
|
6
|
+
# Duplicate (deep clone) the given object
|
7
|
+
#
|
8
|
+
# @param object [Object]
|
9
|
+
# @param seen_objects [Hash<String, Object>]
|
10
|
+
# @return [Object]
|
11
|
+
def duplicate(object, seen_objects = {})
|
12
|
+
case object
|
13
|
+
# return immutable & non-duplicatable objects as-is
|
14
|
+
when Symbol, Numeric, Method, TrueClass, FalseClass, NilClass
|
15
|
+
object
|
16
|
+
when Array
|
17
|
+
duplicate_array(object, seen_objects)
|
18
|
+
when Hash
|
19
|
+
duplicate_hash(object, seen_objects)
|
20
|
+
when Range
|
21
|
+
duplicate_range(object, seen_objects)
|
22
|
+
when Struct
|
23
|
+
duplicate_struct(object, seen_objects)
|
24
|
+
else
|
25
|
+
duplicate_generic_object(object, seen_objects)
|
26
|
+
end
|
27
|
+
rescue StandardError
|
28
|
+
object
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def duplicate_array(array, seen_objects)
|
34
|
+
id = array.object_id
|
35
|
+
|
36
|
+
return seen_objects[id] if seen_objects.key?(id)
|
37
|
+
|
38
|
+
copy = array.dup
|
39
|
+
seen_objects[id] = copy
|
40
|
+
|
41
|
+
copy.map! do |value|
|
42
|
+
duplicate(value, seen_objects)
|
43
|
+
end
|
44
|
+
|
45
|
+
copy
|
46
|
+
end
|
47
|
+
|
48
|
+
def duplicate_hash(hash, seen_objects)
|
49
|
+
id = hash.object_id
|
50
|
+
|
51
|
+
return seen_objects[id] if seen_objects.key?(id)
|
52
|
+
|
53
|
+
copy = {}
|
54
|
+
seen_objects[id] = copy
|
55
|
+
|
56
|
+
hash.each do |key, value|
|
57
|
+
copy[duplicate(key, seen_objects)] = duplicate(value, seen_objects)
|
58
|
+
end
|
59
|
+
|
60
|
+
copy
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Ranges are immutable but the values they contain may not be
|
65
|
+
#
|
66
|
+
# For example, a range of "a".."z" can be mutated: range.first.upcase!
|
67
|
+
def duplicate_range(range, seen_objects)
|
68
|
+
id = range.object_id
|
69
|
+
|
70
|
+
return seen_objects[id] if seen_objects.key?(id)
|
71
|
+
|
72
|
+
begin
|
73
|
+
copy = range.class.new(
|
74
|
+
duplicate(range.first, seen_objects),
|
75
|
+
duplicate(range.last, seen_objects),
|
76
|
+
range.exclude_end?
|
77
|
+
)
|
78
|
+
rescue StandardError
|
79
|
+
copy = range.dup
|
80
|
+
end
|
81
|
+
|
82
|
+
seen_objects[id] = copy
|
83
|
+
end
|
84
|
+
|
85
|
+
def duplicate_struct(struct, seen_objects)
|
86
|
+
id = struct.object_id
|
87
|
+
|
88
|
+
return seen_objects[id] if seen_objects.key?(id)
|
89
|
+
|
90
|
+
copy = struct.dup
|
91
|
+
seen_objects[id] = copy
|
92
|
+
|
93
|
+
struct.each_pair do |attribute, value|
|
94
|
+
begin
|
95
|
+
copy.send("#{attribute}=", duplicate(value, seen_objects))
|
96
|
+
rescue StandardError # rubocop:todo Lint/SuppressedException
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
copy
|
101
|
+
end
|
102
|
+
|
103
|
+
def duplicate_generic_object(object, seen_objects)
|
104
|
+
id = object.object_id
|
105
|
+
|
106
|
+
return seen_objects[id] if seen_objects.key?(id)
|
107
|
+
|
108
|
+
copy = object.dup
|
109
|
+
seen_objects[id] = copy
|
110
|
+
|
111
|
+
begin
|
112
|
+
copy.instance_variables.each do |variable|
|
113
|
+
value = copy.instance_variable_get(variable)
|
114
|
+
|
115
|
+
copy.instance_variable_set(variable, duplicate(value, seen_objects))
|
116
|
+
end
|
117
|
+
rescue StandardError # rubocop:todo Lint/SuppressedException
|
118
|
+
end
|
119
|
+
|
120
|
+
copy
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
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
@@ -5,6 +5,7 @@ require "bugsnag/version"
|
|
5
5
|
require "bugsnag/configuration"
|
6
6
|
require "bugsnag/meta_data"
|
7
7
|
require "bugsnag/report"
|
8
|
+
require "bugsnag/event"
|
8
9
|
require "bugsnag/cleaner"
|
9
10
|
require "bugsnag/helpers"
|
10
11
|
require "bugsnag/session_tracker"
|
@@ -28,10 +29,14 @@ require "bugsnag/middleware/rake"
|
|
28
29
|
require "bugsnag/middleware/classify_error"
|
29
30
|
require "bugsnag/middleware/delayed_job"
|
30
31
|
|
32
|
+
require "bugsnag/breadcrumb_type"
|
31
33
|
require "bugsnag/breadcrumbs/validator"
|
32
34
|
require "bugsnag/breadcrumbs/breadcrumb"
|
33
35
|
require "bugsnag/breadcrumbs/breadcrumbs"
|
34
36
|
|
37
|
+
require "bugsnag/utility/duplicator"
|
38
|
+
require "bugsnag/utility/metadata_delegate"
|
39
|
+
|
35
40
|
# rubocop:todo Metrics/ModuleLength
|
36
41
|
module Bugsnag
|
37
42
|
LOCK = Mutex.new
|
@@ -79,7 +84,12 @@ module Bugsnag
|
|
79
84
|
report = Report.new(exception, configuration, auto_notify)
|
80
85
|
|
81
86
|
# If this is an auto_notify we yield the block before the any middleware is run
|
82
|
-
|
87
|
+
begin
|
88
|
+
yield(report) if block_given? && auto_notify
|
89
|
+
rescue StandardError => e
|
90
|
+
configuration.warn("Error in internal notify block: #{e}")
|
91
|
+
configuration.warn("Error in internal notify block stacktrace: #{e.backtrace.inspect}")
|
92
|
+
end
|
83
93
|
|
84
94
|
if report.ignore?
|
85
95
|
configuration.debug("Not notifying #{report.exceptions.last[:errorClass]} due to ignore being signified in auto_notify block")
|
@@ -106,7 +116,12 @@ module Bugsnag
|
|
106
116
|
|
107
117
|
# If this is not an auto_notify then the block was provided by the user. This should be the last
|
108
118
|
# block that is run as it is the users "most specific" block.
|
109
|
-
|
119
|
+
begin
|
120
|
+
yield(report) if block_given? && !auto_notify
|
121
|
+
rescue StandardError => e
|
122
|
+
configuration.warn("Error in notify block: #{e}")
|
123
|
+
configuration.warn("Error in notify block stacktrace: #{e.backtrace.inspect}")
|
124
|
+
end
|
110
125
|
|
111
126
|
if report.ignore?
|
112
127
|
configuration.debug("Not notifying #{report.exceptions.last[:errorClass]} due to ignore being signified in user provided block")
|
@@ -122,6 +137,11 @@ module Bugsnag
|
|
122
137
|
report.severity_reason = initial_reason
|
123
138
|
end
|
124
139
|
|
140
|
+
if report.unhandled_overridden?
|
141
|
+
# let the dashboard know that the unhandled flag was overridden
|
142
|
+
report.severity_reason[:unhandledOverridden] = true
|
143
|
+
end
|
144
|
+
|
125
145
|
deliver_notification(report)
|
126
146
|
end
|
127
147
|
end
|
@@ -177,13 +197,36 @@ module Bugsnag
|
|
177
197
|
end
|
178
198
|
|
179
199
|
##
|
180
|
-
# Starts a session
|
200
|
+
# Starts a new session, which allows Bugsnag to track error rates across
|
201
|
+
# releases
|
181
202
|
#
|
182
|
-
#
|
203
|
+
# @return [void]
|
183
204
|
def start_session
|
184
205
|
session_tracker.start_session
|
185
206
|
end
|
186
207
|
|
208
|
+
##
|
209
|
+
# Stop any events being attributed to the current session until it is
|
210
|
+
# resumed or a new session is started
|
211
|
+
#
|
212
|
+
# @see resume_session
|
213
|
+
#
|
214
|
+
# @return [void]
|
215
|
+
def pause_session
|
216
|
+
session_tracker.pause_session
|
217
|
+
end
|
218
|
+
|
219
|
+
##
|
220
|
+
# Resume the current session if it was previously paused. If there is no
|
221
|
+
# current session, a new session will be started
|
222
|
+
#
|
223
|
+
# @see pause_session
|
224
|
+
#
|
225
|
+
# @return [Boolean] true if a paused session was resumed
|
226
|
+
def resume_session
|
227
|
+
session_tracker.resume_session
|
228
|
+
end
|
229
|
+
|
187
230
|
##
|
188
231
|
# Allow access to "before notify" callbacks as an array.
|
189
232
|
#
|
@@ -227,7 +270,7 @@ module Bugsnag
|
|
227
270
|
#
|
228
271
|
# @param name [String] the main breadcrumb name/message
|
229
272
|
# @param meta_data [Hash] String, Numeric, or Boolean meta data to attach
|
230
|
-
# @param type [String] the breadcrumb type,
|
273
|
+
# @param type [String] the breadcrumb type, see {Bugsnag::BreadcrumbType}
|
231
274
|
# @param auto [Symbol] set to :auto if the breadcrumb is automatically created
|
232
275
|
# @return [void]
|
233
276
|
def leave_breadcrumb(name, meta_data={}, type=Bugsnag::Breadcrumbs::MANUAL_BREADCRUMB_TYPE, auto=:manual)
|
@@ -240,7 +283,7 @@ module Bugsnag
|
|
240
283
|
# Skip if it's already invalid
|
241
284
|
return if breadcrumb.ignore?
|
242
285
|
|
243
|
-
# Run
|
286
|
+
# Run before_breadcrumb_callbacks
|
244
287
|
configuration.before_breadcrumb_callbacks.each do |c|
|
245
288
|
c.arity > 0 ? c.call(breadcrumb) : c.call
|
246
289
|
break if breadcrumb.ignore?
|
@@ -249,6 +292,10 @@ module Bugsnag
|
|
249
292
|
# Return early if ignored
|
250
293
|
return if breadcrumb.ignore?
|
251
294
|
|
295
|
+
# Run on_breadcrumb callbacks
|
296
|
+
configuration.on_breadcrumb_callbacks.call(breadcrumb)
|
297
|
+
return if breadcrumb.ignore?
|
298
|
+
|
252
299
|
# Validate again in case of callback alteration
|
253
300
|
validator.validate(breadcrumb)
|
254
301
|
|
@@ -265,7 +312,7 @@ module Bugsnag
|
|
265
312
|
# Returning false from an on_error callback will cause the error to be ignored
|
266
313
|
# and will prevent any remaining callbacks from being called
|
267
314
|
#
|
268
|
-
# @param callback [Proc]
|
315
|
+
# @param callback [Proc, Method, #call]
|
269
316
|
# @return [void]
|
270
317
|
def add_on_error(callback)
|
271
318
|
configuration.add_on_error(callback)
|
@@ -283,6 +330,44 @@ module Bugsnag
|
|
283
330
|
configuration.remove_on_error(callback)
|
284
331
|
end
|
285
332
|
|
333
|
+
##
|
334
|
+
# Add the given callback to the list of on_breadcrumb callbacks
|
335
|
+
#
|
336
|
+
# The on_breadcrumb callbacks will be called when a breadcrumb is left and
|
337
|
+
# are passed the {Breadcrumbs::Breadcrumb Breadcrumb} object
|
338
|
+
#
|
339
|
+
# Returning false from an on_breadcrumb callback will cause the breadcrumb
|
340
|
+
# to be ignored and will prevent any remaining callbacks from being called
|
341
|
+
#
|
342
|
+
# @param callback [Proc, Method, #call]
|
343
|
+
# @return [void]
|
344
|
+
def add_on_breadcrumb(callback)
|
345
|
+
configuration.add_on_breadcrumb(callback)
|
346
|
+
end
|
347
|
+
|
348
|
+
##
|
349
|
+
# Remove the given callback from the list of on_breadcrumb callbacks
|
350
|
+
#
|
351
|
+
# Note that this must be the same instance that was passed to
|
352
|
+
# {add_on_breadcrumb}, otherwise it will not be removed
|
353
|
+
#
|
354
|
+
# @param callback [Proc, Method, #call]
|
355
|
+
# @return [void]
|
356
|
+
def remove_on_breadcrumb(callback)
|
357
|
+
configuration.remove_on_breadcrumb(callback)
|
358
|
+
end
|
359
|
+
|
360
|
+
##
|
361
|
+
# Returns the current list of breadcrumbs
|
362
|
+
#
|
363
|
+
# This is a per-thread circular buffer, containing at most 'max_breadcrumbs'
|
364
|
+
# breadcrumbs
|
365
|
+
#
|
366
|
+
# @return [Bugsnag::Utility::CircularBuffer]
|
367
|
+
def breadcrumbs
|
368
|
+
configuration.breadcrumbs
|
369
|
+
end
|
370
|
+
|
286
371
|
##
|
287
372
|
# Returns the client's Cleaner object, or creates one if not yet created.
|
288
373
|
#
|
@@ -296,9 +381,56 @@ module Bugsnag
|
|
296
381
|
end
|
297
382
|
end
|
298
383
|
|
384
|
+
##
|
385
|
+
# Global metadata added to every event
|
386
|
+
#
|
387
|
+
# @return [Hash]
|
388
|
+
def metadata
|
389
|
+
configuration.metadata
|
390
|
+
end
|
391
|
+
|
392
|
+
##
|
393
|
+
# Add values to metadata
|
394
|
+
#
|
395
|
+
# @overload add_metadata(section, data)
|
396
|
+
# Merges data into the given section of metadata
|
397
|
+
# @param section [String, Symbol]
|
398
|
+
# @param data [Hash]
|
399
|
+
#
|
400
|
+
# @overload add_metadata(section, key, value)
|
401
|
+
# Sets key to value in the given section of metadata. If the value is nil
|
402
|
+
# the key will be deleted
|
403
|
+
# @param section [String, Symbol]
|
404
|
+
# @param key [String, Symbol]
|
405
|
+
# @param value
|
406
|
+
#
|
407
|
+
# @return [void]
|
408
|
+
def add_metadata(section, key_or_data, *args)
|
409
|
+
configuration.add_metadata(section, key_or_data, *args)
|
410
|
+
end
|
411
|
+
|
412
|
+
##
|
413
|
+
# Clear values from metadata
|
414
|
+
#
|
415
|
+
# @overload clear_metadata(section)
|
416
|
+
# Clears the given section of metadata
|
417
|
+
# @param section [String, Symbol]
|
418
|
+
#
|
419
|
+
# @overload clear_metadata(section, key)
|
420
|
+
# Clears the key in the given section of metadata
|
421
|
+
# @param section [String, Symbol]
|
422
|
+
# @param key [String, Symbol]
|
423
|
+
#
|
424
|
+
# @return [void]
|
425
|
+
def clear_metadata(section, *args)
|
426
|
+
configuration.clear_metadata(section, *args)
|
427
|
+
end
|
428
|
+
|
299
429
|
private
|
300
430
|
|
301
431
|
def should_deliver_notification?(exception, auto_notify)
|
432
|
+
return false unless configuration.enable_events
|
433
|
+
|
302
434
|
reason = abort_reason(exception, auto_notify)
|
303
435
|
configuration.debug(reason) unless reason.nil?
|
304
436
|
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.
|
4
|
+
version: 6.24.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-06 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,17 @@ 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
|
52
58
|
- lib/bugsnag/helpers.rb
|
53
59
|
- lib/bugsnag/integrations/delayed_job.rb
|
54
60
|
- lib/bugsnag/integrations/mailman.rb
|
55
61
|
- lib/bugsnag/integrations/mongo.rb
|
56
62
|
- lib/bugsnag/integrations/que.rb
|
57
63
|
- lib/bugsnag/integrations/rack.rb
|
64
|
+
- lib/bugsnag/integrations/rails/active_job.rb
|
58
65
|
- lib/bugsnag/integrations/rails/active_record_rescue.rb
|
59
66
|
- lib/bugsnag/integrations/rails/controller_methods.rb
|
60
67
|
- lib/bugsnag/integrations/rails/rails_breadcrumbs.rb
|
@@ -64,6 +71,7 @@ files:
|
|
64
71
|
- lib/bugsnag/integrations/shoryuken.rb
|
65
72
|
- lib/bugsnag/integrations/sidekiq.rb
|
66
73
|
- lib/bugsnag/meta_data.rb
|
74
|
+
- lib/bugsnag/middleware/active_job.rb
|
67
75
|
- lib/bugsnag/middleware/breadcrumbs.rb
|
68
76
|
- lib/bugsnag/middleware/callbacks.rb
|
69
77
|
- lib/bugsnag/middleware/classify_error.rb
|
@@ -88,6 +96,8 @@ files:
|
|
88
96
|
- lib/bugsnag/tasks.rb
|
89
97
|
- lib/bugsnag/tasks/bugsnag.rake
|
90
98
|
- lib/bugsnag/utility/circular_buffer.rb
|
99
|
+
- lib/bugsnag/utility/duplicator.rb
|
100
|
+
- lib/bugsnag/utility/metadata_delegate.rb
|
91
101
|
- lib/bugsnag/version.rb
|
92
102
|
- lib/generators/bugsnag/bugsnag_generator.rb
|
93
103
|
homepage: https://github.com/bugsnag/bugsnag-ruby
|