sentry-raven 1.1.0 → 3.1.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 (69) hide show
  1. checksums.yaml +5 -5
  2. data/.craft.yml +19 -0
  3. data/.scripts/bump-version.rb +5 -0
  4. data/CHANGELOG.md +703 -0
  5. data/Gemfile +37 -0
  6. data/Makefile +3 -0
  7. data/README.md +116 -18
  8. data/Rakefile +30 -0
  9. data/exe/raven +32 -0
  10. data/lib/raven/backtrace.rb +17 -8
  11. data/lib/raven/base.rb +45 -194
  12. data/lib/raven/breadcrumbs/active_support_logger.rb +25 -0
  13. data/lib/raven/breadcrumbs/logger.rb +3 -0
  14. data/lib/raven/breadcrumbs/sentry_logger.rb +73 -0
  15. data/lib/raven/breadcrumbs.rb +76 -0
  16. data/lib/raven/cli.rb +31 -39
  17. data/lib/raven/client.rb +45 -32
  18. data/lib/raven/configuration.rb +427 -130
  19. data/lib/raven/context.rb +33 -6
  20. data/lib/raven/core_ext/object/deep_dup.rb +57 -0
  21. data/lib/raven/core_ext/object/duplicable.rb +153 -0
  22. data/lib/raven/event.rb +194 -206
  23. data/lib/raven/helpers/deprecation_helper.rb +17 -0
  24. data/lib/raven/instance.rb +249 -0
  25. data/lib/raven/integrations/delayed_job.rb +25 -23
  26. data/lib/raven/integrations/rack-timeout.rb +22 -0
  27. data/lib/raven/integrations/rack.rb +40 -24
  28. data/lib/raven/integrations/rails/active_job.rb +52 -20
  29. data/lib/raven/integrations/rails/backtrace_cleaner.rb +29 -0
  30. data/lib/raven/integrations/rails/controller_transaction.rb +13 -0
  31. data/lib/raven/integrations/rails/overrides/debug_exceptions_catcher.rb +2 -2
  32. data/lib/raven/integrations/rails.rb +39 -7
  33. data/lib/raven/integrations/rake.rb +7 -2
  34. data/lib/raven/integrations/sidekiq/cleanup_middleware.rb +13 -0
  35. data/lib/raven/integrations/sidekiq/error_handler.rb +38 -0
  36. data/lib/raven/integrations/sidekiq.rb +6 -48
  37. data/lib/raven/integrations/tasks.rb +1 -1
  38. data/lib/raven/interface.rb +25 -0
  39. data/lib/raven/interfaces/exception.rb +5 -8
  40. data/lib/raven/interfaces/http.rb +5 -12
  41. data/lib/raven/interfaces/message.rb +10 -6
  42. data/lib/raven/interfaces/single_exception.rb +1 -5
  43. data/lib/raven/interfaces/stack_trace.rb +23 -30
  44. data/lib/raven/linecache.rb +35 -23
  45. data/lib/raven/logger.rb +13 -16
  46. data/lib/raven/processor/cookies.rb +27 -7
  47. data/lib/raven/processor/http_headers.rb +55 -0
  48. data/lib/raven/processor/post_data.rb +16 -3
  49. data/lib/raven/processor/removecircularreferences.rb +12 -8
  50. data/lib/raven/processor/removestacktrace.rb +17 -6
  51. data/lib/raven/processor/sanitizedata.rb +92 -37
  52. data/lib/raven/processor/utf8conversion.rb +39 -14
  53. data/lib/raven/processor.rb +5 -1
  54. data/lib/raven/transports/http.rb +31 -22
  55. data/lib/raven/transports/stdout.rb +20 -0
  56. data/lib/raven/transports.rb +6 -10
  57. data/lib/raven/utils/context_filter.rb +42 -0
  58. data/lib/raven/utils/deep_merge.rb +6 -12
  59. data/lib/raven/utils/exception_cause_chain.rb +20 -0
  60. data/lib/raven/utils/real_ip.rb +62 -0
  61. data/lib/raven/utils/request_id.rb +16 -0
  62. data/lib/raven/version.rb +2 -1
  63. data/lib/sentry-raven-without-integrations.rb +6 -1
  64. data/lib/sentry_raven_without_integrations.rb +1 -0
  65. data/sentry-raven.gemspec +28 -0
  66. metadata +44 -127
  67. data/lib/raven/error.rb +0 -4
  68. data/lib/raven/interfaces.rb +0 -34
  69. data/lib/raven/okjson.rb +0 -614
