bugsnag 6.10.0 → 6.11.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/.rubocop_todo.yml +4 -0
- data/CHANGELOG.md +20 -0
- data/Gemfile +1 -0
- data/README.md +1 -0
- data/VERSION +1 -1
- data/features/fixtures/docker-compose.yml +13 -0
- data/features/fixtures/rails3/app/app/controllers/breadcrumbs_controller.rb +19 -0
- data/features/fixtures/rails3/app/app/controllers/session_tracking_controller.rb +10 -6
- data/features/fixtures/rails3/app/config/initializers/bugsnag.rb +8 -2
- data/features/fixtures/rails3/app/config/routes.rb +1 -0
- data/features/fixtures/rails4/app/Gemfile +5 -1
- data/features/fixtures/rails4/app/app/controllers/breadcrumbs_controller.rb +26 -0
- data/features/fixtures/rails4/app/app/controllers/mongo_controller.rb +23 -0
- data/features/fixtures/rails4/app/app/controllers/session_tracking_controller.rb +9 -5
- data/features/fixtures/rails4/app/app/jobs/application_job.rb +2 -0
- data/features/fixtures/rails4/app/app/jobs/notify_job.rb +5 -0
- data/features/fixtures/rails4/app/app/models/mongo_model.rb +6 -0
- data/features/fixtures/rails4/app/config/initializers/bugsnag.rb +7 -1
- data/features/fixtures/rails4/app/config/mongoid.yml +22 -0
- data/features/fixtures/rails4/app/config/routes.rb +2 -0
- data/features/fixtures/rails5/app/Gemfile +4 -0
- data/features/fixtures/rails5/app/app/controllers/breadcrumbs_controller.rb +24 -0
- data/features/fixtures/rails5/app/app/controllers/mongo_controller.rb +22 -0
- data/features/fixtures/rails5/app/app/controllers/session_tracking_controller.rb +9 -5
- data/features/fixtures/rails5/app/app/jobs/notify_job.rb +5 -0
- data/features/fixtures/rails5/app/app/models/mongo_model.rb +6 -0
- data/features/fixtures/rails5/app/config/initializers/bugsnag.rb +7 -1
- data/features/fixtures/rails5/app/config/mongoid.yml +23 -0
- data/features/fixtures/rails5/app/config/routes.rb +11 -1
- data/features/rails_features/auto_capture_sessions.feature +55 -5
- data/features/rails_features/breadcrumbs.feature +135 -0
- data/features/rails_features/mongo_breadcrumbs.feature +100 -0
- data/features/steps/ruby_notifier_steps.rb +6 -0
- data/lib/bugsnag.rb +59 -3
- data/lib/bugsnag/breadcrumbs/breadcrumb.rb +76 -0
- data/lib/bugsnag/breadcrumbs/breadcrumbs.rb +14 -0
- data/lib/bugsnag/breadcrumbs/validator.rb +59 -0
- data/lib/bugsnag/configuration.rb +103 -6
- data/lib/bugsnag/integrations/mongo.rb +132 -0
- data/lib/bugsnag/integrations/rails/rails_breadcrumbs.rb +118 -0
- data/lib/bugsnag/integrations/railtie.rb +28 -1
- data/lib/bugsnag/middleware/breadcrumbs.rb +21 -0
- data/lib/bugsnag/report.rb +30 -1
- data/lib/bugsnag/session_tracker.rb +1 -0
- data/lib/bugsnag/utility/circular_buffer.rb +62 -0
- data/spec/breadcrumbs/breadcrumb_spec.rb +93 -0
- data/spec/breadcrumbs/validator_spec.rb +200 -0
- data/spec/bugsnag_spec.rb +230 -0
- data/spec/configuration_spec.rb +176 -2
- data/spec/integrations/mongo_spec.rb +262 -0
- data/spec/report_spec.rb +149 -0
- data/spec/session_tracker_spec.rb +24 -2
- data/spec/utility/circular_buffer_spec.rb +98 -0
- metadata +27 -2
@@ -0,0 +1,76 @@
|
|
1
|
+
module Bugsnag::Breadcrumbs
|
2
|
+
class Breadcrumb
|
3
|
+
# @return [String] the breadcrumb name
|
4
|
+
attr_accessor :name
|
5
|
+
|
6
|
+
# @return [String] the breadcrumb type
|
7
|
+
attr_accessor :type
|
8
|
+
|
9
|
+
# @return [Hash, nil] metadata hash containing strings, numbers, or booleans, or nil
|
10
|
+
attr_accessor :meta_data
|
11
|
+
|
12
|
+
# @return [Boolean] set to `true` if the breadcrumb was automatically generated
|
13
|
+
attr_reader :auto
|
14
|
+
|
15
|
+
# @return [Time] a Time object referring to breadcrumb creation time
|
16
|
+
attr_reader :timestamp
|
17
|
+
|
18
|
+
##
|
19
|
+
# Creates a breadcrumb
|
20
|
+
#
|
21
|
+
# This will not have been validated, which must occur before this is attached to a report
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
#
|
25
|
+
# @param name [String] the breadcrumb name
|
26
|
+
# @param type [String] the breadcrumb type from Bugsnag::Breadcrumbs::VALID_BREADCRUMB_TYPES
|
27
|
+
# @param meta_data [Hash, nil] a hash containing strings, numbers, or booleans, or nil
|
28
|
+
# @param auto [Symbol] set to `:auto` if the breadcrumb is automatically generated
|
29
|
+
def initialize(name, type, meta_data, auto)
|
30
|
+
@should_ignore = false
|
31
|
+
self.name = name
|
32
|
+
self.type = type
|
33
|
+
self.meta_data = meta_data
|
34
|
+
|
35
|
+
# Use the symbol comparison to improve readability of breadcrumb creation
|
36
|
+
@auto = auto == :auto
|
37
|
+
|
38
|
+
# Store it as a timestamp for now
|
39
|
+
@timestamp = Time.now.utc
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Flags the breadcrumb to be ignored
|
44
|
+
#
|
45
|
+
# Ignored breadcrumbs will not be attached to a report
|
46
|
+
def ignore!
|
47
|
+
@should_ignore = true
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Checks if the `ignore!` method has been called
|
52
|
+
#
|
53
|
+
# Ignored breadcrumbs will not be attached to a report
|
54
|
+
#
|
55
|
+
# @return [True] if `ignore!` has been called
|
56
|
+
# @return [nil] if `ignore` has not been called
|
57
|
+
def ignore?
|
58
|
+
@should_ignore
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Outputs the breadcrumb data in a formatted hash
|
63
|
+
#
|
64
|
+
# These adhere to the breadcrumb format as defined in the Bugsnag error reporting API
|
65
|
+
#
|
66
|
+
# @return [Hash] Hash representation of the breadcrumb
|
67
|
+
def to_h
|
68
|
+
{
|
69
|
+
:name => @name,
|
70
|
+
:type => @type,
|
71
|
+
:metaData => @meta_data,
|
72
|
+
:timestamp => @timestamp.iso8601
|
73
|
+
}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Bugsnag::Breadcrumbs
|
2
|
+
MAX_NAME_LENGTH = 30
|
3
|
+
|
4
|
+
VALID_BREADCRUMB_TYPES = [
|
5
|
+
ERROR_BREADCRUMB_TYPE = "error",
|
6
|
+
MANUAL_BREADCRUMB_TYPE = "manual",
|
7
|
+
NAVIGATION_BREADCRUMB_TYPE = "navigation",
|
8
|
+
REQUEST_BREADCRUMB_TYPE = "request",
|
9
|
+
PROCESS_BREADCRUMB_TYPE = "process",
|
10
|
+
LOG_BREADCRUMB_TYPE = "log",
|
11
|
+
USER_BREADCRUMB_TYPE = "user",
|
12
|
+
STATE_BREADCRUMB_TYPE = "state"
|
13
|
+
].freeze
|
14
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'bugsnag/breadcrumbs/breadcrumbs'
|
2
|
+
|
3
|
+
module Bugsnag::Breadcrumbs
|
4
|
+
##
|
5
|
+
# Validates a given breadcrumb before it is stored
|
6
|
+
class Validator
|
7
|
+
##
|
8
|
+
# @param configuration [Bugsnag::Configuration] The current configuration
|
9
|
+
def initialize(configuration)
|
10
|
+
@configuration = configuration
|
11
|
+
end
|
12
|
+
|
13
|
+
##
|
14
|
+
# Validates a given breadcrumb.
|
15
|
+
#
|
16
|
+
# @param breadcrumb [Bugsnag::Breadcrumbs::Breadcrumb] the breadcrumb to be validated
|
17
|
+
def validate(breadcrumb)
|
18
|
+
# Check name length
|
19
|
+
if breadcrumb.name.size > Bugsnag::Breadcrumbs::MAX_NAME_LENGTH
|
20
|
+
@configuration.warn("Breadcrumb name trimmed to length #{Bugsnag::Breadcrumbs::MAX_NAME_LENGTH}. Original name: #{breadcrumb.name}")
|
21
|
+
breadcrumb.name = breadcrumb.name.slice(0...Bugsnag::Breadcrumbs::MAX_NAME_LENGTH)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Check meta_data hash doesn't contain complex values
|
25
|
+
breadcrumb.meta_data = breadcrumb.meta_data.select do |k, v|
|
26
|
+
if valid_meta_data_type?(v)
|
27
|
+
true
|
28
|
+
else
|
29
|
+
@configuration.warn("Breadcrumb #{breadcrumb.name} meta_data #{k}:#{v} has been dropped for having an invalid data type")
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Check type is valid, set to manual otherwise
|
35
|
+
unless Bugsnag::Breadcrumbs::VALID_BREADCRUMB_TYPES.include?(breadcrumb.type)
|
36
|
+
@configuration.warn("Invalid type: #{breadcrumb.type} for breadcrumb: #{breadcrumb.name}, defaulting to #{Bugsnag::Breadcrumbs::MANUAL_BREADCRUMB_TYPE}")
|
37
|
+
breadcrumb.type = Bugsnag::Breadcrumbs::MANUAL_BREADCRUMB_TYPE
|
38
|
+
end
|
39
|
+
|
40
|
+
# If auto is true, check type is in enabled_automatic_breadcrumb_types
|
41
|
+
return unless breadcrumb.auto && !@configuration.enabled_automatic_breadcrumb_types.include?(breadcrumb.type)
|
42
|
+
|
43
|
+
@configuration.warn("Automatic breadcrumb of type #{breadcrumb.type} ignored: #{breadcrumb.name}")
|
44
|
+
breadcrumb.ignore!
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
##
|
50
|
+
# Tests whether the meta_data types are non-complex objects.
|
51
|
+
#
|
52
|
+
# Acceptable types are String, Numeric, TrueClass, FalseClass, and nil.
|
53
|
+
#
|
54
|
+
# @param value [Object] the object to be type checked
|
55
|
+
def valid_meta_data_type?(value)
|
56
|
+
value.nil? || value.is_a?(String) || value.is_a?(Numeric) || value.is_a?(FalseClass) || value.is_a?(TrueClass)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -8,6 +8,9 @@ require "bugsnag/middleware/ignore_error_class"
|
|
8
8
|
require "bugsnag/middleware/suggestion_data"
|
9
9
|
require "bugsnag/middleware/classify_error"
|
10
10
|
require "bugsnag/middleware/session_data"
|
11
|
+
require "bugsnag/middleware/breadcrumbs"
|
12
|
+
require "bugsnag/utility/circular_buffer"
|
13
|
+
require "bugsnag/breadcrumbs/breadcrumbs"
|
11
14
|
|
12
15
|
module Bugsnag
|
13
16
|
class Configuration
|
@@ -22,7 +25,6 @@ module Bugsnag
|
|
22
25
|
attr_accessor :app_version
|
23
26
|
attr_accessor :app_type
|
24
27
|
attr_accessor :meta_data_filters
|
25
|
-
attr_accessor :endpoint
|
26
28
|
attr_accessor :logger
|
27
29
|
attr_accessor :middleware
|
28
30
|
attr_accessor :internal_middleware
|
@@ -35,12 +37,38 @@ module Bugsnag
|
|
35
37
|
attr_accessor :ignore_classes
|
36
38
|
attr_accessor :auto_capture_sessions
|
37
39
|
attr_accessor :track_sessions
|
38
|
-
|
40
|
+
|
41
|
+
##
|
42
|
+
# @return [String] URL error notifications will be delivered to
|
43
|
+
attr_reader :notify_endpoint
|
44
|
+
alias :endpoint :notify_endpoint
|
45
|
+
|
46
|
+
##
|
47
|
+
# @return [String] URL session notifications will be delivered to
|
48
|
+
attr_reader :session_endpoint
|
49
|
+
|
50
|
+
##
|
51
|
+
# @return [Boolean] whether any sessions types will be delivered
|
52
|
+
attr_reader :enable_sessions
|
53
|
+
|
54
|
+
##
|
55
|
+
# @return [Array<String>] strings indicating allowable automatic breadcrumb types
|
56
|
+
attr_accessor :enabled_automatic_breadcrumb_types
|
57
|
+
|
58
|
+
##
|
59
|
+
# @return [Array<#call>] callables to be run before a breadcrumb is logged
|
60
|
+
attr_accessor :before_breadcrumb_callbacks
|
61
|
+
|
62
|
+
##
|
63
|
+
# @return [Integer] the maximum allowable amount of breadcrumbs per thread
|
64
|
+
attr_reader :max_breadcrumbs
|
39
65
|
|
40
66
|
API_KEY_REGEX = /[0-9a-f]{32}/i
|
41
67
|
THREAD_LOCAL_NAME = "bugsnag_req_data"
|
42
|
-
|
68
|
+
|
69
|
+
DEFAULT_NOTIFY_ENDPOINT = "https://notify.bugsnag.com"
|
43
70
|
DEFAULT_SESSION_ENDPOINT = "https://sessions.bugsnag.com"
|
71
|
+
DEFAULT_ENDPOINT = DEFAULT_NOTIFY_ENDPOINT
|
44
72
|
|
45
73
|
DEFAULT_META_DATA_FILTERS = [
|
46
74
|
/authorization/i,
|
@@ -51,6 +79,8 @@ module Bugsnag
|
|
51
79
|
"rack.request.form_vars"
|
52
80
|
].freeze
|
53
81
|
|
82
|
+
DEFAULT_MAX_BREADCRUMBS = 25
|
83
|
+
|
54
84
|
alias :track_sessions :auto_capture_sessions
|
55
85
|
alias :track_sessions= :auto_capture_sessions=
|
56
86
|
|
@@ -62,12 +92,23 @@ module Bugsnag
|
|
62
92
|
self.send_environment = false
|
63
93
|
self.send_code = true
|
64
94
|
self.meta_data_filters = Set.new(DEFAULT_META_DATA_FILTERS)
|
65
|
-
self.endpoint = DEFAULT_ENDPOINT
|
66
95
|
self.hostname = default_hostname
|
67
96
|
self.timeout = 15
|
68
97
|
self.notify_release_stages = nil
|
69
|
-
self.auto_capture_sessions =
|
70
|
-
|
98
|
+
self.auto_capture_sessions = true
|
99
|
+
|
100
|
+
# All valid breadcrumb types should be allowable initially
|
101
|
+
self.enabled_automatic_breadcrumb_types = Bugsnag::Breadcrumbs::VALID_BREADCRUMB_TYPES.dup
|
102
|
+
self.before_breadcrumb_callbacks = []
|
103
|
+
|
104
|
+
# Store max_breadcrumbs here instead of outputting breadcrumbs.max_items
|
105
|
+
# to avoid infinite recursion when creating breadcrumb buffer
|
106
|
+
@max_breadcrumbs = DEFAULT_MAX_BREADCRUMBS
|
107
|
+
|
108
|
+
# These are set exclusively using the "set_endpoints" method
|
109
|
+
@notify_endpoint = DEFAULT_NOTIFY_ENDPOINT
|
110
|
+
@session_endpoint = DEFAULT_SESSION_ENDPOINT
|
111
|
+
@enable_sessions = true
|
71
112
|
|
72
113
|
# SystemExit and SignalException are common Exception types seen with
|
73
114
|
# successful exits and are not automatically reported to Bugsnag
|
@@ -95,6 +136,7 @@ module Bugsnag
|
|
95
136
|
self.internal_middleware.use Bugsnag::Middleware::SuggestionData
|
96
137
|
self.internal_middleware.use Bugsnag::Middleware::ClassifyError
|
97
138
|
self.internal_middleware.use Bugsnag::Middleware::SessionData
|
139
|
+
self.internal_middleware.use Bugsnag::Middleware::Breadcrumbs
|
98
140
|
|
99
141
|
self.middleware = Bugsnag::MiddlewareStack.new
|
100
142
|
self.middleware.use Bugsnag::Middleware::Callbacks
|
@@ -190,6 +232,61 @@ module Bugsnag
|
|
190
232
|
self.proxy_password = proxy.password
|
191
233
|
end
|
192
234
|
|
235
|
+
##
|
236
|
+
# Sets the maximum allowable amount of breadcrumbs
|
237
|
+
#
|
238
|
+
# @param [Integer] the new maximum breadcrumb limit
|
239
|
+
def max_breadcrumbs=(new_max_breadcrumbs)
|
240
|
+
@max_breadcrumbs = new_max_breadcrumbs
|
241
|
+
breadcrumbs.max_items = new_max_breadcrumbs
|
242
|
+
end
|
243
|
+
|
244
|
+
##
|
245
|
+
# Returns the breadcrumb circular buffer
|
246
|
+
#
|
247
|
+
# @return [Bugsnag::Utility::CircularBuffer] a thread based circular buffer containing breadcrumbs
|
248
|
+
def breadcrumbs
|
249
|
+
request_data[:breadcrumbs] ||= Bugsnag::Utility::CircularBuffer.new(@max_breadcrumbs)
|
250
|
+
end
|
251
|
+
|
252
|
+
# Sets the notification endpoint
|
253
|
+
#
|
254
|
+
# @param new_notify_endpoint [String] The URL to deliver error notifications to
|
255
|
+
#
|
256
|
+
# @deprecated Use {#set_endpoints} instead
|
257
|
+
def endpoint=(new_notify_endpoint)
|
258
|
+
warn("The 'endpoint' configuration option is deprecated. The 'set_endpoints' method should be used instead")
|
259
|
+
set_endpoints(new_notify_endpoint, session_endpoint) # Pass the existing session_endpoint through so it doesn't get overwritten
|
260
|
+
end
|
261
|
+
|
262
|
+
##
|
263
|
+
# Sets the sessions endpoint
|
264
|
+
#
|
265
|
+
# @param new_session_endpoint [String] The URL to deliver session notifications to
|
266
|
+
#
|
267
|
+
# @deprecated Use {#set_endpoints} instead
|
268
|
+
def session_endpoint=(new_session_endpoint)
|
269
|
+
warn("The 'session_endpoint' configuration option is deprecated. The 'set_endpoints' method should be used instead")
|
270
|
+
set_endpoints(notify_endpoint, new_session_endpoint) # Pass the existing notify_endpoint through so it doesn't get overwritten
|
271
|
+
end
|
272
|
+
|
273
|
+
##
|
274
|
+
# Sets the notification and session endpoints
|
275
|
+
#
|
276
|
+
# @param new_notify_endpoint [String] The URL to deliver error notifications to
|
277
|
+
# @param new_session_endpoint [String] The URL to deliver session notifications to
|
278
|
+
def set_endpoints(new_notify_endpoint, new_session_endpoint)
|
279
|
+
@notify_endpoint = new_notify_endpoint
|
280
|
+
@session_endpoint = new_session_endpoint
|
281
|
+
end
|
282
|
+
|
283
|
+
##
|
284
|
+
# Disables session tracking and delivery. Cannot be undone
|
285
|
+
def disable_sessions
|
286
|
+
self.auto_capture_sessions = false
|
287
|
+
@enable_sessions = false
|
288
|
+
end
|
289
|
+
|
193
290
|
private
|
194
291
|
|
195
292
|
PROG_NAME = "[Bugsnag]"
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'mongo'
|
2
|
+
require 'bugsnag/breadcrumbs/breadcrumbs'
|
3
|
+
|
4
|
+
module Bugsnag
|
5
|
+
##
|
6
|
+
# Subscribes to, and creates breadcrumbs from, mongo_ruby_driver events
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
class MongoBreadcrumbSubscriber
|
10
|
+
MONGO_MESSAGE_PREFIX = "Mongo query "
|
11
|
+
MONGO_EVENT_PREFIX = "mongo."
|
12
|
+
MONGO_COMMAND_KEY = :bugsnag_mongo_commands
|
13
|
+
MAX_FILTER_DEPTH = 5
|
14
|
+
|
15
|
+
##
|
16
|
+
# Listens to the 'started' event, storing the command for later usage
|
17
|
+
#
|
18
|
+
# @param event [Mongo::Event::Base] the mongo_ruby_driver generated event
|
19
|
+
def started(event)
|
20
|
+
leave_command(event)
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Listens to the 'succeeded' event, leaving a breadcrumb
|
25
|
+
#
|
26
|
+
# @param event [Mongo::Event::Base] the mongo_ruby_driver generated event
|
27
|
+
def succeeded(event)
|
28
|
+
leave_mongo_breadcrumb("succeeded", event)
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Listens to the 'failed' event, leaving a breadcrumb
|
33
|
+
#
|
34
|
+
# @param event [Mongo::Event::Base] the mongo_ruby_driver generated event
|
35
|
+
def failed(event)
|
36
|
+
leave_mongo_breadcrumb("failed", event)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
##
|
42
|
+
# Generates breadcrumb data from an event
|
43
|
+
#
|
44
|
+
# @param event_name [String] the type of event
|
45
|
+
# @param event [Mongo::Event::Base] the mongo_ruby_driver generated event
|
46
|
+
def leave_mongo_breadcrumb(event_name, event)
|
47
|
+
message = MONGO_MESSAGE_PREFIX + event_name
|
48
|
+
meta_data = {
|
49
|
+
:event_name => MONGO_EVENT_PREFIX + event_name,
|
50
|
+
:command_name => event.command_name,
|
51
|
+
:database_name => event.database_name,
|
52
|
+
:operation_id => event.operation_id,
|
53
|
+
:request_id => event.request_id,
|
54
|
+
:duration => event.duration
|
55
|
+
}
|
56
|
+
if (command = pop_command(event.request_id))
|
57
|
+
collection_key = event.command_name == "getMore" ? "collection" : event.command_name
|
58
|
+
meta_data[:collection] = command[collection_key]
|
59
|
+
unless command["filter"].nil?
|
60
|
+
filter = sanitize_filter_hash(command["filter"])
|
61
|
+
meta_data[:filter] = JSON.dump(filter)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
meta_data[:message] = event.message if defined?(event.message)
|
65
|
+
|
66
|
+
Bugsnag.leave_breadcrumb(message, meta_data, Bugsnag::Breadcrumbs::PROCESS_BREADCRUMB_TYPE, :auto)
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Removes values from filter hashes, replacing them with '?'
|
71
|
+
#
|
72
|
+
# @param filter_hash [Hash] the filter hash for the mongo transaction
|
73
|
+
# @param depth [Integer] the current filter depth
|
74
|
+
#
|
75
|
+
# @return [Hash] the filtered hash
|
76
|
+
def sanitize_filter_hash(filter_hash, depth = 0)
|
77
|
+
filter_hash.each_with_object({}) do |(key, value), output|
|
78
|
+
output[key] = sanitize_filter_value(value, depth)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Transforms a value element into a useful, redacted, version
|
84
|
+
#
|
85
|
+
# @param value [Object] the filter value
|
86
|
+
# @param depth [Integer] the current filter depth
|
87
|
+
#
|
88
|
+
# @return [Array, Hash, String] the sanitized value
|
89
|
+
def sanitize_filter_value(value, depth)
|
90
|
+
depth += 1
|
91
|
+
if depth >= MAX_FILTER_DEPTH
|
92
|
+
'[MAX_FILTER_DEPTH_REACHED]'
|
93
|
+
elsif value.is_a?(Array)
|
94
|
+
value.map { |array_value| sanitize_filter_value(array_value, depth) }
|
95
|
+
elsif value.is_a?(Hash)
|
96
|
+
sanitize_filter_hash(value, depth)
|
97
|
+
else
|
98
|
+
'?'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
##
|
103
|
+
# Stores the mongo command in the request data by the request_id
|
104
|
+
#
|
105
|
+
# @param event [Mongo::Event::Base] the mongo_ruby_driver generated event
|
106
|
+
def leave_command(event)
|
107
|
+
event_commands[event.request_id] = event.command
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# Removes and retrieves a stored command from the request data
|
112
|
+
#
|
113
|
+
# @param request_id [String] the id of the mongo_ruby_driver event
|
114
|
+
#
|
115
|
+
# @return [Hash, nil] the requested command, or nil if not found
|
116
|
+
def pop_command(request_id)
|
117
|
+
event_commands.delete(request_id)
|
118
|
+
end
|
119
|
+
|
120
|
+
##
|
121
|
+
# Provides access to a thread-based mongo event command hash
|
122
|
+
#
|
123
|
+
# @return [Hash] the hash of mongo event commands
|
124
|
+
def event_commands
|
125
|
+
Bugsnag.configuration.request_data[MONGO_COMMAND_KEY] ||= {}
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
##
|
131
|
+
# Add the subscriber to the global Mongo monitoring object
|
132
|
+
Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::COMMAND, Bugsnag::MongoBreadcrumbSubscriber.new)
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require "bugsnag/breadcrumbs/breadcrumbs"
|
2
|
+
|
3
|
+
module Bugsnag::Rails
|
4
|
+
DEFAULT_RAILS_BREADCRUMBS = [
|
5
|
+
{
|
6
|
+
:id => "perform_action.action_cable",
|
7
|
+
:message => "Perform ActionCable",
|
8
|
+
:type => Bugsnag::Breadcrumbs::PROCESS_BREADCRUMB_TYPE,
|
9
|
+
:allowed_data => [
|
10
|
+
:channel_class,
|
11
|
+
:action
|
12
|
+
]
|
13
|
+
},
|
14
|
+
{
|
15
|
+
:id => "perform_start.active_job",
|
16
|
+
:message => "Start perform ActiveJob",
|
17
|
+
:type => Bugsnag::Breadcrumbs::PROCESS_BREADCRUMB_TYPE,
|
18
|
+
:allowed_data => []
|
19
|
+
},
|
20
|
+
{
|
21
|
+
:id => "cache_read.active_support",
|
22
|
+
:message => "Read cache",
|
23
|
+
:type => Bugsnag::Breadcrumbs::PROCESS_BREADCRUMB_TYPE,
|
24
|
+
:allowed_data => [
|
25
|
+
:key,
|
26
|
+
:hit,
|
27
|
+
:super_operation
|
28
|
+
]
|
29
|
+
},
|
30
|
+
{
|
31
|
+
:id => "cache_fetch_hit.active_support",
|
32
|
+
:message => "Fetch cache hit",
|
33
|
+
:type => Bugsnag::Breadcrumbs::PROCESS_BREADCRUMB_TYPE,
|
34
|
+
:allowed_data => [
|
35
|
+
:key
|
36
|
+
]
|
37
|
+
},
|
38
|
+
{
|
39
|
+
:id => "sql.active_record",
|
40
|
+
:message => "ActiveRecord SQL query",
|
41
|
+
:type => Bugsnag::Breadcrumbs::PROCESS_BREADCRUMB_TYPE,
|
42
|
+
:allowed_data => [
|
43
|
+
:name,
|
44
|
+
:connection_id,
|
45
|
+
:cached
|
46
|
+
]
|
47
|
+
},
|
48
|
+
{
|
49
|
+
:id => "start_processing.action_controller",
|
50
|
+
:message => "Controller started processing",
|
51
|
+
:type => Bugsnag::Breadcrumbs::REQUEST_BREADCRUMB_TYPE,
|
52
|
+
:allowed_data => [
|
53
|
+
:controller,
|
54
|
+
:action,
|
55
|
+
:method,
|
56
|
+
:path
|
57
|
+
]
|
58
|
+
},
|
59
|
+
{
|
60
|
+
:id => "process_action.action_controller",
|
61
|
+
:message => "Controller action processed",
|
62
|
+
:type => Bugsnag::Breadcrumbs::REQUEST_BREADCRUMB_TYPE,
|
63
|
+
:allowed_data => [
|
64
|
+
:controller,
|
65
|
+
:action,
|
66
|
+
:method,
|
67
|
+
:status,
|
68
|
+
:db_runtime
|
69
|
+
]
|
70
|
+
},
|
71
|
+
{
|
72
|
+
:id => "redirect_to.action_controller",
|
73
|
+
:message => "Controller redirect",
|
74
|
+
:type => Bugsnag::Breadcrumbs::REQUEST_BREADCRUMB_TYPE,
|
75
|
+
:allowed_data => [
|
76
|
+
:status,
|
77
|
+
:location
|
78
|
+
]
|
79
|
+
},
|
80
|
+
{
|
81
|
+
:id => "halted_callback.action_controller",
|
82
|
+
:message => "Controller halted via callback",
|
83
|
+
:type => Bugsnag::Breadcrumbs::REQUEST_BREADCRUMB_TYPE,
|
84
|
+
:allowed_data => [
|
85
|
+
:filter
|
86
|
+
]
|
87
|
+
},
|
88
|
+
{
|
89
|
+
:id => "render_template.action_view",
|
90
|
+
:message => "ActionView template rendered",
|
91
|
+
:type => Bugsnag::Breadcrumbs::REQUEST_BREADCRUMB_TYPE,
|
92
|
+
:allowed_data => [
|
93
|
+
:identifier,
|
94
|
+
:layout
|
95
|
+
]
|
96
|
+
},
|
97
|
+
{
|
98
|
+
:id => "render_partial.action_view",
|
99
|
+
:message => "ActionView partial rendered",
|
100
|
+
:type => Bugsnag::Breadcrumbs::REQUEST_BREADCRUMB_TYPE,
|
101
|
+
:allowed_data => [
|
102
|
+
:identifier
|
103
|
+
]
|
104
|
+
},
|
105
|
+
{
|
106
|
+
:id => "deliver.action_mailer",
|
107
|
+
:message => "ActionMail delivered",
|
108
|
+
:type => Bugsnag::Breadcrumbs::REQUEST_BREADCRUMB_TYPE,
|
109
|
+
:allowed_data => [
|
110
|
+
:mailer,
|
111
|
+
:message_id,
|
112
|
+
:from,
|
113
|
+
:date,
|
114
|
+
:perform_deliveries
|
115
|
+
]
|
116
|
+
}
|
117
|
+
]
|
118
|
+
end
|