rollbar 2.22.1 → 2.27.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/pull_request_template.md +25 -0
- data/.rubocop.yml +136 -0
- data/.travis.yml +33 -30
- data/Gemfile +2 -0
- data/README.md +1 -1
- data/data/rollbar.snippet.js +1 -1
- data/docs/configuration.md +8 -0
- data/gemfiles/rails42.gemfile +4 -0
- data/gemfiles/rails50.gemfile +6 -2
- data/gemfiles/rails51.gemfile +6 -2
- data/gemfiles/rails60.gemfile +1 -1
- data/lib/rails/rollbar_runner.rb +3 -1
- data/lib/rollbar/capistrano.rb +1 -1
- data/lib/rollbar/capistrano_tasks.rb +10 -1
- data/lib/rollbar/configuration.rb +28 -6
- data/lib/rollbar/delay/girl_friday.rb +3 -7
- data/lib/rollbar/delay/resque.rb +2 -3
- data/lib/rollbar/delay/sidekiq.rb +2 -4
- data/lib/rollbar/delay/sucker_punch.rb +3 -4
- data/lib/rollbar/delay/thread.rb +14 -0
- data/lib/rollbar/deploy.rb +2 -0
- data/lib/rollbar/encoding/encoder.rb +10 -3
- data/lib/rollbar/item/backtrace.rb +12 -2
- data/lib/rollbar/item/frame.rb +2 -0
- data/lib/rollbar/item/locals.rb +45 -1
- data/lib/rollbar/item.rb +22 -14
- data/lib/rollbar/json.rb +1 -0
- data/lib/rollbar/middleware/js.rb +13 -3
- data/lib/rollbar/notifier.rb +154 -61
- data/lib/rollbar/plugins/active_job.rb +6 -2
- data/lib/rollbar/plugins/delayed_job/plugin.rb +11 -1
- data/lib/rollbar/plugins/error_context.rb +11 -0
- data/lib/rollbar/rake_tasks.rb +1 -1
- data/lib/rollbar/request_data_extractor.rb +7 -1
- data/lib/rollbar/rollbar_test.rb +6 -117
- data/lib/rollbar/scrubbers/url.rb +10 -5
- data/lib/rollbar/scrubbers.rb +1 -5
- data/lib/rollbar/truncation/frames_strategy.rb +1 -1
- data/lib/rollbar/truncation/mixin.rb +1 -1
- data/lib/rollbar/truncation/strings_strategy.rb +4 -2
- data/lib/rollbar/util.rb +4 -0
- data/lib/rollbar/version.rb +1 -1
- data/rollbar.gemspec +1 -0
- data/spec/support/rollbar_api.rb +67 -0
- metadata +6 -4
@@ -17,10 +17,8 @@ module Rollbar
|
|
17
17
|
|
18
18
|
def perform(*args)
|
19
19
|
Rollbar.process_from_async_handler(*args)
|
20
|
-
|
21
|
-
#
|
22
|
-
# and retry it
|
23
|
-
raise
|
20
|
+
|
21
|
+
# Do not rescue. Sidekiq will call the error handler.
|
24
22
|
end
|
25
23
|
end
|
26
24
|
end
|
@@ -33,7 +33,7 @@ module Rollbar
|
|
33
33
|
|
34
34
|
def perform(*args)
|
35
35
|
Rollbar.process_from_async_handler(*args)
|
36
|
-
|
36
|
+
|
37
37
|
# SuckerPunch can configure an exception handler with:
|
38
38
|
#
|
39
39
|
# SuckerPunch.exception_handler { # do something here }
|
@@ -41,9 +41,8 @@ module Rollbar
|
|
41
41
|
# This is just passed to Celluloid.exception_handler which will
|
42
42
|
# push the reiceved block to an array of handlers, by default empty, [].
|
43
43
|
#
|
44
|
-
|
45
|
-
#
|
46
|
-
raise
|
44
|
+
|
45
|
+
# Do not rescue. SuckerPunch will call the error handler.
|
47
46
|
end
|
48
47
|
end
|
49
48
|
end
|
data/lib/rollbar/delay/thread.rb
CHANGED
@@ -9,7 +9,10 @@ module Rollbar
|
|
9
9
|
Error = Class.new(StandardError)
|
10
10
|
TimeoutError = Class.new(Error)
|
11
11
|
|
12
|
+
DEFAULT_PRIORITY = 1
|
13
|
+
|
12
14
|
class << self
|
15
|
+
attr_writer :options
|
13
16
|
attr_reader :reaper
|
14
17
|
|
15
18
|
def call(payload)
|
@@ -20,6 +23,10 @@ module Rollbar
|
|
20
23
|
thread
|
21
24
|
end
|
22
25
|
|
26
|
+
def options
|
27
|
+
@options || {}
|
28
|
+
end
|
29
|
+
|
23
30
|
private
|
24
31
|
|
25
32
|
def threads
|
@@ -61,9 +68,16 @@ module Rollbar
|
|
61
68
|
end
|
62
69
|
end # class << self
|
63
70
|
|
71
|
+
def priority
|
72
|
+
self.class.options[:priority] || DEFAULT_PRIORITY
|
73
|
+
end
|
74
|
+
|
64
75
|
def call(payload)
|
76
|
+
priority = self.priority
|
77
|
+
|
65
78
|
::Thread.new do
|
66
79
|
begin
|
80
|
+
::Thread.current.priority = priority
|
67
81
|
Rollbar.process_from_async_handler(payload)
|
68
82
|
rescue StandardError
|
69
83
|
# Here we swallow the exception:
|
data/lib/rollbar/deploy.rb
CHANGED
@@ -3,7 +3,6 @@ module Rollbar
|
|
3
3
|
class Encoder
|
4
4
|
ALL_ENCODINGS = [::Encoding::UTF_8, ::Encoding::ISO_8859_1, ::Encoding::ASCII_8BIT, ::Encoding::US_ASCII].freeze
|
5
5
|
ASCII_ENCODINGS = [::Encoding::US_ASCII, ::Encoding::ASCII_8BIT, ::Encoding::ISO_8859_1].freeze
|
6
|
-
ENCODING_OPTIONS = { :invalid => :replace, :undef => :replace, :replace => '' }.freeze
|
7
6
|
UTF8 = 'UTF-8'.freeze
|
8
7
|
BINARY = 'binary'.freeze
|
9
8
|
|
@@ -21,10 +20,19 @@ module Rollbar
|
|
21
20
|
encoded_value = if encoding == ::Encoding::UTF_8 && value.valid_encoding?
|
22
21
|
value
|
23
22
|
else
|
24
|
-
force_encoding(value).encode(
|
23
|
+
force_encoding(value).encode(
|
24
|
+
*encoding_args(value),
|
25
|
+
# Ruby 2.7 requires this to look like keyword args,
|
26
|
+
# and Ruby 1.9.3 doesn't understand keyword args, so
|
27
|
+
# don't use hash rockets here and both will be happy.
|
28
|
+
invalid: :replace, undef: :replace, replace: '' # rubocop:disable Style/HashSyntax
|
29
|
+
)
|
25
30
|
end
|
26
31
|
|
27
32
|
object.is_a?(Symbol) ? encoded_value.to_sym : encoded_value
|
33
|
+
rescue StandardError => e
|
34
|
+
# If encoding fails for any reason, replace the string with a diagnostic error.
|
35
|
+
"error encoding string: #{e.class}: #{e.message}"
|
28
36
|
end
|
29
37
|
|
30
38
|
private
|
@@ -54,7 +62,6 @@ module Rollbar
|
|
54
62
|
def encoding_args(value)
|
55
63
|
args = [UTF8]
|
56
64
|
args << BINARY if ASCII_ENCODINGS.include?(value.encoding)
|
57
|
-
args << ENCODING_OPTIONS
|
58
65
|
|
59
66
|
args
|
60
67
|
end
|
@@ -74,10 +74,20 @@ module Rollbar
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def map_frames(current_exception)
|
77
|
-
|
77
|
+
frames = cleaned_backtrace(current_exception).map do |frame|
|
78
78
|
Rollbar::Item::Frame.new(self, frame,
|
79
79
|
:configuration => configuration).to_h
|
80
|
-
end
|
80
|
+
end
|
81
|
+
frames.reverse!
|
82
|
+
end
|
83
|
+
|
84
|
+
def cleaned_backtrace(current_exception)
|
85
|
+
normalized_backtrace = exception_backtrace(current_exception)
|
86
|
+
if configuration.backtrace_cleaner
|
87
|
+
configuration.backtrace_cleaner.clean(normalized_backtrace)
|
88
|
+
else
|
89
|
+
normalized_backtrace
|
90
|
+
end
|
81
91
|
end
|
82
92
|
|
83
93
|
# Returns the backtrace to be sent to our API. There are 3 options:
|
data/lib/rollbar/item/frame.rb
CHANGED
data/lib/rollbar/item/locals.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rollbar/notifier'
|
2
2
|
require 'rollbar/scrubbers/params'
|
3
|
+
require 'rollbar/util'
|
3
4
|
|
4
5
|
module Rollbar
|
5
6
|
class Item
|
@@ -39,8 +40,51 @@ module Rollbar
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
43
|
+
# Prepare objects to be handled by the payload serializer.
|
44
|
+
#
|
45
|
+
# Hashes and Arrays are traversed. Then all types execpt strings and
|
46
|
+
# immediates are exported using #inspect. Sending the object itself to the
|
47
|
+
# serializer can result in large recursive expansions, especially in Rails
|
48
|
+
# environments with ActiveRecord, ActiveSupport, etc. on the stack.
|
49
|
+
# Other export options could be #to_s, #to_h, and #as_json. Several of these
|
50
|
+
# will omit the class name, or are not implemented for many types.
|
51
|
+
#
|
52
|
+
# #inspect has the advantage that it is specifically intended for debugging
|
53
|
+
# output. If the user wants more or different information in the payload
|
54
|
+
# about a specific type, #inspect is the correct place to implement it.
|
55
|
+
# Likewise the default implementation should be oriented toward usefulness
|
56
|
+
# in debugging.
|
57
|
+
#
|
58
|
+
# Because #inspect outputs a string, it can be handled well by the string
|
59
|
+
# truncation strategy for large payloads.
|
60
|
+
#
|
42
61
|
def prepare_value(value)
|
43
|
-
value.
|
62
|
+
return simple_value?(value) ? value : value.inspect unless value.is_a?(Hash) || value.is_a?(Array)
|
63
|
+
|
64
|
+
cloned_value = ::Rollbar::Util.deep_copy(value)
|
65
|
+
::Rollbar::Util.iterate_and_update_with_block(cloned_value) do |v|
|
66
|
+
simple_value?(v) ? v : v.inspect
|
67
|
+
end
|
68
|
+
|
69
|
+
cloned_value
|
70
|
+
end
|
71
|
+
|
72
|
+
def simple_classes
|
73
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.4.0')
|
74
|
+
[String, Symbol, Integer, Float, TrueClass, FalseClass, NilClass]
|
75
|
+
else
|
76
|
+
[String, Symbol, Fixnum, Bignum, Float, TrueClass, FalseClass, NilClass] # rubocop:disable Lint/UnifiedInteger
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def simple_value?(value)
|
81
|
+
simple_classes.each do |klass|
|
82
|
+
# Use instance_of? so that subclasses and module containers will
|
83
|
+
# be treated like complex object types, not simple values.
|
84
|
+
return true if value.instance_of?(klass)
|
85
|
+
end
|
86
|
+
|
87
|
+
false
|
44
88
|
end
|
45
89
|
|
46
90
|
def scrub(hash)
|
data/lib/rollbar/item.rb
CHANGED
@@ -65,7 +65,6 @@ module Rollbar
|
|
65
65
|
def build
|
66
66
|
data = build_data
|
67
67
|
self.payload = {
|
68
|
-
'access_token' => configuration.access_token,
|
69
68
|
'data' => data
|
70
69
|
}
|
71
70
|
|
@@ -109,15 +108,11 @@ module Rollbar
|
|
109
108
|
# the risk just to send this diagnostic object. In versions < 4.1, ActiveSupport hooks
|
110
109
|
# Ruby's JSON.generate so deeply there's no workaround.
|
111
110
|
'not serialized in ActiveSupport < 4.1'
|
112
|
-
elsif configuration.use_async
|
113
|
-
#
|
114
|
-
# means it is actually performed by ActiveSupport
|
115
|
-
#
|
116
|
-
|
117
|
-
# it should at least be done by rollbar-gem itself. Much work has been done
|
118
|
-
# to avoid the bugs in ActiveSupport JSON. The async handlers are currently
|
119
|
-
# still subject to all those knnown issues.
|
120
|
-
'not serialized for async/delayed handlers'
|
111
|
+
elsif configuration.use_async && !configuration.async_json_payload
|
112
|
+
# The setting allows serialization to be performed by each handler,
|
113
|
+
# and this usually means it is actually performed by ActiveSupport,
|
114
|
+
# which cannot safely serialize this key.
|
115
|
+
'not serialized when async_json_payload is not set'
|
121
116
|
else
|
122
117
|
scrub(configuration.configured_options.configured)
|
123
118
|
end
|
@@ -141,11 +136,18 @@ module Rollbar
|
|
141
136
|
uuid = stringified_payload['data']['uuid']
|
142
137
|
host = stringified_payload['data'].fetch('server', {})['host']
|
143
138
|
|
139
|
+
original_error = {
|
140
|
+
:message => message,
|
141
|
+
:exception => exception,
|
142
|
+
:configuration => configuration,
|
143
|
+
:uuid => uuid,
|
144
|
+
:host => host
|
145
|
+
}
|
146
|
+
|
144
147
|
notifier.send_failsafe(
|
145
148
|
too_large_payload_string(attempts),
|
146
149
|
nil,
|
147
|
-
|
148
|
-
host
|
150
|
+
original_error
|
149
151
|
)
|
150
152
|
logger.error("[Rollbar] Payload too large to be sent for UUID #{uuid}: #{Rollbar::JSON.dump(payload)}")
|
151
153
|
end
|
@@ -187,13 +189,19 @@ module Rollbar
|
|
187
189
|
end
|
188
190
|
|
189
191
|
def build_extra
|
192
|
+
merged_extra = Util.deep_merge(scrub(extra), scrub(error_context))
|
193
|
+
|
190
194
|
if custom_data_method? && !Rollbar::Util.method_in_stack(:custom_data, __FILE__)
|
191
|
-
Util.deep_merge(scrub(custom_data),
|
195
|
+
Util.deep_merge(scrub(custom_data), merged_extra)
|
192
196
|
else
|
193
|
-
|
197
|
+
merged_extra.empty? ? nil : merged_extra # avoid putting an empty {} in the payload.
|
194
198
|
end
|
195
199
|
end
|
196
200
|
|
201
|
+
def error_context
|
202
|
+
exception.respond_to?(:rollbar_context) && exception.rollbar_context
|
203
|
+
end
|
204
|
+
|
197
205
|
def scrub(data)
|
198
206
|
return data unless data.is_a? Hash
|
199
207
|
|
data/lib/rollbar/json.rb
CHANGED
@@ -80,10 +80,18 @@ module Rollbar
|
|
80
80
|
return app_result unless response_string
|
81
81
|
|
82
82
|
env[JS_IS_INJECTED_KEY] = true
|
83
|
-
response = ::Rack::Response.new(response_string, app_result[0],
|
84
|
-
app_result[1])
|
85
83
|
|
86
|
-
|
84
|
+
status, headers, = app_result
|
85
|
+
headers['Content-Length'] = response_string.bytesize.to_s if headers.key?('Content-Length')
|
86
|
+
|
87
|
+
response = ::Rack::Response.new(response_string, status, headers)
|
88
|
+
|
89
|
+
finished = response.finish
|
90
|
+
|
91
|
+
# Rack < 2.x Response#finish returns self in array[2]. Rack >= 2.x returns self.body.
|
92
|
+
# Always return with the response object here regardless of rack version.
|
93
|
+
finished[2] = response
|
94
|
+
finished
|
87
95
|
end
|
88
96
|
|
89
97
|
def build_body_with_js(env, body, head_open_end)
|
@@ -116,6 +124,8 @@ module Rollbar
|
|
116
124
|
end
|
117
125
|
|
118
126
|
def config_js_tag(env)
|
127
|
+
require 'json'
|
128
|
+
|
119
129
|
js_config = Rollbar::Util.deep_copy(config[:options])
|
120
130
|
|
121
131
|
add_person_data(js_config, env)
|