@@ -0,0 +1,249 @@
1
+ module Raven
2
+ # A copy of Raven's base module class methods, minus some of the integration
3
+ # and global hooks since it's meant to be used explicitly. Useful for
4
+ # sending errors to multiple sentry projects in a large application.
5
+ #
6
+ # @example
7
+ # class Foo
8
+ # def initialize
9
+ # @other_raven = Raven::Instance.new
10
+ # @other_raven.configure do |config|
11
+ # config.server = 'http://...'
12
+ # end
13
+ # end
14
+ #
15
+ # def foo
16
+ # # ...
17
+ # rescue => e
18
+ # @other_raven.capture_exception(e)
19
+ # end
20
+ # end
21
+ class Instance
22
+ # See Raven::Client.
23
+ attr_writer :client
24
+
25
+ # See Raven::Configuration.
26
+ attr_accessor :configuration
27
+
28
+ def initialize(context = nil, config = nil)
29
+ @context = @explicit_context = context
30
+ self.configuration = config || Configuration.new
31
+ end
32
+
33
+ def context
34
+ if @explicit_context
35
+ @context ||= Context.new
36
+ else
37
+ Context.current
38
+ end
39
+ end
40
+
41
+ def logger
42
+ configuration.logger
43
+ end
44
+
45
+ # The client object is responsible for delivering formatted data to the
46
+ # Sentry server.
47
+ def client
48
+ @client ||= Client.new(configuration)
49
+ end
50
+
51
+ # Tell the log that the client is good to go
52
+ def report_status
53
+ return unless configuration.enabled_in_current_env?
54
+ return if configuration.silence_ready
55
+
56
+ if configuration.capture_allowed?
57
+ logger.info "Raven #{VERSION} ready to catch errors"
58
+ else
59
+ logger.info "Raven #{VERSION} configured not to capture errors: #{configuration.error_messages}"
60
+ end
61
+ end
62
+
63
+ # Call this method to modify defaults in your initializers.
64
+ #
65
+ # @example
66
+ # Raven.configure do |config|
67
+ # config.server = 'http://...'
68
+ # end
69
+ def configure
70
+ yield(configuration) if block_given?
71
+
72
+ self.client = Client.new(configuration)
73
+ report_status
74
+ client
75
+ end
76
+
77
+ # Send an event to the configured Sentry server
78
+ #
79
+ # @example
80
+ # evt = Raven::Event.new(:message => "An errore)
81
+ # Raven.send_event(evt)
82
+ def send_event(event, hint = nil)
83
+ client.send_event(event, hint)
84
+ end
85
+
86
+ # Capture and process any exceptions from the given block.
87
+ #
88
+ # @example
89
+ # Raven.capture do
90
+ # MyApp.run
91
+ # end
92
+ def capture(options = {})
93
+ if block_given?
94
+ begin
95
+ yield
96
+ rescue Error
97
+ raise # Don't capture Raven errors
98
+ rescue Exception => e
99
+ capture_type(e, options)
100
+ raise
101
+ end
102
+ else
103
+ install_at_exit_hook(options)
104
+ end
105
+ end
106
+
107
+ def capture_type(obj, options = {})
108
+ unless configuration.capture_allowed?(obj)
109
+ logger.debug("#{obj} excluded from capture: #{configuration.error_messages}")
110
+ return false
111
+ end
112
+
113
+ message_or_exc = obj.is_a?(String) ? "message" : "exception"
114
+ options = options.deep_dup
115
+ options[:configuration] = configuration
116
+ options[:context] = context
117
+ options[:breadcrumbs] = breadcrumbs
118
+
119
+ if evt = Event.send("from_" + message_or_exc, obj, options)
120
+ yield evt if block_given?
121
+ if configuration.async?
122
+ begin
123
+ # We have to convert to a JSON-like hash, because background job
124
+ # processors (esp ActiveJob) may not like weird types in the event hash
125
+ configuration.async.call(evt.to_json_compatible)
126
+ rescue => e
127
+ logger.error("async event sending failed: #{e.message}")
128
+ send_event(evt, make_hint(obj))
129
+ end
130
+ else
131
+ send_event(evt, make_hint(obj))
132
+ end
133
+ Thread.current["sentry_#{object_id}_last_event_id".to_sym] = evt.id
134
+ evt
135
+ end
136
+ end
137
+
138
+ alias capture_message capture_type
139
+ alias capture_exception capture_type
140
+
141
+ def last_event_id
142
+ Thread.current["sentry_#{object_id}_last_event_id".to_sym]
143
+ end
144
+
145
+ # Provides extra context to the exception prior to it being handled by
146
+ # Raven. An exception can have multiple annotations, which are merged
147
+ # together.
148
+ #
149
+ # The options (annotation) is treated the same as the ``options``
150
+ # parameter to ``capture_exception`` or ``Event.from_exception``, and
151
+ # can contain the same ``:user``, ``:tags``, etc. options as these
152
+ # methods.
153
+ #
154
+ # These will be merged with the ``options`` parameter to
155
+ # ``Event.from_exception`` at the top of execution.
156
+ #
157
+ # @example
158
+ # begin
159
+ # raise "Hello"
160
+ # rescue => exc
161
+ # Raven.annotate_exception(exc, :user => { 'id' => 1,
162
+ # 'email' => 'foo@example.com' })
163
+ # end
164
+ def annotate_exception(exc, options = {})
165
+ notes = (exc.instance_variable_defined?(:@__raven_context) && exc.instance_variable_get(:@__raven_context)) || {}
166
+ Raven::Utils::DeepMergeHash.deep_merge!(notes, options)
167
+ exc.instance_variable_set(:@__raven_context, notes)
168
+ exc
169
+ end
170
+
171
+ # Bind user context. Merges with existing context (if any).
172
+ #
173
+ # It is recommending that you send at least the ``id`` and ``email``
174
+ # values. All other values are arbitrary.
175
+ #
176
+ # @example
177
+ # Raven.user_context('id' => 1, 'email' => 'foo@example.com')
178
+ def user_context(options = nil)
179
+ original_user_context = context.user
180
+
181
+ if options
182
+ context.user.merge!(options)
183
+ else
184
+ context.user = {}
185
+ end
186
+
187
+ yield if block_given?
188
+ context.user
189
+ ensure
190
+ context.user = original_user_context if block_given?
191
+ end
192
+
193
+ # Bind tags context. Merges with existing context (if any).
194
+ #
195
+ # Tags are key / value pairs which generally represent things like
196
+ # application version, environment, role, and server names.
197
+ #
198
+ # @example
199
+ # Raven.tags_context('my_custom_tag' => 'tag_value')
200
+ def tags_context(options = nil)
201
+ context.tags.merge!(options || {})
202
+ yield if block_given?
203
+ context.tags
204
+ ensure
205
+ context.tags.delete_if { |k, _| options.keys.include? k } if block_given?
206
+ end
207
+
208
+ # Bind extra context. Merges with existing context (if any).
209
+ #
210
+ # Extra context shows up as Additional Data within Sentry, and is
211
+ # completely arbitrary.
212
+ #
213
+ # @example
214
+ # Raven.extra_context('my_custom_data' => 'value')
215
+ def extra_context(options = nil)
216
+ context.extra.merge!(options || {})
217
+ yield if block_given?
218
+ context.extra
219
+ ensure
220
+ context.extra.delete_if { |k, _| options.keys.include? k } if block_given?
221
+ end
222
+
223
+ def rack_context(env)
224
+ env = nil if env.empty?
225
+
226
+ context.rack_env = env
227
+ end
228
+
229
+ def breadcrumbs
230
+ BreadcrumbBuffer.current
231
+ end
232
+
233
+ private
234
+
235
+ def install_at_exit_hook(options)
236
+ at_exit do
237
+ exception = $ERROR_INFO
238
+ if exception
239
+ logger.debug "Caught a post-mortem exception: #{exception.inspect}"
240
+ capture_type(exception, options)
241
+ end
242
+ end
243
+ end
244
+
245
+ def make_hint(obj)
246
+ obj.is_a?(String) ? { :exception => nil, :message => obj } : { :exception => obj, :message => nil }
247
+ end
248
+ end
249
+ end
@@ -1,4 +1,5 @@
1
1
  require 'delayed_job'
