bugsnag 6.10.0 → 6.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +4 -0
  3. data/CHANGELOG.md +20 -0
  4. data/Gemfile +1 -0
  5. data/README.md +1 -0
  6. data/VERSION +1 -1
  7. data/features/fixtures/docker-compose.yml +13 -0
  8. data/features/fixtures/rails3/app/app/controllers/breadcrumbs_controller.rb +19 -0
  9. data/features/fixtures/rails3/app/app/controllers/session_tracking_controller.rb +10 -6
  10. data/features/fixtures/rails3/app/config/initializers/bugsnag.rb +8 -2
  11. data/features/fixtures/rails3/app/config/routes.rb +1 -0
  12. data/features/fixtures/rails4/app/Gemfile +5 -1
  13. data/features/fixtures/rails4/app/app/controllers/breadcrumbs_controller.rb +26 -0
  14. data/features/fixtures/rails4/app/app/controllers/mongo_controller.rb +23 -0
  15. data/features/fixtures/rails4/app/app/controllers/session_tracking_controller.rb +9 -5
  16. data/features/fixtures/rails4/app/app/jobs/application_job.rb +2 -0
  17. data/features/fixtures/rails4/app/app/jobs/notify_job.rb +5 -0
  18. data/features/fixtures/rails4/app/app/models/mongo_model.rb +6 -0
  19. data/features/fixtures/rails4/app/config/initializers/bugsnag.rb +7 -1
  20. data/features/fixtures/rails4/app/config/mongoid.yml +22 -0
  21. data/features/fixtures/rails4/app/config/routes.rb +2 -0
  22. data/features/fixtures/rails5/app/Gemfile +4 -0
  23. data/features/fixtures/rails5/app/app/controllers/breadcrumbs_controller.rb +24 -0
  24. data/features/fixtures/rails5/app/app/controllers/mongo_controller.rb +22 -0
  25. data/features/fixtures/rails5/app/app/controllers/session_tracking_controller.rb +9 -5
  26. data/features/fixtures/rails5/app/app/jobs/notify_job.rb +5 -0
  27. data/features/fixtures/rails5/app/app/models/mongo_model.rb +6 -0
  28. data/features/fixtures/rails5/app/config/initializers/bugsnag.rb +7 -1
  29. data/features/fixtures/rails5/app/config/mongoid.yml +23 -0
  30. data/features/fixtures/rails5/app/config/routes.rb +11 -1
  31. data/features/rails_features/auto_capture_sessions.feature +55 -5
  32. data/features/rails_features/breadcrumbs.feature +135 -0
  33. data/features/rails_features/mongo_breadcrumbs.feature +100 -0
  34. data/features/steps/ruby_notifier_steps.rb +6 -0
  35. data/lib/bugsnag.rb +59 -3
  36. data/lib/bugsnag/breadcrumbs/breadcrumb.rb +76 -0
  37. data/lib/bugsnag/breadcrumbs/breadcrumbs.rb +14 -0
  38. data/lib/bugsnag/breadcrumbs/validator.rb +59 -0
  39. data/lib/bugsnag/configuration.rb +103 -6
  40. data/lib/bugsnag/integrations/mongo.rb +132 -0
  41. data/lib/bugsnag/integrations/rails/rails_breadcrumbs.rb +118 -0
  42. data/lib/bugsnag/integrations/railtie.rb +28 -1
  43. data/lib/bugsnag/middleware/breadcrumbs.rb +21 -0
  44. data/lib/bugsnag/report.rb +30 -1
  45. data/lib/bugsnag/session_tracker.rb +1 -0
  46. data/lib/bugsnag/utility/circular_buffer.rb +62 -0
  47. data/spec/breadcrumbs/breadcrumb_spec.rb +93 -0
  48. data/spec/breadcrumbs/validator_spec.rb +200 -0
  49. data/spec/bugsnag_spec.rb +230 -0
  50. data/spec/configuration_spec.rb +176 -2
  51. data/spec/integrations/mongo_spec.rb +262 -0
  52. data/spec/report_spec.rb +149 -0
  53. data/spec/session_tracker_spec.rb +24 -2
  54. data/spec/utility/circular_buffer_spec.rb +98 -0
  55. 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
- attr_accessor :session_endpoint
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
- DEFAULT_ENDPOINT = "https://notify.bugsnag.com"
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 = false
70
- self.session_endpoint = DEFAULT_SESSION_ENDPOINT
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