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.
- checksums.yaml +5 -5
- data/.craft.yml +19 -0
- data/.scripts/bump-version.rb +5 -0
- data/CHANGELOG.md +703 -0
- data/Gemfile +37 -0
- data/Makefile +3 -0
- data/README.md +116 -18
- data/Rakefile +30 -0
- data/exe/raven +32 -0
- data/lib/raven/backtrace.rb +16 -6
- data/lib/raven/base.rb +17 -4
- data/lib/raven/breadcrumbs/{activesupport.rb → active_support_logger.rb} +9 -3
- data/lib/raven/breadcrumbs/logger.rb +2 -92
- data/lib/raven/breadcrumbs/sentry_logger.rb +73 -0
- data/lib/raven/breadcrumbs.rb +3 -1
- data/lib/raven/cli.rb +31 -43
- data/lib/raven/client.rb +39 -17
- data/lib/raven/configuration.rb +277 -37
- data/lib/raven/context.rb +17 -11
- data/lib/raven/core_ext/object/deep_dup.rb +57 -0
- data/lib/raven/core_ext/object/duplicable.rb +153 -0
- data/lib/raven/event.rb +172 -233
- data/lib/raven/helpers/deprecation_helper.rb +17 -0
- data/lib/raven/instance.rb +51 -25
- data/lib/raven/integrations/delayed_job.rb +18 -18
- data/lib/raven/integrations/rack-timeout.rb +11 -5
- data/lib/raven/integrations/rack.rb +36 -19
- data/lib/raven/integrations/rails/active_job.rb +52 -20
- data/lib/raven/integrations/rails/backtrace_cleaner.rb +29 -0
- data/lib/raven/integrations/rails/controller_transaction.rb +13 -0
- data/lib/raven/integrations/rails/overrides/debug_exceptions_catcher.rb +2 -2
- data/lib/raven/integrations/rails.rb +24 -8
- data/lib/raven/integrations/rake.rb +6 -1
- data/lib/raven/integrations/sidekiq/cleanup_middleware.rb +13 -0
- data/lib/raven/integrations/sidekiq/error_handler.rb +38 -0
- data/lib/raven/integrations/sidekiq.rb +6 -57
- data/lib/raven/interface.rb +2 -2
- data/lib/raven/interfaces/exception.rb +0 -2
- data/lib/raven/interfaces/http.rb +0 -2
- data/lib/raven/interfaces/message.rb +1 -1
- data/lib/raven/interfaces/single_exception.rb +0 -2
- data/lib/raven/interfaces/stack_trace.rb +19 -27
- data/lib/raven/linecache.rb +34 -17
- data/lib/raven/logger.rb +11 -18
- data/lib/raven/processor/cookies.rb +27 -7
- data/lib/raven/processor/http_headers.rb +18 -5
- data/lib/raven/processor/post_data.rb +16 -3
- data/lib/raven/processor/removecircularreferences.rb +12 -8
- data/lib/raven/processor/removestacktrace.rb +17 -6
- data/lib/raven/processor/sanitizedata.rb +88 -29
- data/lib/raven/processor/utf8conversion.rb +39 -14
- data/lib/raven/processor.rb +1 -1
- data/lib/raven/transports/http.rb +29 -21
- data/lib/raven/transports/stdout.rb +20 -0
- data/lib/raven/transports.rb +4 -8
- data/lib/raven/utils/context_filter.rb +42 -0
- data/lib/raven/utils/deep_merge.rb +6 -12
- data/lib/raven/utils/exception_cause_chain.rb +20 -0
- data/lib/raven/utils/real_ip.rb +1 -1
- data/lib/raven/utils/request_id.rb +16 -0
- data/lib/raven/version.rb +2 -2
- data/lib/sentry-raven-without-integrations.rb +6 -1
- data/lib/sentry_raven_without_integrations.rb +1 -0
- data/sentry-raven.gemspec +28 -0
- metadata +37 -103
- data/lib/raven/error.rb +0 -4
data/lib/raven/instance.rb
CHANGED
@@ -19,16 +19,15 @@ module Raven
|
|
19
19
|
# end
|
20
20
|
# end
|
21
21
|
class Instance
|
22
|
-
#
|
23
|
-
# Sentry server. Must respond to #send. See Raven::Client.
|
22
|
+
# See Raven::Client.
|
24
23
|
attr_writer :client
|
25
24
|
|
26
|
-
#
|
27
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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 =>
|
127
|
-
|
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
|
-
|
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
|
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
|
17
|
-
:priority
|
18
|
-
:attempts
|
19
|
-
:run_at
|
20
|
-
:locked_at
|
21
|
-
:locked_by
|
22
|
-
:queue
|
23
|
-
: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...
|
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...
|
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(
|
36
|
-
:logger
|
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
|
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
|
-
|
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
|
16
|
-
Rack::Timeout::RequestTimeoutException.include
|
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
|
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(
|
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
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
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
|
-
|
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
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
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
|
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.
|
36
|
-
Raven.
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
43
|
-
|
44
|
-
|
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
|
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
|