2
+ require 'raven/utils/context_filter'
2
3
 
3
4
  module Delayed
4
5
  module Plugins
@@ -8,45 +9,46 @@ module Delayed
8
9
  begin
9
10
  # Forward the call to the next callback in the callback chain
10
11
  block.call(job, *args)
11
-
12
- rescue Exception => exception
12
+ rescue Exception => e
13
13
  # Log error to Sentry
14
14
  extra = {
15
15
  :delayed_job => {
16
- :id => job.id,
17
- :priority => job.priority,
18
- :attempts => job.attempts,
19
- :run_at => job.run_at,
20
- :locked_at => job.locked_at,
21
- :locked_by => job.locked_by,
22
- :queue => job.queue,
23
- :created_at => job.created_at
24
- }
16
+ :id => job.id.to_s,
17
+ :priority => job.priority,
18
+ :attempts => job.attempts,
19
+ :run_at => job.run_at,
20
+ :locked_at => job.locked_at,
21
+ :locked_by => job.locked_by,
22
+ :queue => job.queue,
23
+ :created_at => job.created_at
24
+ }
25
25
  }
26
26
  # last_error can be nil
27
- extra[:last_error] = job.last_error[0...100] if job.last_error
27
+ extra[:last_error] = job.last_error[0...1000] if job.last_error
28
28
  # handlers are YAML objects in strings, we definitely can't
