sentry-raven 2.1.3 → 3.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) 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 +16 -6
  11. data/lib/raven/base.rb +17 -4
  12. data/lib/raven/breadcrumbs/{activesupport.rb → active_support_logger.rb} +9 -3
  13. data/lib/raven/breadcrumbs/logger.rb +2 -92
  14. data/lib/raven/breadcrumbs/sentry_logger.rb +73 -0
  15. data/lib/raven/breadcrumbs.rb +3 -1
  16. data/lib/raven/cli.rb +31 -43
  17. data/lib/raven/client.rb +39 -17
  18. data/lib/raven/configuration.rb +277 -37
  19. data/lib/raven/context.rb +17 -11
  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 +172 -233
  23. data/lib/raven/helpers/deprecation_helper.rb +17 -0
  24. data/lib/raven/instance.rb +51 -25
  25. data/lib/raven/integrations/delayed_job.rb +18 -18
  26. data/lib/raven/integrations/rack-timeout.rb +11 -5
  27. data/lib/raven/integrations/rack.rb +36 -19
  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 +24 -8
  33. data/lib/raven/integrations/rake.rb +6 -1
  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 -57
  37. data/lib/raven/interface.rb +2 -2
  38. data/lib/raven/interfaces/exception.rb +0 -2
  39. data/lib/raven/interfaces/http.rb +0 -2
  40. data/lib/raven/interfaces/message.rb +1 -1
  41. data/lib/raven/interfaces/single_exception.rb +0 -2
  42. data/lib/raven/interfaces/stack_trace.rb +19 -27
  43. data/lib/raven/linecache.rb +34 -17
  44. data/lib/raven/logger.rb +11 -18
  45. data/lib/raven/processor/cookies.rb +27 -7
  46. data/lib/raven/processor/http_headers.rb +18 -5
  47. data/lib/raven/processor/post_data.rb +16 -3
  48. data/lib/raven/processor/removecircularreferences.rb +12 -8
  49. data/lib/raven/processor/removestacktrace.rb +17 -6
  50. data/lib/raven/processor/sanitizedata.rb +88 -29
  51. data/lib/raven/processor/utf8conversion.rb +39 -14
  52. data/lib/raven/processor.rb +1 -1
  53. data/lib/raven/transports/http.rb +29 -21
  54. data/lib/raven/transports/stdout.rb +20 -0
  55. data/lib/raven/transports.rb +4 -8
  56. data/lib/raven/utils/context_filter.rb +42 -0
  57. data/lib/raven/utils/deep_merge.rb +6 -12
  58. data/lib/raven/utils/exception_cause_chain.rb +20 -0
  59. data/lib/raven/utils/real_ip.rb +1 -1
  60. data/lib/raven/utils/request_id.rb +16 -0
  61. data/lib/raven/version.rb +2 -2
  62. data/lib/sentry-raven-without-integrations.rb +6 -1
  63. data/lib/sentry_raven_without_integrations.rb +1 -0
  64. data/sentry-raven.gemspec +28 -0
  65. metadata +37 -103
  66. data/lib/raven/error.rb +0 -4
@@ -19,16 +19,15 @@ module Raven
19
19
  # end
20
20
  # end
21
21
  class Instance
22
- # The client object is responsible for delivering formatted data to the
23
- # Sentry server. Must respond to #send. See Raven::Client.
22
+ # See Raven::Client.
24
23
  attr_writer :client
25
24
 
26
- # A Raven configuration object. Must act like a hash and return sensible
27
- # values for all Raven configuration options. See Raven::Configuration.
28
- attr_writer :configuration
25
+ # See Raven::Configuration.
26
+ attr_accessor :configuration
29
27
 
30
- def initialize(context = nil)
28
+ def initialize(context = nil, config = nil)
31
29
  @context = @explicit_context = context
30
+ self.configuration = config || Configuration.new
32
31
  end
33
32
 
34
33
  def context
@@ -40,13 +39,7 @@ module Raven
40
39
  end
41
40
 
42
41
  def logger
43
- @logger ||= Logger.new
44
- end
45
-
46
- # The configuration object.
47
- # @see Raven.configure
48
- def configuration
49
- @configuration ||= Configuration.new
42
+ configuration.logger
50
43
  end
51
44
 
52
45
  # The client object is responsible for delivering formatted data to the
@@ -57,11 +50,13 @@ module Raven
57
50
 
58
51
  # Tell the log that the client is good to go
59
52
  def report_status
53
+ return unless configuration.enabled_in_current_env?
60
54
  return if configuration.silence_ready
55
+
61
56
  if configuration.capture_allowed?
