rollbar 2.22.1 → 3.4.0
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 +34 -0
- data/.github/workflows/ci.yml +104 -0
- data/.rubocop.yml +185 -33
- data/Gemfile +26 -28
- data/README.md +32 -8
- data/data/rollbar.snippet.js +1 -1
- data/docs/configuration.md +8 -0
- data/gemfiles/rails30.gemfile +17 -35
- data/gemfiles/rails31.gemfile +20 -37
- data/gemfiles/rails32.gemfile +13 -31
- data/gemfiles/rails40.gemfile +12 -32
- data/gemfiles/rails41.gemfile +11 -31
- data/gemfiles/rails42.gemfile +12 -32
- data/gemfiles/rails50.gemfile +16 -30
- data/gemfiles/rails51.gemfile +16 -30
- data/gemfiles/rails52.gemfile +10 -19
- data/gemfiles/rails60.gemfile +10 -25
- data/gemfiles/rails61.gemfile +52 -0
- data/gemfiles/rails70.gemfile +52 -0
- data/lib/generators/rollbar/rollbar_generator.rb +18 -14
- data/lib/rails/rollbar_runner.rb +11 -20
- data/lib/rollbar/capistrano.rb +17 -9
- data/lib/rollbar/capistrano3.rb +8 -2
- data/lib/rollbar/capistrano_tasks.rb +44 -8
- data/lib/rollbar/configuration.rb +138 -84
- data/lib/rollbar/delay/girl_friday.rb +3 -7
- data/lib/rollbar/delay/resque.rb +2 -3
- data/lib/rollbar/delay/shoryuken.rb +4 -3
- data/lib/rollbar/delay/sidekiq.rb +5 -5
- data/lib/rollbar/delay/sucker_punch.rb +4 -6
- data/lib/rollbar/delay/thread.rb +17 -2
- data/lib/rollbar/deploy.rb +8 -7
- data/lib/rollbar/encoding/encoder.rb +17 -6
- data/lib/rollbar/encoding.rb +2 -7
- data/lib/rollbar/exception_reporter.rb +17 -8
- data/lib/rollbar/item/backtrace.rb +22 -10
- data/lib/rollbar/item/frame.rb +8 -5
- data/lib/rollbar/item/locals.rb +49 -2
- data/lib/rollbar/item.rb +80 -50
- data/lib/rollbar/json.rb +2 -1
- data/lib/rollbar/language_support.rb +0 -6
- data/lib/rollbar/lazy_store.rb +3 -7
- data/lib/rollbar/logger.rb +2 -0
- data/lib/rollbar/logger_proxy.rb +3 -1
- data/lib/rollbar/middleware/js/json_value.rb +15 -5
- data/lib/rollbar/middleware/js.rb +70 -38
- data/lib/rollbar/middleware/rack/builder.rb +3 -3
- data/lib/rollbar/middleware/rack/test_session.rb +3 -3
- data/lib/rollbar/middleware/rack.rb +4 -4
- data/lib/rollbar/middleware/rails/rollbar.rb +9 -6
- data/lib/rollbar/middleware/rails/show_exceptions.rb +8 -4
- data/lib/rollbar/notifier/trace_with_bindings.rb +13 -3
- data/lib/rollbar/notifier.rb +309 -172
- data/lib/rollbar/plugin.rb +8 -8
- data/lib/rollbar/plugins/active_job.rb +20 -3
- data/lib/rollbar/plugins/delayed_job/plugin.rb +19 -2
- data/lib/rollbar/plugins/error_context.rb +11 -0
- data/lib/rollbar/plugins/goalie.rb +27 -16
- data/lib/rollbar/plugins/rails/controller_methods.rb +18 -14
- data/lib/rollbar/plugins/rails/railtie30.rb +2 -1
- data/lib/rollbar/plugins/rails/railtie32.rb +2 -1
- data/lib/rollbar/plugins/rails/railtie_mixin.rb +2 -2
- data/lib/rollbar/plugins/rails.rb +5 -2
- data/lib/rollbar/plugins/rake.rb +2 -1
- data/lib/rollbar/plugins/sidekiq/plugin.rb +39 -21
- data/lib/rollbar/plugins/sidekiq.rb +1 -1
- data/lib/rollbar/plugins/thread.rb +8 -7
- data/lib/rollbar/plugins/validations.rb +3 -1
- data/lib/rollbar/rake_tasks.rb +1 -2
- data/lib/rollbar/request_data_extractor.rb +53 -19
- data/lib/rollbar/rollbar_test.rb +9 -118
- data/lib/rollbar/scrubbers/params.rb +13 -7
- data/lib/rollbar/scrubbers/url.rb +56 -17
- data/lib/rollbar/scrubbers.rb +2 -6
- data/lib/rollbar/truncation/frames_strategy.rb +1 -1
- data/lib/rollbar/truncation/mixin.rb +1 -1
- data/lib/rollbar/truncation/remove_any_key_strategy.rb +4 -1
- data/lib/rollbar/truncation/remove_extra_strategy.rb +3 -1
- data/lib/rollbar/truncation/strings_strategy.rb +4 -2
- data/lib/rollbar/util/hash.rb +14 -7
- data/lib/rollbar/util/ip_anonymizer.rb +1 -1
- data/lib/rollbar/util.rb +23 -13
- data/lib/rollbar/version.rb +1 -1
- data/lib/rollbar.rb +12 -7
- data/lib/tasks/benchmark.rake +2 -1
- data/rollbar.gemspec +6 -3
- data/spec/support/rollbar_api.rb +67 -0
- metadata +19 -12
- data/.travis.yml +0 -281
- data/lib/rollbar/encoding/legacy_encoder.rb +0 -20
- /data/lib/generators/rollbar/templates/{initializer.rb → initializer.erb} +0 -0
data/lib/rollbar/rollbar_test.rb
CHANGED
@@ -1,48 +1,16 @@
|
|
1
1
|
require 'rollbar'
|
2
|
-
begin
|
3
|
-
require 'rack/mock'
|
4
|
-
rescue LoadError
|
5
|
-
puts 'Cannot load rack/mock'
|
6
|
-
end
|
7
|
-
require 'logger'
|
8
2
|
|
9
|
-
# Module to inject into the Rails controllers or rack apps
|
10
3
|
module RollbarTest # :nodoc:
|
11
|
-
def test_rollbar
|
12
|
-
puts 'Raising RollbarTestingException to simulate app failure.'
|
13
|
-
|
14
|
-
raise RollbarTestingException.new, ::RollbarTest.success_message
|
15
|
-
end
|
16
|
-
|
17
4
|
def self.run
|
18
5
|
return unless confirmed_token?
|
19
6
|
|
20
|
-
|
21
|
-
|
22
|
-
puts 'Testing manual report...'
|
23
|
-
Rollbar.error('Test error from rollbar:test')
|
24
|
-
|
25
|
-
return unless defined?(Rack::MockRequest)
|
26
|
-
|
27
|
-
protocol, app = setup_app
|
28
|
-
|
29
|
-
puts 'Processing...'
|
30
|
-
env = Rack::MockRequest.env_for("#{protocol}://www.example.com/verify", 'REMOTE_ADDR' => '127.0.0.1')
|
31
|
-
status, = app.call(env)
|
32
|
-
|
33
|
-
puts error_message unless status.to_i == 500
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.configure_rails
|
37
|
-
Rails.logger = if defined?(ActiveSupport::TaggedLogging)
|
38
|
-
ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
|
39
|
-
else
|
40
|
-
Logger.new(STDOUT)
|
41
|
-
end
|
7
|
+
puts 'Test sending to Rollbar...'
|
8
|
+
result = Rollbar.info('Test message from rollbar:test')
|
42
9
|
|
43
|
-
|
44
|
-
|
45
|
-
|
10
|
+
if result == 'error'
|
11
|
+
puts error_message
|
12
|
+
else
|
13
|
+
puts success_message
|
46
14
|
end
|
47
15
|
end
|
48
16
|
|
@@ -54,94 +22,17 @@ module RollbarTest # :nodoc:
|
|
54
22
|
false
|
55
23
|
end
|
56
24
|
|
57
|
-
def self.authlogic_config
|
58
|
-
# from http://stackoverflow.com/questions/5270835/authlogic-activation-problems
|
59
|
-
return unless defined?(Authlogic)
|
60
|
-
|
61
|
-
Authlogic::Session::Base.controller = Authlogic::ControllerAdapters::RailsAdapter.new(self)
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.setup_app
|
65
|
-
puts 'Setting up the test app.'
|
66
|
-
|
67
|
-
if defined?(Rails)
|
68
|
-
app = rails_app
|
69
|
-
|
70
|
-
draw_rails_route(app)
|
71
|
-
|
72
|
-
authlogic_config
|
73
|
-
|
74
|
-
[rails_protocol(app), app]
|
75
|
-
else
|
76
|
-
['http', rack_app]
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def self.rails_app
|
81
|
-
# The setup below is needed for Rails 5.x, but not for Rails 4.x and below.
|
82
|
-
# (And fails on Rails 4.x in various ways depending on the exact version.)
|
83
|
-
return Rails.application if Rails.version < '5.0.0'
|
84
|
-
|
85
|
-
# Spring now runs by default in development on all new Rails installs. This causes
|
86
|
-
# the new `/verify` route to not get picked up if `config.cache_classes == false`
|
87
|
-
# which is also a default in development env.
|
88
|
-
#
|
89
|
-
# `config.cache_classes` needs to be set, but the only possible time is at app load,
|
90
|
-
# so here we clone the default app with an updated config.
|
91
|
-
#
|
92
|
-
config = Rails.application.config
|
93
|
-
config.cache_classes = true
|
94
|
-
|
95
|
-
# Make a copy of the app, so the config can be updated.
|
96
|
-
Rails.application.class.name.constantize.new(:config => config)
|
97
|
-
end
|
98
|
-
|
99
|
-
def self.draw_rails_route(app)
|
100
|
-
app.routes_reloader.execute_if_updated
|
101
|
-
app.routes.draw do
|
102
|
-
get 'verify' => 'rollbar_test#verify', :as => 'verify'
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def self.rails_protocol(app)
|
107
|
-
defined?(app.config.force_ssl && app.config.force_ssl) ? 'https' : 'http'
|
108
|
-
end
|
109
|
-
|
110
|
-
def self.rack_app
|
111
|
-
Class.new do
|
112
|
-
include RollbarTest
|
113
|
-
|
114
|
-
def self.call(_env)
|
115
|
-
new.test_rollbar
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
25
|
def self.token_error_message
|
121
26
|
'Rollbar needs an access token configured. Check the README for instructions.'
|
122
27
|
end
|
123
28
|
|
124
29
|
def self.error_message
|
125
|
-
'Test failed! You may have a configuration issue, or you could be using a
|
30
|
+
'Test failed! You may have a configuration issue, or you could be using a ' \
|
31
|
+
'gem that\'s blocking the test. Contact support@rollbar.com if you need ' \
|
32
|
+
'help troubleshooting.'
|
126
33
|
end
|
127
34
|
|
128
35
|
def self.success_message
|
129
36
|
'Testing rollbar with "rake rollbar:test". If you can see this, it works.'
|
130
37
|
end
|
131
38
|
end
|
132
|
-
|
133
|
-
class RollbarTestingException < RuntimeError; end
|
134
|
-
|
135
|
-
if defined?(Rails)
|
136
|
-
class RollbarTestController < ActionController::Base # :nodoc:
|
137
|
-
include RollbarTest
|
138
|
-
|
139
|
-
def verify
|
140
|
-
test_rollbar
|
141
|
-
end
|
142
|
-
|
143
|
-
def logger
|
144
|
-
nil
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
@@ -10,7 +10,8 @@ module Rollbar
|
|
10
10
|
# configuration array even if :scrub_all is true.
|
11
11
|
class Params
|
12
12
|
SKIPPED_CLASSES = [::Tempfile].freeze
|
13
|
-
ATTACHMENT_CLASSES = %w[ActionDispatch::Http::UploadedFile
|
13
|
+
ATTACHMENT_CLASSES = %w[ActionDispatch::Http::UploadedFile
|
14
|
+
Rack::Multipart::UploadedFile].freeze
|
14
15
|
SCRUB_ALL = :scrub_all
|
15
16
|
|
16
17
|
def self.call(*args)
|
@@ -21,7 +22,7 @@ module Rollbar
|
|
21
22
|
params = options[:params]
|
22
23
|
return {} unless params
|
23
24
|
|
24
|
-
@
|
25
|
+
@scrubbed_objects = {}.compare_by_identity
|
25
26
|
|
26
27
|
config = options[:config]
|
27
28
|
extra_fields = options[:extra_fields]
|
@@ -52,16 +53,20 @@ module Rollbar
|
|
52
53
|
end
|
53
54
|
|
54
55
|
def build_whitelist_regex(whitelist)
|
55
|
-
fields = whitelist.find_all
|
56
|
+
fields = whitelist.find_all do |f|
|
57
|
+
f.is_a?(String) || f.is_a?(Symbol) || f.is_a?(Regexp)
|
58
|
+
end
|
56
59
|
return unless fields.any?
|
57
60
|
|
58
|
-
Regexp.new(fields.map
|
61
|
+
Regexp.new(fields.map do |val|
|
62
|
+
val.is_a?(Regexp) ? val : /\A#{Regexp.escape(val.to_s)}\z/
|
63
|
+
end.join('|'))
|
59
64
|
end
|
60
65
|
|
61
66
|
def scrub(params, options)
|
62
|
-
return params if @
|
67
|
+
return params if @scrubbed_objects[params]
|
63
68
|
|
64
|
-
@
|
69
|
+
@scrubbed_objects[params] = true
|
65
70
|
|
66
71
|
fields_regex = options[:fields_regex]
|
67
72
|
scrub_all = options[:scrub_all]
|
@@ -71,7 +76,8 @@ module Rollbar
|
|
71
76
|
|
72
77
|
params.to_hash.inject({}) do |result, (key, value)|
|
73
78
|
encoded_key = Rollbar::Encoding.encode(key).to_s
|
74
|
-
result[key] = if (fields_regex === encoded_key) &&
|
79
|
+
result[key] = if (fields_regex === encoded_key) &&
|
80
|
+
!(whitelist_regex === encoded_key)
|
75
81
|
scrub_value(value)
|
76
82
|
elsif value.is_a?(Hash)
|
77
83
|
scrub(value, options)
|
@@ -13,7 +13,7 @@ module Rollbar
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def call(options = {})
|
16
|
-
url = options[:url]
|
16
|
+
url = ascii_encode(options[:url])
|
17
17
|
|
18
18
|
filter(url,
|
19
19
|
build_regex(options[:scrub_fields]),
|
@@ -23,12 +23,29 @@ module Rollbar
|
|
23
23
|
options[:scrub_fields].include?(SCRUB_ALL),
|
24
24
|
build_whitelist_regex(options[:whitelist] || []))
|
25
25
|
rescue StandardError => e
|
26
|
-
|
26
|
+
message = '[Rollbar] There was an error scrubbing the url: ' \
|
27
|
+
"#{e}, options: #{options.inspect}"
|
28
|
+
Rollbar.logger.error(message)
|
27
29
|
url
|
28
30
|
end
|
29
31
|
|
30
32
|
private
|
31
33
|
|
34
|
+
def ascii_encode(url)
|
35
|
+
# In some cases non-ascii characters won't be properly encoded, so we do it here.
|
36
|
+
#
|
37
|
+
# The standard encoders (the CGI and URI methods) are not reliable when
|
38
|
+
# the query string is already embedded in the full URL, but the inconsistencies
|
39
|
+
# are limited to issues with characters in the ascii range. (For example,
|
40
|
+
# the '#' if it appears in an unexpected place.) For escaping non-ascii,
|
41
|
+
# they are all OK, so we'll take care to skip the ascii chars.
|
42
|
+
|
43
|
+
return url if url.ascii_only?
|
44
|
+
|
45
|
+
# Iterate each char and only escape non-ascii characters.
|
46
|
+
url.each_char.map { |c| c.ascii_only? ? c : CGI.escape(c) }.join
|
47
|
+
end
|
48
|
+
|
32
49
|
def build_whitelist_regex(whitelist)
|
33
50
|
fields = whitelist.find_all { |f| f.is_a?(String) || f.is_a?(Symbol) }
|
34
51
|
return unless fields.any?
|
@@ -36,12 +53,15 @@ module Rollbar
|
|
36
53
|
Regexp.new(fields.map { |val| /\A#{Regexp.escape(val.to_s)}\z/ }.join('|'))
|
37
54
|
end
|
38
55
|
|
39
|
-
def filter(url, regex, scrub_user, scrub_password, randomize_scrub_length,
|
56
|
+
def filter(url, regex, scrub_user, scrub_password, randomize_scrub_length,
|
57
|
+
scrub_all, whitelist)
|
40
58
|
uri = URI.parse(url)
|
41
59
|
|
42
60
|
uri.user = filter_user(uri.user, scrub_user, randomize_scrub_length)
|
43
|
-
uri.password = filter_password(uri.password, scrub_password,
|
44
|
-
|
61
|
+
uri.password = filter_password(uri.password, scrub_password,
|
62
|
+
randomize_scrub_length)
|
63
|
+
uri.query = filter_query(uri.query, regex, randomize_scrub_length, scrub_all,
|
64
|
+
whitelist)
|
45
65
|
|
46
66
|
uri.to_s
|
47
67
|
end
|
@@ -59,7 +79,12 @@ module Rollbar
|
|
59
79
|
end
|
60
80
|
|
61
81
|
def filter_password(password, scrub_password, randomize_scrub_length)
|
62
|
-
scrub_password && password
|
82
|
+
if scrub_password && password
|
83
|
+
filtered_value(password,
|
84
|
+
randomize_scrub_length)
|
85
|
+
else
|
86
|
+
password
|
87
|
+
end
|
63
88
|
end
|
64
89
|
|
65
90
|
def filter_query(query, regex, randomize_scrub_length, scrub_all, whitelist)
|
@@ -67,10 +92,8 @@ module Rollbar
|
|
67
92
|
|
68
93
|
params = decode_www_form(query)
|
69
94
|
|
70
|
-
|
71
|
-
|
72
|
-
# We want this to rebuild array params like foo[]=1&foo[]=2
|
73
|
-
URI.escape(CGI.unescape(encoded_query))
|
95
|
+
encode_www_form(filter_query_params(params, regex, randomize_scrub_length,
|
96
|
+
scrub_all, whitelist))
|
74
97
|
end
|
75
98
|
|
76
99
|
def decode_www_form(query)
|
@@ -78,12 +101,28 @@ module Rollbar
|
|
78
101
|
end
|
79
102
|
|
80
103
|
def encode_www_form(params)
|
81
|
-
URI.encode_www_form(params)
|
104
|
+
restore_square_brackets(URI.encode_www_form(params))
|
105
|
+
end
|
106
|
+
|
107
|
+
def restore_square_brackets(query)
|
108
|
+
# We want this to rebuild array params like foo[]=1&foo[]=2
|
109
|
+
#
|
110
|
+
# URI.encode_www_form follows the spec at
|
111
|
+
# https://url.spec.whatwg.org/#concept-urlencoded-serializer
|
112
|
+
# and percent encodes square brackets. Here we change them back.
|
113
|
+
query.gsub('%5B', '[').gsub('%5D', ']')
|
82
114
|
end
|
83
115
|
|
84
|
-
def filter_query_params(params, regex, randomize_scrub_length, scrub_all,
|
116
|
+
def filter_query_params(params, regex, randomize_scrub_length, scrub_all,
|
117
|
+
whitelist)
|
85
118
|
params.map do |key, value|
|
86
|
-
[key,
|
119
|
+
[key,
|
120
|
+
if filter_key?(key, regex, scrub_all,
|
121
|
+
whitelist)
|
122
|
+
filtered_value(value, randomize_scrub_length)
|
123
|
+
else
|
124
|
+
value
|
125
|
+
end]
|
87
126
|
end
|
88
127
|
end
|
89
128
|
|
@@ -96,10 +135,10 @@ module Rollbar
|
|
96
135
|
random_filtered_value
|
97
136
|
else
|
98
137
|
'*' * (begin
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
138
|
+
value.length
|
139
|
+
rescue StandardError
|
140
|
+
8
|
141
|
+
end)
|
103
142
|
end
|
104
143
|
end
|
105
144
|
|
data/lib/rollbar/scrubbers.rb
CHANGED
@@ -2,15 +2,11 @@ module Rollbar
|
|
2
2
|
module Scrubbers
|
3
3
|
module_function
|
4
4
|
|
5
|
-
def scrub_value(
|
5
|
+
def scrub_value(_value)
|
6
6
|
if Rollbar.configuration.randomize_scrub_length
|
7
7
|
random_filtered_value
|
8
8
|
else
|
9
|
-
'*' *
|
10
|
-
value.length
|
11
|
-
rescue StandardError
|
12
|
-
8
|
13
|
-
end)
|
9
|
+
'*' * 6
|
14
10
|
end
|
15
11
|
end
|
16
12
|
|
@@ -91,7 +91,10 @@ module Rollbar
|
|
91
91
|
def extract_title(body)
|
92
92
|
return body['message']['body'] if body['message'] && body['message']['body']
|
93
93
|
return extract_title_from_trace(body['trace']) if body['trace']
|
94
|
-
|
94
|
+
|
95
|
+
return unless body['trace_chain'] && body['trace_chain'][0]
|
96
|
+
|
97
|
+
extract_title_from_trace(body['trace_chain'][0])
|
95
98
|
end
|
96
99
|
|
97
100
|
def extract_title_from_trace(trace)
|
@@ -24,7 +24,9 @@ module Rollbar
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def delete_trace_chain_extra(body)
|
27
|
-
|
27
|
+
return unless body['trace_chain'] && body['trace_chain'][0]['extra']
|
28
|
+
|
29
|
+
body['trace_chain'][0].delete('extra')
|
28
30
|
end
|
29
31
|
|
30
32
|
def delete_trace_extra(body)
|
@@ -6,7 +6,7 @@ module Rollbar
|
|
6
6
|
class StringsStrategy
|
7
7
|
include ::Rollbar::Truncation::Mixin
|
8
8
|
|
9
|
-
STRING_THRESHOLDS = [1024, 512, 256].freeze
|
9
|
+
STRING_THRESHOLDS = [1024, 512, 256, 128].freeze
|
10
10
|
|
11
11
|
def self.call(payload)
|
12
12
|
new.call(payload)
|
@@ -29,7 +29,9 @@ module Rollbar
|
|
29
29
|
|
30
30
|
def truncate_strings_proc(threshold)
|
31
31
|
proc do |value|
|
32
|
-
|
32
|
+
# Rollbar::Util.truncate will operate on characters, not bytes,
|
33
|
+
# so use value.length, not bytesize.
|
34
|
+
if value.is_a?(String) && value.length > threshold
|
33
35
|
Rollbar::Util.truncate(value, threshold)
|
34
36
|
else
|
35
37
|
value
|
data/lib/rollbar/util/hash.rb
CHANGED
@@ -2,9 +2,10 @@ module Rollbar
|
|
2
2
|
module Util
|
3
3
|
module Hash # :nodoc:
|
4
4
|
def self.deep_stringify_keys(hash, seen = {})
|
5
|
-
|
5
|
+
seen.compare_by_identity
|
6
|
+
return if seen[hash]
|
6
7
|
|
7
|
-
seen[hash
|
8
|
+
seen[hash] = true
|
8
9
|
replace_seen_children(hash, seen)
|
9
10
|
|
10
11
|
hash.reduce({}) do |h, (key, value)|
|
@@ -19,10 +20,10 @@ module Rollbar
|
|
19
20
|
when ::Hash
|
20
21
|
send(meth, thing, seen)
|
21
22
|
when Array
|
22
|
-
if seen[thing
|
23
|
+
if seen[thing]
|
23
24
|
thing
|
24
25
|
else
|
25
|
-
seen[thing
|
26
|
+
seen[thing] = true
|
26
27
|
replace_seen_children(thing, seen)
|
27
28
|
thing.map { |v| map_value(v, meth, seen) }
|
28
29
|
end
|
@@ -34,12 +35,18 @@ module Rollbar
|
|
34
35
|
def self.replace_seen_children(thing, seen)
|
35
36
|
case thing
|
36
37
|
when ::Hash
|
37
|
-
thing.keys.each do |key|
|
38
|
-
|
38
|
+
thing.keys.each do |key| # rubocop:disable Style/HashEachMethods
|
39
|
+
if seen[thing[key]]
|
40
|
+
thing[key] =
|
41
|
+
"removed circular reference: #{thing[key]}"
|
42
|
+
end
|
39
43
|
end
|
40
44
|
when Array
|
41
45
|
thing.each_with_index do |_, i|
|
42
|
-
|
46
|
+
if seen[thing[i]]
|
47
|
+
thing[i] =
|
48
|
+
"removed circular reference: #{thing[i]}"
|
49
|
+
end
|
43
50
|
end
|
44
51
|
end
|
45
52
|
end
|
@@ -24,7 +24,7 @@ module Rollbar
|
|
24
24
|
def self.anonymize_ipv6(ip)
|
25
25
|
ip_parts = ip.to_s.split ':'
|
26
26
|
|
27
|
-
ip_string = ip_parts[0..2].join(':')
|
27
|
+
ip_string = "#{ip_parts[0..2].join(':')}:0000:0000:0000:0000:0000"
|
28
28
|
|
29
29
|
IPAddr.new(ip_string).to_s
|
30
30
|
end
|
data/lib/rollbar/util.rb
CHANGED
@@ -2,10 +2,15 @@ require 'rollbar/util/hash'
|
|
2
2
|
|
3
3
|
module Rollbar
|
4
4
|
module Util # :nodoc:
|
5
|
+
def self.iterate_and_update_with_block(obj, &block)
|
6
|
+
iterate_and_update(obj, block)
|
7
|
+
end
|
8
|
+
|
5
9
|
def self.iterate_and_update(obj, block, seen = {})
|
6
|
-
|
10
|
+
seen.compare_by_identity
|
11
|
+
return if obj.frozen? || seen[obj]
|
7
12
|
|
8
|
-
seen[obj
|
13
|
+
seen[obj] = true
|
9
14
|
|
10
15
|
if obj.is_a?(Array)
|
11
16
|
iterate_and_update_array(obj, block, seen)
|
@@ -25,7 +30,7 @@ module Rollbar
|
|
25
30
|
end
|
26
31
|
|
27
32
|
def self.iterate_and_update_hash(obj, block, seen)
|
28
|
-
obj.keys.each do |k|
|
33
|
+
obj.keys.each do |k| # rubocop:disable Style/HashEachMethods
|
29
34
|
v = obj[k]
|
30
35
|
new_key = block.call(k)
|
31
36
|
|
@@ -43,18 +48,21 @@ module Rollbar
|
|
43
48
|
end
|
44
49
|
|
45
50
|
def self.deep_copy(obj, copied = {})
|
51
|
+
copied.compare_by_identity
|
52
|
+
|
46
53
|
# if we've already made a copy, return it.
|
47
|
-
return copied[obj
|
54
|
+
return copied[obj] if copied[obj]
|
48
55
|
|
49
56
|
result = clone_obj(obj)
|
50
57
|
|
51
58
|
# Memoize the cloned object before recursive calls to #deep_copy below.
|
52
59
|
# This is the point of doing the work in two steps.
|
53
|
-
copied[obj
|
60
|
+
copied[obj] = result
|
54
61
|
|
55
|
-
|
62
|
+
case obj
|
63
|
+
when ::Hash
|
56
64
|
obj.each { |k, v| result[k] = deep_copy(v, copied) }
|
57
|
-
|
65
|
+
when Array
|
58
66
|
obj.each { |v| result << deep_copy(v, copied) }
|
59
67
|
end
|
60
68
|
|
@@ -62,9 +70,10 @@ module Rollbar
|
|
62
70
|
end
|
63
71
|
|
64
72
|
def self.clone_obj(obj)
|
65
|
-
|
73
|
+
case obj
|
74
|
+
when ::Hash
|
66
75
|
obj.dup
|
67
|
-
|
76
|
+
when Array
|
68
77
|
obj.dup.clear
|
69
78
|
else
|
70
79
|
obj
|
@@ -74,12 +83,13 @@ module Rollbar
|
|
74
83
|
def self.deep_merge(hash1, hash2, merged = {})
|
75
84
|
hash1 ||= {}
|
76
85
|
hash2 ||= {}
|
86
|
+
merged.compare_by_identity
|
77
87
|
|
78
88
|
# If we've already merged these two objects, return hash1 now.
|
79
|
-
return hash1 if merged[hash1
|
89
|
+
return hash1 if merged[hash1] && merged[hash1].include?(hash2.object_id)
|
80
90
|
|
81
|
-
merged[hash1
|
82
|
-
merged[hash1
|
91
|
+
merged[hash1] ||= []
|
92
|
+
merged[hash1] << hash2.object_id
|
83
93
|
|
84
94
|
perform_deep_merge(hash1, hash2, merged)
|
85
95
|
|
@@ -117,7 +127,7 @@ module Rollbar
|
|
117
127
|
end
|
118
128
|
|
119
129
|
def self.count_method_in_stack(method_symbol, file_path = '')
|
120
|
-
caller.grep(/#{file_path}.*#{method_symbol
|
130
|
+
caller.grep(/#{file_path}.*#{method_symbol}/).count
|
121
131
|
end
|
122
132
|
|
123
133
|
def self.method_in_stack(method_symbol, file_path = '')
|
data/lib/rollbar/version.rb
CHANGED
data/lib/rollbar.rb
CHANGED
@@ -8,6 +8,7 @@ require 'forwardable'
|
|
8
8
|
begin
|
9
9
|
require 'securerandom'
|
10
10
|
rescue LoadError
|
11
|
+
# Skip loading
|
11
12
|
end
|
12
13
|
|
13
14
|
require 'rollbar/version'
|
@@ -31,8 +32,7 @@ module Rollbar
|
|
31
32
|
|
32
33
|
def_delegators :notifier, *PUBLIC_NOTIFIER_METHODS
|
33
34
|
|
34
|
-
attr_writer :plugins
|
35
|
-
attr_writer :root_notifier
|
35
|
+
attr_writer :plugins, :root_notifier
|
36
36
|
|
37
37
|
def notifier
|
38
38
|
# Use the global instance @root_notifier so we don't fall
|
@@ -160,8 +160,10 @@ module Rollbar
|
|
160
160
|
|
161
161
|
# Backwards compatibility methods
|
162
162
|
|
163
|
-
def report_exception(exception, request_data = nil, person_data = nil,
|
164
|
-
|
163
|
+
def report_exception(exception, request_data = nil, person_data = nil,
|
164
|
+
level = 'error')
|
165
|
+
Kernel.warn('[DEPRECATION] Rollbar.report_exception has been deprecated, ' \
|
166
|
+
'please use log() or one of the level functions')
|
165
167
|
|
166
168
|
scope = {}
|
167
169
|
scope[:request] = request_data if request_data
|
@@ -173,13 +175,16 @@ module Rollbar
|
|
173
175
|
end
|
174
176
|
|
175
177
|
def report_message(message, level = 'info', extra_data = nil)
|
176
|
-
Kernel.warn('[DEPRECATION] Rollbar.report_message has been deprecated,
|
178
|
+
Kernel.warn('[DEPRECATION] Rollbar.report_message has been deprecated, ' \
|
179
|
+
'please use log() or one of the level functions')
|
177
180
|
|
178
181
|
Rollbar.notifier.log(level, message, extra_data)
|
179
182
|
end
|
180
183
|
|
181
|
-
def report_message_with_request(message, level = 'info', request_data = nil,
|
182
|
-
|
184
|
+
def report_message_with_request(message, level = 'info', request_data = nil,
|
185
|
+
person_data = nil, extra_data = nil)
|
186
|
+
Kernel.warn('[DEPRECATION] Rollbar.report_message_with_request has been ' \
|
187
|
+
'deprecated, please use log() or one of the level functions')
|
183
188
|
|
184
189
|
scope = {}
|
185
190
|
scope[:request] = request_data if request_data
|
data/lib/tasks/benchmark.rake
CHANGED
@@ -77,7 +77,8 @@ class BenchmarkTraceWithBindings # :nodoc:
|
|
77
77
|
def trace_point # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
78
78
|
return unless defined?(TracePoint)
|
79
79
|
|
80
|
-
@trace_point ||= TracePoint.new(:call, :return, :b_call, :b_return, :c_call,
|
80
|
+
@trace_point ||= TracePoint.new(:call, :return, :b_call, :b_return, :c_call,
|
81
|
+
:c_return, :raise) do |tp|
|
81
82
|
next if options['hook_only']
|
82
83
|
|
83
84
|
case tp.event
|
data/rollbar.gemspec
CHANGED
@@ -7,15 +7,18 @@ Gem::Specification.new do |gem|
|
|
7
7
|
|
8
8
|
gem.authors = ['Rollbar, Inc.']
|
9
9
|
gem.email = ['support@rollbar.com']
|
10
|
-
gem.description = '
|
10
|
+
gem.description = "Track and debug errors in your Ruby applications with ease using Rollbar. With this gem, you can easily monitor and report on exceptions and other errors in your code, helping you identify and fix issues more quickly. Rollbar's intuitive interface and advanced error tracking features make it the perfect tool for ensuring the stability and reliability of your Ruby applications."
|
11
11
|
gem.executables = ['rollbar-rails-runner']
|
12
12
|
gem.summary = 'Reports exceptions to Rollbar'
|
13
13
|
gem.homepage = 'https://rollbar.com'
|
14
14
|
gem.license = 'MIT'
|
15
|
-
gem.files = `git ls-files -z`.split("\x0").reject
|
15
|
+
gem.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
gem.files += ['spec/support/rollbar_api.rb'] # useful helper for app spec/tests.
|
16
19
|
gem.name = 'rollbar'
|
17
20
|
gem.require_paths = ['lib']
|
18
|
-
gem.required_ruby_version = '>=
|
21
|
+
gem.required_ruby_version = '>= 2.0.0'
|
19
22
|
gem.version = Rollbar::VERSION
|
20
23
|
|
21
24
|
if gem.respond_to?(:metadata)
|