29
29
  # report all of that or the event will get truncated randomly
30
- extra[:handler] = job.handler[0...100] if job.handler
30
+ extra[:handler] = job.handler[0...1000] if job.handler
31
31
 
32
32
  if job.respond_to?('payload_object') && job.payload_object.respond_to?('job_data')
33
- extra[:active_job] = job.payload_object.job_data
33
+ extra[:active_job] = ::Raven::Utils::ContextFilter.filter_context(job.payload_object.job_data)
34
34
  end
35
- ::Raven.capture_exception(exception,
36
- :logger => 'delayed_job',
37
- :tags => {
38
- :delayed_job_queue => job.queue,
39
- :delayed_job_id => job.id
40
- },
41
- :extra => extra)
35
+ ::Raven.capture_exception(e,
36
+ :logger => 'delayed_job',
37
+ :tags => {
38
+ :delayed_job_queue => job.queue,
39
+ :delayed_job_id => job.id.to_s
40
+ },
41
+ :extra => extra)
42
42
 
43
43
  # Make sure we propagate the failure!
44
- raise exception
44
+ raise e
45
+ ensure
46
+ ::Raven::Context.clear!
47
+ ::Raven::BreadcrumbBuffer.clear!
45
48
  end
46
49
  end
47
50
  end
48
51
  end
49
-
50
52
  end
51
53
  end
52
54
 