62
57
  logger.info "Raven #{VERSION} ready to catch errors"
63
58
  else
64
- logger.info "Raven #{VERSION} configured not to capture errors."
59
+ logger.info "Raven #{VERSION} configured not to capture errors: #{configuration.error_messages}"
65
60
  end
66
61
  end
67
62
 
@@ -82,10 +77,10 @@ module Raven
82
77
  # Send an event to the configured Sentry server
83
78
  #
84
79
  # @example
85
- # evt = Raven::Event.new(:message => "An error")
80
+ # evt = Raven::Event.new(:message => "An errore)
86
81
  # Raven.send_event(evt)
87
- def send_event(event)
88
- client.send_event(event)
82
+ def send_event(event, hint = nil)
83
+ client.send_event(event, hint)
89
84
  end
90
85
 
91
86
  # Capture and process any exceptions from the given block.
@@ -111,30 +106,38 @@ module Raven
111
106
 
112
107
  def capture_type(obj, options = {})
113
108
  unless configuration.capture_allowed?(obj)
114
- Raven.logger.debug("#{obj} excluded from capture due to environment or should_capture callback")
109
+ logger.debug("#{obj} excluded from capture: #{configuration.error_messages}")
115
110
  return false
116
111
  end
117
112
 
118
113
  message_or_exc = obj.is_a?(String) ? "message" : "exception"
119
- if (evt = Event.send("from_" + message_or_exc, obj, options))
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
120
  yield evt if block_given?
121
121
  if configuration.async?
122
122
  begin
123
123
  # We have to convert to a JSON-like hash, because background job
124
124
  # processors (esp ActiveJob) may not like weird types in the event hash
125
125
  configuration.async.call(evt.to_json_compatible)
126
- rescue => ex
127
- Raven.logger.error("async event sending failed: #{ex.message}")
128
- send_event(evt)
126
+ rescue => e
127
+ logger.error("async event sending failed: #{e.message}")
128
+ send_event(evt, make_hint(obj))
129
129
  end
130
130
  else
131
- send_event(evt)
131
+ send_event(evt, make_hint(obj))
132
132
  end
133
133
  Thread.current["sentry_#{object_id}_last_event_id".to_sym] = evt.id
134
134
  evt
135
135
  end
136
136
  end
137
137
 
138
+ alias capture_message capture_type
139
+ alias capture_exception capture_type
140
+
138
141
  def last_event_id
139
142
  Thread.current["sentry_#{object_id}_last_event_id".to_sym]
140
143
  end
@@ -160,7 +163,7 @@ module Raven
160
163
  # end
161
164
  def annotate_exception(exc, options = {})
162
165
  notes = (exc.instance_variable_defined?(:@__raven_context) && exc.instance_variable_get(:@__raven_context)) || {}
163
- notes.merge!(options)
166
+ Raven::Utils::DeepMergeHash.deep_merge!(notes, options)
164
167
  exc.instance_variable_set(:@__raven_context, notes)
165
168
  exc
166
169
  end
@@ -173,7 +176,18 @@ module Raven
173
176
  # @example
174
177
  # Raven.user_context('id' => 1, 'email' => 'foo@example.com')
175
178
  def user_context(options = nil)
176
- context.user = options || {}
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?
177
191
  end
178
192
 
179
193
  # Bind tags context. Merges with existing context (if any).
@@ -185,6 +199,10 @@ module Raven
185
199
  # Raven.tags_context('my_custom_tag' => 'tag_value')
186
200
  def tags_context(options = nil)
187
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?
188
206
  end
189
207
 
190
208
  # Bind extra context. Merges with existing context (if any).
@@ -196,6 +214,10 @@ module Raven
196
214
  # Raven.extra_context('my_custom_data' => 'value')
197
215
  def extra_context(options = nil)
198
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?
199
221
  end
200
222
 
201
223
  def rack_context(env)
@@ -219,5 +241,9 @@ module Raven
219
241
  end
220
242
  end
221
243
  end
244
+
245
+ def make_hint(obj)
246
+ obj.is_a?(String) ? { :exception => nil, :message => obj } : { :exception => obj, :message => nil }
247
+ end
222
248
  end