@@ -0,0 +1,22 @@
1
+ # We need to do this because of the way integration loading works
2
+ require "rack/timeout/base" unless defined?(Rack::Timeout)
3
+
4
+ # This integration is a good example of how to change how exceptions
5
+ # get grouped by Sentry's UI. Simply override #raven_context in
6
+ # the exception class, and append something to the fingerprint
7
+ # that will distinguish exceptions in the way you desire.
8
+ module RackTimeoutExtensions
9
+ def raven_context
10
+ # Only rack-timeout 0.3.0+ provides the request environment, but we can't
11
+ # gate this based on a gem version constant because rack-timeout does
12
+ # not provide one.
13
+ if defined?(env)
14
+ { :fingerprint => ["{{ default }}", env["REQUEST_URI"]] }
15
+ else
16
+ {}
17
+ end
18
+ end
19
+ end
20
+
21
+ Rack::Timeout::Error.include(RackTimeoutExtensions)
22
+ Rack::Timeout::RequestTimeoutException.include(RackTimeoutExtensions)
@@ -41,20 +41,17 @@ module Raven
41
41
  end
42
42
 
43
43
  def call(env)
44
- # clear context at the beginning of the request to ensure a clean slate
45
- Context.clear!
46
-
47
44
  # store the current environment in our local context for arbitrary
48
45
  # callers
49
46
  env['raven.requested_at'] = Time.now
50
47
  Raven.rack_context(env)
48
+ Raven.context.transaction.push(env["PATH_INFO"]) if env["PATH_INFO"]
51
49
 
52
50
  begin
53
51
  response = @app.call(env)
54
52
  rescue Error
55
53
  raise # Don't capture Raven errors
56
54
  rescue Exception => e
57
- Raven.logger.debug "Collecting %p: %s" % [ e.class, e.message ]
58
55
  Raven::Rack.capture_exception(e, env)
59
56
  raise
60
57
  end
@@ -63,6 +60,9 @@ module Raven
63
60
  Raven::Rack.capture_exception(error, env) if error
64
61
 
65
62
  response
63
+ ensure
64
+ Context.clear!
65
+ BreadcrumbBuffer.clear!
66
66
  end
67
67
  end
68
68
 
@@ -74,47 +74,63 @@ module Raven
74
74
  self.method = req.request_method
75
75
  self.query_string = req.query_string
76
76
  self.data = read_data_from(req)
77
+ self.cookies = req.cookies
77
78
 
78
79
  self.headers = format_headers_for_sentry(env_hash)
79
- self.env = format_env_for_sentry(env_hash)
80
+ self.env = format_env_for_sentry(env_hash)
80
81
  end
81
82
 
82
83
  private
83
84
 
85
+ # See Sentry server default limits at
86
+ # https://github.com/getsentry/sentry/blob/master/src/sentry/conf/server.py
84
87
  def read_data_from(request)
85
88
  if request.form_data?
86
89
  request.POST
87
- elsif request.body
88
- data = request.body.read
90
+ elsif request.body # JSON requests, etc
91
+ data = request.body.read(4096 * 4) # Sentry server limit
89
92
  request.body.rewind
90
93
  data
91
94
  end
95
+ rescue IOError => e
96
+ e.message
92
97
  end
93
98
 
94
99
  def format_headers_for_sentry(env_hash)
95
100
  env_hash.each_with_object({}) do |(key, value), memo|
96
- key = key.to_s # rack env can contain symbols
97
- value = value.to_s
98
- next unless key.upcase == key # Non-upper case stuff isn't either
99
-
100
- # Rack adds in an incorrect HTTP_VERSION key, which causes downstream
101
- # to think this is a Version header. Instead, this is mapped to
102
- # env['SERVER_PROTOCOL']. But we don't want to ignore a valid header
103
- # if the request has legitimately sent a Version header themselves.
104
- # See: https://github.com/rack/rack/blob/028438f/lib/rack/handler/cgi.rb#L29
105
- next if key == 'HTTP_VERSION' && value == ENV['SERVER_PROTOCOL']
106
-
107
- next unless key.start_with?('HTTP_') || %w(CONTENT_TYPE CONTENT_LENGTH).include?(key)
108
- # Rack stores headers as HTTP_WHAT_EVER, we need What-Ever
109
- key = key.gsub("HTTP_", "")
110
- key = key.split('_').map(&:capitalize).join('-')
111
- memo[key] = value
101
+ begin
102
+ key = key.to_s # rack env can contain symbols
103
+ next memo['X-Request-Id'] ||= Utils::RequestId.read_from(env_hash) if Utils::RequestId::REQUEST_ID_HEADERS.include?(key)
104
+ next unless key.upcase == key # Non-upper case stuff isn't either
105
+
106
+ # Rack adds in an incorrect HTTP_VERSION key, which causes downstream
107
+ # to think this is a Version header. Instead, this is mapped to
108
+ # env['SERVER_PROTOCOL']. But we don't want to ignore a valid header
109
+ # if the request has legitimately sent a Version header themselves.
110
+ # See: https://github.com/rack/rack/blob/028438f/lib/rack/handler/cgi.rb#L29
111
+ next if key == 'HTTP_VERSION' && value == env_hash['SERVER_PROTOCOL']
112
+ next if key == 'HTTP_COOKIE' # Cookies don't go here, they go somewhere else
113
+ next unless key.start_with?('HTTP_') || %w(CONTENT_TYPE CONTENT_LENGTH).include?(key)
114
+
115
+ # Rack stores headers as HTTP_WHAT_EVER, we need What-Ever
116
+ key = key.sub(/^HTTP_/, "")
117
+ key = key.split('_').map(&:capitalize).join('-')
118
+ memo[key] = value.to_s
119
+ rescue StandardError => e
120
+ # Rails adds objects to the Rack env that can sometimes raise exceptions
121
+ # when `to_s` is called.
122
+ # See: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/remote_ip.rb#L134
123
+ Raven.logger.warn("Error raised while formatting headers: #{e.message}")
124
+ next
125
+ end
112
126
  end
113
127
  end
114
128
 
115
129
  def format_env_for_sentry(env_hash)
130
+ return env_hash if Raven.configuration.rack_env_whitelist.empty?
131
+
116
132
  env_hash.select do |k, _v|
117
- %w(REMOTE_ADDR SERVER_NAME SERVER_PORT).include? k.to_s
133
+ Raven.configuration.rack_env_whitelist.include? k.to_s
118
134
  end
119
135
  end
120
136
  end
@@ -1,31 +1,63 @@
1
1
  module Raven
2
2
  class Rails
3
- module ActiveJob
3
+ module ActiveJobExtensions
4
+ ALREADY_SUPPORTED_SENTRY_ADAPTERS = %w(
5
+ ActiveJob::QueueAdapters::SidekiqAdapter
6
+ ActiveJob::QueueAdapters::DelayedJobAdapter
7
+ ).freeze
8
+
4
9
  def self.included(base)
5
10
  base.class_eval do
6
- rescue_from(Exception) do |exception|
7
- # Do not capture exceptions when using Sidekiq so we don't capture
8
- # The same exception twice.
9
- unless self.class.queue_adapter.to_s == 'ActiveJob::QueueAdapters::SidekiqAdapter'
10
- active_job_details = {
11
- :active_job => self.class.name,
12
- :arguments => arguments,
13
- :scheduled_at => scheduled_at,
14
- :job_id => job_id,
15
- :locale => locale,
16
- }
17
-
18
- # Add provider_job_id details if Rails 5
19
- if defined?(provider_job_id)
20
- active_job_details[:provider_job_id] = provider_job_id
21
- end
22
-
23
- Raven.capture_exception(exception, :extra => active_job_details)
24
- raise exception
11
+ around_perform do |job, block|
12
+ if already_supported_by_specific_integration?(job)
13
+ block.call
14
+ else
15
+ capture_and_reraise_with_sentry(job, block)
25
16
  end