223
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,40 +9,39 @@ 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
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
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 => {
35
+ ::Raven.capture_exception(e,
36
+ :logger => 'delayed_job',
37
+ :tags => {
38
38
  :delayed_job_queue => job.queue,
39
- :delayed_job_id => job.id
39
+ :delayed_job_id => job.id.to_s
40
40
  },
41
41
  :extra => extra)
42
42
 
43
43
  # Make sure we propagate the failure!
44
- raise exception
44
+ raise e
45
45
  ensure
46
46
  ::Raven::Context.clear!
47
47
  ::Raven::BreadcrumbBuffer.clear!
@@ -1,6 +1,5 @@
1
- # rubocop:disable Style/FileName
2
1
  # We need to do this because of the way integration loading works
3
- require "rack/timeout/base"
2
+ require "rack/timeout/base" unless defined?(Rack::Timeout)
4
3
 
5
4
  # This integration is a good example of how to change how exceptions
6
5
  # get grouped by Sentry's UI. Simply override #raven_context in
@@ -8,9 +7,16 @@ require "rack/timeout/base"
8
7
  # that will distinguish exceptions in the way you desire.
9
8
  module RackTimeoutExtensions
10
9
  def raven_context
11
- { :fingerprint => ["{{ default }}", env["REQUEST_URI"]] }
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
12
18
  end
13
19
  end
14
20
 
15
- Rack::Timeout::Error.include RackTimeoutExtensions
16
- Rack::Timeout::RequestTimeoutException.include RackTimeoutExtensions
21
+ Rack::Timeout::Error.include(RackTimeoutExtensions)
22
+ Rack::Timeout::RequestTimeoutException.include(RackTimeoutExtensions)
@@ -45,6 +45,7 @@ module Raven
45
45
  # callers
46
46
  env['raven.requested_at'] = Time.now
47
47
  Raven.rack_context(env)
48
+ Raven.context.transaction.push(env["PATH_INFO"]) if env["PATH_INFO"]
48
49
 
49
50
  begin
50
51
  response = @app.call(env)
@@ -73,47 +74,63 @@ module Raven
73
74
  self.method = req.request_method
74
75
  self.query_string = req.query_string
75
76
  self.data = read_data_from(req)
77
+ self.cookies = req.cookies
76
78
 
77
79
  self.headers = format_headers_for_sentry(env_hash)
78
- self.env = format_env_for_sentry(env_hash)
80
+ self.env = format_env_for_sentry(env_hash)
79
81
  end
80
82
 
81
83
  private
82
84
 
85
+ # See Sentry server default limits at
86
+ # https://github.com/getsentry/sentry/blob/master/src/sentry/conf/server.py
83
87
  def read_data_from(request)
84
88
  if request.form_data?
85
89
  request.POST
86
90
  elsif request.body # JSON requests, etc
87
- data = request.body.read(2048) # Sentry server limit
91
+ data = request.body.read(4096 * 4) # Sentry server limit
88
92
  request.body.rewind
89
93
  data
90
94
  end
95
+ rescue IOError => e
96
+ e.message
91
97
  end
92
98
 
93
99
  def format_headers_for_sentry(env_hash)
94
100
  env_hash.each_with_object({}) do |(key, value), memo|
95
- key = key.to_s # rack env can contain symbols
96
- value = value.to_s
97
- next unless key.upcase == key # Non-upper case stuff isn't either
98
-
99
- # Rack adds in an incorrect HTTP_VERSION key, which causes downstream
100
- # to think this is a Version header. Instead, this is mapped to
101
- # env['SERVER_PROTOCOL']. But we don't want to ignore a valid header
102
- # if the request has legitimately sent a Version header themselves.
103
- # See: https://github.com/rack/rack/blob/028438f/lib/rack/handler/cgi.rb#L29
104
- next if key == 'HTTP_VERSION' && value == ENV['SERVER_PROTOCOL']
105
-
106
- next unless key.start_with?('HTTP_') || %w(CONTENT_TYPE CONTENT_LENGTH).include?(key)
107
- # Rack stores headers as HTTP_WHAT_EVER, we need What-Ever
108
- key = key.gsub("HTTP_", "")
109
- key = key.split('_').map(&:capitalize).join('-')
110
- 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
111
126
  end
112
127
  end
113
128
 
114
129
  def format_env_for_sentry(env_hash)
130
+ return env_hash if Raven.configuration.rack_env_whitelist.empty?
131
+
115
132
  env_hash.select do |k, _v|
116
- %w(REMOTE_ADDR SERVER_NAME SERVER_PORT).include? k.to_s
133
+ Raven.configuration.rack_env_whitelist.include? k.to_s
117
134
  end
118
135
  end
119
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
@@ -4,6 +4,9 @@ module Raven
4
4
  class Rails < ::Rails::Railtie
5
5
  require 'raven/integrations/rails/overrides/streaming_reporter'
6
6
  require 'raven/integrations/rails/controller_methods'
7
+ require 'raven/integrations/rails/controller_transaction'
8
+ require 'raven/integrations/rails/backtrace_cleaner'
9
+ require 'raven/integrations/rack'
7
10
 
8
11
  initializer "raven.use_rack_middleware" do |app|
9
12
  app.config.middleware.insert 0, Raven::Rack
@@ -12,6 +15,7 @@ module Raven
12
15
  initializer 'raven.action_controller' do
13
16
  ActiveSupport.on_load :action_controller do
14
17
  include Raven::Rails::ControllerMethods
18
+ include Raven::Rails::ControllerTransaction
15
19
  if ::Rails::VERSION::STRING >= "4.0.0"
16
20
  Raven.safely_prepend(
17
21
  "StreamingReporter",
@@ -32,16 +36,22 @@ module Raven
32
36
  end
33
37
  end
34
38
 
35
- config.after_initialize do
36
- Raven.configure do |config|
37
- config.logger ||= ::Rails.logger
38
- config.project_root ||= ::Rails.root
39
- config.release ||= config.detect_release # if project_root has changed, need to re-check
39
+ config.before_initialize do
40
+ Raven.configuration.logger = ::Rails.logger
41
+
42
+ backtrace_cleaner = Raven::Rails::BacktraceCleaner.new
43
+
44
+ Raven.configuration.backtrace_cleanup_callback = lambda do |backtrace|
45
+ backtrace_cleaner.clean(backtrace)
40
46
  end
47
+ end
41
48
 
42
- if Raven.configuration.rails_activesupport_breadcrumbs
43
- require 'raven/breadcrumbs/activesupport'
44
- Raven::ActiveSupportBreadcrumbs.inject
49
+ config.after_initialize do
50
+ if Raven.configuration.breadcrumbs_logger.include?(:active_support_logger) ||
51
+ Raven.configuration.rails_activesupport_breadcrumbs
52
+
53
+ require 'raven/breadcrumbs/active_support_logger'
54
+ Raven::Breadcrumbs::ActiveSupportLogger.inject
45
55
  end
46
56
 
47
57
  if Raven.configuration.rails_report_rescued_exceptions
@@ -60,6 +70,12 @@ module Raven
60
70
  end
61
71
  end
62
72
 
73
+ initializer 'raven.active_job' do
74
+ ActiveSupport.on_load :active_job do
75
+ require 'raven/integrations/rails/active_job'
76
+ end
77
+ end
78
+
63
79
  rake_tasks do
64
80
  require 'raven/integrations/tasks'
65
81
  end
@@ -6,7 +6,12 @@ module Rake
6
6
  class Application
7
7
  alias orig_display_error_messsage display_error_message
8
8
  def display_error_message(ex)
9
- Raven.capture_exception ex, :logger => 'rake', :tags => { 'rake_task' => @name }
9
+ Raven.capture_exception(
10
+ ex,
11
+ :transaction => top_level_tasks.join(' '),
12
+ :logger => 'rake',
13
+ :tags => { 'rake_task' => top_level_tasks.join(' ') }
14
+ )
10
15
  orig_display_error_messsage(ex)
11
16
  end
12
17
  end
@@ -0,0 +1,13 @@
1
+ module Raven
2
+ module Sidekiq
3
+ class CleanupMiddleware
4
+ def call(_worker, job, queue)
5
+ Raven.context.transaction.push "Sidekiq/#{job['class']}"
6
+ Raven.extra_context(:sidekiq => job.merge("queue" => queue))
7
+ yield
8
+ Context.clear!
9
+ BreadcrumbBuffer.clear!
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,38 @@
1
+ require 'raven/utils/context_filter'
2
+
3
+ module Raven
4
+ module Sidekiq
5
+ class ErrorHandler
6
+ SIDEKIQ_NAME = "Sidekiq".freeze
7
+
8
+ def call(ex, context)
9
+ context = Utils::ContextFilter.filter_context(context)
10
+ Raven.context.transaction.push transaction_from_context(context)
11
+ Raven.capture_exception(
12
+ ex,
13
+ :message => ex.message,
14
+ :extra => { :sidekiq => context }
15
+ )
16
+ Context.clear!
17
+ BreadcrumbBuffer.clear!
18
+ end
19
+
20
+ private
21
+
22
+ # this will change in the future:
23
+ # https://github.com/mperham/sidekiq/pull/3161
24
+ def transaction_from_context(context)
25
+ classname = (context["wrapped"] || context["class"] ||
26
+ (context[:job] && (context[:job]["wrapped"] || context[:job]["class"]))
27
+ )
28
+ if classname
29
+ "#{SIDEKIQ_NAME}/#{classname}"
30
+ elsif context[:event]
31
+ "#{SIDEKIQ_NAME}/#{context[:event]}"
32
+ else
33
+ SIDEKIQ_NAME
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end