26
17
  end
27
18
  end
28
19
  end
20
+
21
+ def capture_and_reraise_with_sentry(job, block)
22
+ block.call
23
+ rescue Exception => e # rubocop:disable Lint/RescueException
24
+ rescue_handler_result = rescue_with_handler(e)
25
+ return rescue_handler_result if rescue_handler_result
26
+
27
+ Raven.capture_exception(e, :extra => raven_context(job))
28
+ raise e
29
+ ensure
30
+ Context.clear!
31
+ BreadcrumbBuffer.clear!
32
+ end
33
+
34
+ def already_supported_by_specific_integration?(job)
35
+ if ::Rails.version.to_f < 5.0
36
+ ALREADY_SUPPORTED_SENTRY_ADAPTERS.include?(job.class.queue_adapter.to_s)
37
+ else
38
+ ALREADY_SUPPORTED_SENTRY_ADAPTERS.include?(job.class.queue_adapter.class.to_s)
39
+ end
40
+ end
41
+
42
+ def raven_context(job)
43
+ ctx = {
44
+ :active_job => job.class.name,
45
+ :arguments => job.arguments,
46
+ :scheduled_at => job.scheduled_at,
47
+ :job_id => job.job_id,
48
+ :locale => job.locale
49
+ }
50
+ # Add provider_job_id details if Rails 5
51
+ if job.respond_to?(:provider_job_id)
52
+ ctx[:provider_job_id] = job.provider_job_id
53
+ end
54
+
55
+ ctx
56
+ end
29
57
  end
30
58
  end
31
59
  end
60
+
61
+ class ActiveJob::Base
62
+ include Raven::Rails::ActiveJobExtensions
63
+ end
@@ -0,0 +1,29 @@
1
+ require "active_support/backtrace_cleaner"
2
+ require "active_support/core_ext/string/access"
3
+
4
+ module Raven
5
+ class Rails
6
+ class BacktraceCleaner < ActiveSupport::BacktraceCleaner
7
+ APP_DIRS_PATTERN = /\A(?:\.\/)?(?:app|config|lib|test|\(\w*\))/.freeze
8
+ RENDER_TEMPLATE_PATTERN = /:in `.*_\w+_{2,3}\d+_\d+'/.freeze
9
+
10
+ def initialize
11
+ super
12
+ # we don't want any default silencers because they're too aggressive
13
+ remove_silencers!
14
+
15
+ @root = "#{Raven.configuration.project_root}/"
16
+ add_filter do |line|
17
+ line.start_with?(@root) ? line.from(@root.size) : line
18
+ end
19
+ add_filter do |line|
20
+ if line =~ RENDER_TEMPLATE_PATTERN
21
+ line.sub(RENDER_TEMPLATE_PATTERN, "")
22
+ else
23
+ line
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ module Raven
2
+ class Rails
3
+ module ControllerTransaction
4
+ def self.included(base)
5
+ base.prepend_around_action do |controller, block|
6
+ Raven.context.transaction.push "#{controller.class}##{controller.action_name}"
7
+ block.call
8
+ Raven.context.transaction.pop
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -6,7 +6,7 @@ module Raven
6
6
  begin
7
7
  env = env_or_request.respond_to?(:env) ? env_or_request.env : env_or_request
8
8
  Raven::Rack.capture_exception(exception, env)
9
- rescue # rubocop:disable Lint/HandleExceptions
9
+ rescue
10
10
  end
11
11
  super
12
12
  end
@@ -21,7 +21,7 @@ module Raven
21
21
  begin
22
22
  env = env_or_request.respond_to?(:env) ? env_or_request.env : env_or_request
23
23
  Raven::Rack.capture_exception(exception, env)
24
- rescue # rubocop:disable Lint/HandleExceptions
24
+ rescue
25
25
  end
26
26
  render_exception_without_raven(env_or_request, exception)
27
27
  end