rollbar 3.1.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +18 -1
  3. data/.rubocop.yml +81 -34
  4. data/Gemfile +17 -10
  5. data/README.md +1 -1
  6. data/data/rollbar.snippet.js +1 -1
  7. data/gemfiles/rails30.gemfile +11 -12
  8. data/gemfiles/rails31.gemfile +12 -13
  9. data/gemfiles/rails32.gemfile +5 -6
  10. data/gemfiles/rails40.gemfile +3 -5
  11. data/gemfiles/rails41.gemfile +3 -6
  12. data/gemfiles/rails42.gemfile +5 -10
  13. data/gemfiles/rails50.gemfile +9 -10
  14. data/gemfiles/rails51.gemfile +8 -9
  15. data/gemfiles/rails52.gemfile +6 -5
  16. data/gemfiles/rails60.gemfile +7 -12
  17. data/gemfiles/rails61.gemfile +54 -0
  18. data/lib/generators/rollbar/rollbar_generator.rb +18 -14
  19. data/lib/generators/rollbar/templates/{initializer.rb → initializer.erb} +0 -0
  20. data/lib/rails/rollbar_runner.rb +12 -5
  21. data/lib/rollbar/capistrano.rb +16 -8
  22. data/lib/rollbar/capistrano3.rb +8 -2
  23. data/lib/rollbar/capistrano_tasks.rb +37 -10
  24. data/lib/rollbar/configuration.rb +114 -90
  25. data/lib/rollbar/delay/shoryuken.rb +4 -3
  26. data/lib/rollbar/delay/sidekiq.rb +3 -1
  27. data/lib/rollbar/delay/sucker_punch.rb +1 -2
  28. data/lib/rollbar/delay/thread.rb +3 -2
  29. data/lib/rollbar/deploy.rb +6 -7
  30. data/lib/rollbar/encoding/encoder.rb +7 -3
  31. data/lib/rollbar/exception_reporter.rb +17 -8
  32. data/lib/rollbar/item/backtrace.rb +10 -8
  33. data/lib/rollbar/item/frame.rb +6 -5
  34. data/lib/rollbar/item/locals.rb +3 -2
  35. data/lib/rollbar/item.rb +48 -39
  36. data/lib/rollbar/json.rb +1 -1
  37. data/lib/rollbar/lazy_store.rb +1 -3
  38. data/lib/rollbar/logger.rb +2 -0
  39. data/lib/rollbar/logger_proxy.rb +3 -1
  40. data/lib/rollbar/middleware/js.rb +58 -36
  41. data/lib/rollbar/middleware/rack/builder.rb +3 -3
  42. data/lib/rollbar/middleware/rack/test_session.rb +3 -3
  43. data/lib/rollbar/middleware/rack.rb +4 -4
  44. data/lib/rollbar/middleware/rails/rollbar.rb +9 -6
  45. data/lib/rollbar/middleware/rails/show_exceptions.rb +8 -4
  46. data/lib/rollbar/notifier/trace_with_bindings.rb +4 -2
  47. data/lib/rollbar/notifier.rb +179 -133
  48. data/lib/rollbar/plugin.rb +8 -8
  49. data/lib/rollbar/plugins/active_job.rb +11 -2
  50. data/lib/rollbar/plugins/delayed_job/plugin.rb +10 -3
  51. data/lib/rollbar/plugins/goalie.rb +27 -16
  52. data/lib/rollbar/plugins/rails/controller_methods.rb +18 -14
  53. data/lib/rollbar/plugins/rails/railtie30.rb +2 -1
  54. data/lib/rollbar/plugins/rails/railtie32.rb +2 -1
  55. data/lib/rollbar/plugins/rails/railtie_mixin.rb +2 -2
  56. data/lib/rollbar/plugins/rails.rb +5 -2
  57. data/lib/rollbar/plugins/rake.rb +2 -1
  58. data/lib/rollbar/plugins/sidekiq/plugin.rb +37 -20
  59. data/lib/rollbar/plugins/sidekiq.rb +1 -1
  60. data/lib/rollbar/plugins/thread.rb +8 -7
  61. data/lib/rollbar/plugins/validations.rb +3 -1
  62. data/lib/rollbar/rake_tasks.rb +0 -1
  63. data/lib/rollbar/request_data_extractor.rb +38 -17
  64. data/lib/rollbar/rollbar_test.rb +3 -1
  65. data/lib/rollbar/scrubbers/params.rb +13 -7
  66. data/lib/rollbar/scrubbers/url.rb +48 -14
  67. data/lib/rollbar/scrubbers.rb +1 -1
  68. data/lib/rollbar/truncation/remove_any_key_strategy.rb +4 -1
  69. data/lib/rollbar/truncation/remove_extra_strategy.rb +3 -1
  70. data/lib/rollbar/util/hash.rb +14 -7
  71. data/lib/rollbar/util/ip_anonymizer.rb +1 -1
  72. data/lib/rollbar/util.rb +19 -13
  73. data/lib/rollbar/version.rb +1 -1
  74. data/lib/rollbar.rb +12 -7
  75. data/lib/tasks/benchmark.rake +2 -1
  76. data/rollbar.gemspec +3 -1
  77. metadata +5 -5
@@ -11,29 +11,40 @@ Rollbar.plugins.define('goalie') do
11
11
  begin
12
12
  controller = env['action_controller.instance']
13
13
  request_data = begin
14
- controller.rollbar_request_data
15
- rescue StandardError
16
- nil
17
- end
14
+ controller.rollbar_request_data
15
+ rescue StandardError
16
+ nil
17
+ end
18
18
  person_data = begin
19
- controller.rollbar_person_data
20
- rescue StandardError
21
- nil
22
- end
23
- exception_data = Rollbar.scope(:request => request_data, :person => person_data).error(exception, :use_exception_level_filters => true)
19
+ controller.rollbar_person_data
20
+ rescue StandardError
21
+ nil
22
+ end
23
+ exception_data = Rollbar.scope(
24
+ :request => request_data,
25
+ :person => person_data
26
+ ).error(exception, :use_exception_level_filters => true)
24
27
  rescue StandardError => e
25
- Rollbar.log_warning "[Rollbar] Exception while reporting exception to Rollbar: #{e}"
28
+ message = "[Rollbar] Exception while reporting exception to Rollbar: #{e}"
29
+ Rollbar.log_warning(message)
26
30
  end
27
31
 
28
32
  # if an exception was reported, save uuid in the env
29
33
  # so it can be displayed to the user on the error page
30
- if exception_data.is_a?(Hash)
34
+ case exception_data
35
+ when Hash
31
36
  env['rollbar.exception_uuid'] = exception_data[:uuid]
32
- Rollbar.log_info "[Rollbar] Exception uuid saved in env: #{exception_data[:uuid]}"
33
- elsif exception_data == 'disabled'
34
- Rollbar.log_info '[Rollbar] Exception not reported because Rollbar is disabled'
35
- elsif exception_data == 'ignored'
36
- Rollbar.log_info '[Rollbar] Exception not reported because it was ignored'
37
+ Rollbar.log_info(
38
+ "[Rollbar] Exception uuid saved in env: #{exception_data[:uuid]}"
39
+ )
40
+ when 'disabled'
41
+ Rollbar.log_info(
42
+ '[Rollbar] Exception not reported because Rollbar is disabled'
43
+ )
44
+ when 'ignored'
45
+ Rollbar.log_info(
46
+ '[Rollbar] Exception not reported because it was ignored'
47
+ )
37
48
  end
38
49
 
39
50
  # now continue as normal
@@ -7,30 +7,34 @@ module Rollbar
7
7
  include RequestDataExtractor
8
8
 
9
9
  def rollbar_person_data
10
- (user = send(Rollbar.configuration.person_method)) unless Rollbar::Util.method_in_stack_twice(:rollbar_person_data, __FILE__)
10
+ user = nil
11
+ unless Rollbar::Util.method_in_stack_twice(:rollbar_person_data, __FILE__)
12
+ user = send(Rollbar.configuration.person_method)
13
+ end
14
+
11
15
  # include id, username, email if non-empty
12
16
  if user
13
17
  {
14
18
  :id => (begin
15
- user.send(Rollbar.configuration.person_id_method)
16
- rescue StandardError
17
- nil
18
- end),
19
+ user.send(Rollbar.configuration.person_id_method)
20
+ rescue StandardError
21
+ nil
22
+ end),
19
23
  :username => (begin
20
- user.send(Rollbar.configuration.person_username_method)
21
- rescue StandardError
22
- nil
23
- end),
24
+ user.send(Rollbar.configuration.person_username_method)
25
+ rescue StandardError
26
+ nil
27
+ end),
24
28
  :email => (begin
25
- user.send(Rollbar.configuration.person_email_method)
26
- rescue StandardError
27
- nil
28
- end)
29
+ user.send(Rollbar.configuration.person_email_method)
30
+ rescue StandardError
31
+ nil
32
+ end)
29
33
  }
30
34
  else
31
35
  {}
32
36
  end
33
- rescue NoMethodError, NameError
37
+ rescue NameError
34
38
  {}
35
39
  end
36
40
 
@@ -11,7 +11,8 @@ module Rollbar
11
11
 
12
12
  app.config.middleware.insert_after ActionDispatch::ShowExceptions,
13
13
  Rollbar::Middleware::Rails::RollbarMiddleware
14
- ActionDispatch::ShowExceptions.send(:include, Rollbar::Middleware::Rails::ShowExceptions)
14
+ ActionDispatch::ShowExceptions.send(:include,
15
+ Rollbar::Middleware::Rails::ShowExceptions)
15
16
  end
16
17
  end
17
18
  end
@@ -11,7 +11,8 @@ module Rollbar
11
11
 
12
12
  app.config.middleware.insert_after ActionDispatch::DebugExceptions,
13
13
  Rollbar::Middleware::Rails::RollbarMiddleware
14
- ActionDispatch::DebugExceptions.send(:include, Rollbar::Middleware::Rails::ShowExceptions)
14
+ ActionDispatch::DebugExceptions.send(:include,
15
+ Rollbar::Middleware::Rails::ShowExceptions)
15
16
  end
16
17
  end
17
18
  end
@@ -16,9 +16,9 @@ module Rollbar
16
16
  config.framework = "Rails: #{::Rails::VERSION::STRING}"
17
17
  config.filepath ||= begin
18
18
  if ::Rails.application.class.respond_to?(:module_parent_name)
19
- ::Rails.application.class.module_parent_name + '.rollbar'
19
+ "#{::Rails.application.class.module_parent_name}.rollbar"
20
20
  else
21
- ::Rails.application.class.parent_name + '.rollbar'
21
+ "#{::Rails.application.class.parent_name}.rollbar"
22
22
  end
23
23
  end
24
24
  end
@@ -39,7 +39,8 @@ Rollbar.plugins.define('rails-rollbar.js') do
39
39
  end
40
40
 
41
41
  def after_secure_headers(&block)
42
- Rollbar::Railtie.initializer('rollbar.js.frameworks.rails', :after => 'secure_headers.middleware', &block)
42
+ Rollbar::Railtie.initializer('rollbar.js.frameworks.rails',
43
+ :after => 'secure_headers.middleware', &block)
43
44
  end
44
45
 
45
46
  def plugin_execute_proc_body(plugin)
@@ -52,7 +53,8 @@ Rollbar.plugins.define('rails-rollbar.js') do
52
53
  :options => Rollbar.configuration.js_options,
53
54
  :enabled => Rollbar.configuration.js_enabled
54
55
  }
55
- ::Rails.configuration.middleware.use(::Rollbar::Middleware::Js, config)
56
+ ::Rails.configuration.middleware.use(::Rollbar::Middleware::Js,
57
+ config)
56
58
  end
57
59
  end
58
60
  end
@@ -62,6 +64,7 @@ Rollbar.plugins.define('rails-rollbar.js') do
62
64
  begin
63
65
  require 'secure_headers'
64
66
  rescue LoadError
67
+ # Skip loading
65
68
  end
66
69
 
67
70
  defined?(::SecureHeaders::Middleware)
@@ -40,7 +40,8 @@ Rollbar.plugins.define('rake') do
40
40
  end
41
41
 
42
42
  def self.skip_patch
43
- warn('[Rollbar] Rollbar is disabled for Rake tasks since your Rake version is under 0.9.x. Please upgrade to 0.9.x or higher.')
43
+ warn('[Rollbar] Rollbar is disabled for Rake tasks since your Rake ' \
44
+ 'version is under 0.9.x. Please upgrade to 0.9.x or higher.')
44
45
  end
45
46
 
46
47
  def self.patch?
@@ -4,21 +4,39 @@ module Rollbar
4
4
  class Sidekiq
5
5
  PARAM_BLACKLIST = %w[backtrace error_backtrace error_message error_class].freeze
6
6
 
7
- class ClearScope
8
- def call(_worker, _msg, _queue)
9
- Rollbar.reset_notifier!
7
+ class ResetScope
8
+ def call(_worker, msg, _queue, &block)
9
+ Rollbar.reset_notifier! # clears scope
10
10
 
11
- yield
11
+ return yield unless Rollbar.configuration.sidekiq_use_scoped_block
12
+
13
+ Rollbar.scoped(Rollbar::Sidekiq.job_scope(msg), &block)
12
14
  end
13
15
  end
14
16
 
15
- def self.handle_exception(ctx_hash, e)
16
- job_hash = ctx_hash && (ctx_hash[:job] || ctx_hash)
17
- return if skip_report?(job_hash, e)
17
+ def self.handle_exception(msg, e)
18
+ return if skip_report?(msg, e)
19
+
20
+ Rollbar.scope(job_scope(msg)).error(e, :use_exception_level_filters => true)
21
+ end
22
+
23
+ def self.skip_report?(msg, _e)
24
+ job_hash = job_hash_from_msg(msg)
25
+
26
+ return false if job_hash.nil?
27
+
28
+ # when rollbar middleware catches, sidekiq's retry_job processor hasn't set
29
+ # the retry_count for the current job yet, so adding 1 gives the actual retry count
30
+ actual_retry_count = job_hash.fetch('retry_count', -1) + 1
31
+ job_hash['retry'] && actual_retry_count < ::Rollbar.configuration.sidekiq_threshold
32
+ end
18
33
 
34
+ def self.job_scope(msg)
19
35
  scope = {
20
36
  :framework => "Sidekiq: #{::Sidekiq::VERSION}"
21
37
  }
38
+ job_hash = job_hash_from_msg(msg)
39
+
22
40
  unless job_hash.nil?
23
41
  params = job_hash.reject { |k| PARAM_BLACKLIST.include?(k) }
24
42
  scope[:request] = { :params => scrub_params(params) }
@@ -26,7 +44,7 @@ module Rollbar
26
44
  scope[:queue] = params['queue']
27
45
  end
28
46
 
29
- Rollbar.scope(scope).error(e, :use_exception_level_filters => true)
47
+ scope
30
48
  end
31
49
 
32
50
  def self.scrub_params(params)
@@ -38,22 +56,21 @@ module Rollbar
38
56
  Rollbar::Scrubbers::Params.call(options)
39
57
  end
40
58
 
41
- def self.skip_report?(job_hash, _e)
42
- return false if job_hash.nil?
59
+ # see https://github.com/mperham/sidekiq/wiki/Middleware#server-middleware
60
+ def call(_worker, msg, _queue, &block)
61
+ Rollbar.reset_notifier! # clears scope
43
62
 
44
- # when rollbar middleware catches, sidekiq's retry_job processor hasn't set
45
- # the retry_count for the current job yet, so adding 1 gives the actual retry count
46
- actual_retry_count = job_hash.fetch('retry_count', -1) + 1
47
- job_hash['retry'] && actual_retry_count < ::Rollbar.configuration.sidekiq_threshold
48
- end
49
-
50
- def call(_worker, msg, _queue)
51
- Rollbar.reset_notifier!
63
+ return yield unless Rollbar.configuration.sidekiq_use_scoped_block
52
64
 
53
- yield
54
- rescue Exception => e
65
+ Rollbar.scoped(Rollbar::Sidekiq.job_scope(msg), &block)
66
+ rescue Exception => e # rubocop:disable Lint/RescueException
55
67
  Rollbar::Sidekiq.handle_exception(msg, e)
56
68
  raise
57
69
  end
70
+
71
+ def self.job_hash_from_msg(msg)
72
+ msg && (msg[:job] || msg)
73
+ end
74
+ private_class_method :job_hash_from_msg
58
75
  end
59
76
  end
@@ -9,7 +9,7 @@ Rollbar.plugins.define('sidekiq >= 3') do
9
9
 
10
10
  Sidekiq.configure_server do |config|
11
11
  config.server_middleware do |chain|
12
- chain.add Rollbar::Sidekiq::ClearScope
12
+ chain.add Rollbar::Sidekiq::ResetScope
13
13
  end
14
14
 
15
15
  config.error_handlers << proc do |e, context|
@@ -1,13 +1,14 @@
1
1
  Rollbar.plugins.define('thread') do
2
- execute do
3
- Thread.class_eval do
4
- def initialize_with_rollbar(*args, &block)
2
+ module Rollbar
3
+ module ThreadPlugin
4
+ def initialize(*args)
5
5
  self[:_rollbar_notifier] ||= Rollbar.notifier.scope
6
- initialize_without_rollbar(*args, &block)
6
+ super
7
7
  end
8
-
9
- alias_method :initialize_without_rollbar, :initialize
10
- alias_method :initialize, :initialize_with_rollbar
11
8
  end
12
9
  end
10
+
11
+ execute do
12
+ Thread.send(:prepend, Rollbar::ThreadPlugin)
13
+ end
13
14
  end
@@ -17,7 +17,9 @@ Rollbar.plugins.define('active_model') do
17
17
  module ActiveRecordExtension
18
18
  def report_validation_errors_to_rollbar
19
19
  errors.full_messages.each do |error|
20
- Rollbar.log_info "[Rollbar] Reporting form validation error: #{error} for #{self}"
20
+ Rollbar.log_info(
21
+ "[Rollbar] Reporting form validation error: #{error} for #{self}"
22
+ )
21
23
  Rollbar.warning("Form Validation Error: #{error} for #{self}")
22
24
  end
23
25
  end
@@ -1,4 +1,3 @@
1
-
2
1
  namespace :rollbar do
3
2
  desc 'Verify your gem installation by sending a test message to Rollbar'
4
3
  task :test => [:environment] do
@@ -19,10 +19,10 @@ module Rollbar
19
19
  else
20
20
  controller = env['action_controller.instance']
21
21
  person_data = begin
22
- controller.rollbar_person_data
23
- rescue StandardError
24
- {}
25
- end
22
+ controller.rollbar_person_data
23
+ rescue StandardError
24
+ {}
25
+ end
26
26
  end
27
27
 
28
28
  person_data
@@ -34,7 +34,8 @@ module Rollbar
34
34
 
35
35
  get_params = scrub_params(rollbar_get_params(rack_req), sensitive_params)
36
36
  post_params = scrub_params(rollbar_post_params(rack_req), sensitive_params)
37
- raw_body_params = scrub_params(mergeable_raw_body_params(rack_req), sensitive_params)
37
+ raw_body_params = scrub_params(mergeable_raw_body_params(rack_req),
38
+ sensitive_params)
38
39
  cookies = scrub_params(rollbar_request_cookies(rack_req), sensitive_params)
39
40
  session = scrub_params(rollbar_request_session(env), sensitive_params)
40
41
  route_params = scrub_params(rollbar_route_params(env), sensitive_params)
@@ -54,7 +55,10 @@ module Rollbar
54
55
  :method => rollbar_request_method(env)
55
56
  }
56
57
 
57
- data[:request_id] = env['action_dispatch.request_id'] if env['action_dispatch.request_id']
58
+ if env['action_dispatch.request_id']
59
+ data[:request_id] =
60
+ env['action_dispatch.request_id']
61
+ end
58
62
 
59
63
  data
60
64
  end
@@ -87,9 +91,10 @@ module Rollbar
87
91
  def mergeable_raw_body_params(rack_req)
88
92
  raw_body_params = rollbar_raw_body_params(rack_req)
89
93
 
90
- if raw_body_params.is_a?(Hash)
94
+ case raw_body_params
95
+ when Hash
91
96
  raw_body_params
92
- elsif raw_body_params.is_a?(Array)
97
+ when Array
93
98
  { 'body.multi' => raw_body_params }
94
99
  else
95
100
  { 'body.value' => raw_body_params }
@@ -109,13 +114,17 @@ module Rollbar
109
114
  { name => Rollbar::Scrubbers.scrub_value(env[header]) }
110
115
  elsif name == 'X-Forwarded-For' && !Rollbar.configuration.collect_user_ip
111
116
  {}
112
- elsif name == 'X-Forwarded-For' && Rollbar.configuration.collect_user_ip && Rollbar.configuration.anonymize_user_ip
117
+ elsif name == 'X-Forwarded-For' &&
118
+ Rollbar.configuration.collect_user_ip &&
119
+ Rollbar.configuration.anonymize_user_ip
113
120
  ips = env[header].sub(' ', '').split(',')
114
121
  ips = ips.map { |ip| Rollbar::Util::IPAnonymizer.anonymize_ip(ip) }
115
122
  { name => ips.join(', ') }
116
123
  elsif name == 'X-Real-Ip' && !Rollbar.configuration.collect_user_ip
117
124
  {}
118
- elsif name == 'X-Real-Ip' && Rollbar.configuration.collect_user_ip && Rollbar.configuration.anonymize_user_ip
125
+ elsif name == 'X-Real-Ip' &&
126
+ Rollbar.configuration.collect_user_ip &&
127
+ Rollbar.configuration.anonymize_user_ip
119
128
  { name => Rollbar::Util::IPAnonymizer.anonymize_ip(env[header]) }
120
129
  else
121
130
  { name => env[header] }
@@ -131,16 +140,15 @@ module Rollbar
131
140
  host = host.split(',').first.strip unless host.empty?
132
141
 
133
142
  path = env['ORIGINAL_FULLPATH'] || env['REQUEST_URI']
134
- path ||= "#{env['SCRIPT_NAME']}#{env['PATH_INFO']}#{"?#{env['QUERY_STRING']}" unless env['QUERY_STRING'].to_s.empty?}"
135
- unless path.nil? || path.empty?
136
- path = '/' + path.to_s if path.to_s.slice(0, 1) != '/'
137
- end
143
+ query = env['QUERY_STRING'].to_s.empty? ? nil : "?#{env['QUERY_STRING']}"
144
+ path ||= "#{env['SCRIPT_NAME']}#{env['PATH_INFO']}#{query}"
145
+ path = "/#{path}" if !(path.nil? || path.empty?) && (path.to_s.slice(0, 1) != '/')
138
146
 
139
147
  port = env['HTTP_X_FORWARDED_PORT']
140
148
  if port && !(!scheme.nil? && scheme.casecmp('http').zero? && port.to_i == 80) && \
141
149
  !(!scheme.nil? && scheme.casecmp('https').zero? && port.to_i == 443) && \
142
150
  !(host.include? ':')
143
- host = host + ':' + port
151
+ host = "#{host}:#{port}"
144
152
  end
145
153
 
146
154
  [scheme, '://', host, path].join
@@ -149,7 +157,11 @@ module Rollbar
149
157
  def rollbar_user_ip(env)
150
158
  return nil unless Rollbar.configuration.collect_user_ip
151
159
 
152
- user_ip_string = (env['action_dispatch.remote_ip'] || env['HTTP_X_REAL_IP'] || x_forwarded_for_client(env['HTTP_X_FORWARDED_FOR']) || env['REMOTE_ADDR']).to_s
160
+ user_ip_string = (user_ip_at_configured_key(env) ||
161
+ env['action_dispatch.remote_ip'] ||
162
+ env['HTTP_X_REAL_IP'] ||
163
+ x_forwarded_for_client(env['HTTP_X_FORWARDED_FOR']) ||
164
+ env['REMOTE_ADDR']).to_s
153
165
 
154
166
  user_ip_string = Rollbar::Util::IPAnonymizer.anonymize_ip(user_ip_string)
155
167
 
@@ -158,6 +170,12 @@ module Rollbar
158
170
  nil
159
171
  end
160
172
 
173
+ def user_ip_at_configured_key(env)
174
+ return nil unless Rollbar.configuration.user_ip_rack_env_key
175
+
176
+ env[Rollbar.configuration.user_ip_rack_env_key]
177
+ end
178
+
161
179
  def x_forwarded_for_client(header_value)
162
180
  return nil unless header_value
163
181
 
@@ -248,7 +266,10 @@ module Rollbar
248
266
  end
249
267
 
250
268
  def sensitive_headers_list
251
- return [] unless Rollbar.configuration.scrub_headers && Rollbar.configuration.scrub_headers.is_a?(Array)
269
+ unless Rollbar.configuration.scrub_headers &&
270
+ Rollbar.configuration.scrub_headers.is_a?(Array)
271
+ return []
272
+ end
252
273
 
253
274
  # Normalize into the expected matching format
254
275
  Rollbar.configuration.scrub_headers.map do |header|
@@ -27,7 +27,9 @@ module RollbarTest # :nodoc:
27
27
  end
28
28
 
29
29
  def self.error_message
30
- 'Test failed! You may have a configuration issue, or you could be using a gem that\'s blocking the test. Contact support@rollbar.com if you need help troubleshooting.'
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.'
31
33
  end
32
34
 
33
35
  def self.success_message
@@ -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 Rack::Multipart::UploadedFile].freeze
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
- @scrubbed_object_ids = {}
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 { |f| f.is_a?(String) || f.is_a?(Symbol) || f.is_a?(Regexp) }
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 { |val| val.is_a?(Regexp) ? val : /\A#{Regexp.escape(val.to_s)}\z/ }.join('|'))
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 @scrubbed_object_ids[params.object_id]
67
+ return params if @scrubbed_objects[params]
63
68
 
64
- @scrubbed_object_ids[params.object_id] = true
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) && !(whitelist_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
- Rollbar.logger.error("[Rollbar] There was an error scrubbing the url: #{e}, options: #{options.inspect}")
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, scrub_all, whitelist)
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, randomize_scrub_length)
44
- uri.query = filter_query(uri.query, regex, randomize_scrub_length, scrub_all, whitelist)
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 ? filtered_value(password, randomize_scrub_length) : 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,7 +92,8 @@ module Rollbar
67
92
 
68
93
  params = decode_www_form(query)
69
94
 
70
- encode_www_form(filter_query_params(params, regex, randomize_scrub_length, scrub_all, whitelist))
95
+ encode_www_form(filter_query_params(params, regex, randomize_scrub_length,
96
+ scrub_all, whitelist))
71
97
  end
72
98
 
73
99
  def decode_www_form(query)
@@ -81,14 +107,22 @@ module Rollbar
81
107
  def restore_square_brackets(query)
82
108
  # We want this to rebuild array params like foo[]=1&foo[]=2
83
109
  #
84
- # URI.encode_www_form follows the spec at https://url.spec.whatwg.org/#concept-urlencoded-serializer
110
+ # URI.encode_www_form follows the spec at
111
+ # https://url.spec.whatwg.org/#concept-urlencoded-serializer
85
112
  # and percent encodes square brackets. Here we change them back.
86
113
  query.gsub('%5B', '[').gsub('%5D', ']')
87
114
  end
88
115
 
89
- def filter_query_params(params, regex, randomize_scrub_length, scrub_all, whitelist)
116
+ def filter_query_params(params, regex, randomize_scrub_length, scrub_all,
117
+ whitelist)
90
118
  params.map do |key, value|
91
- [key, filter_key?(key, regex, scrub_all, whitelist) ? filtered_value(value, randomize_scrub_length) : value]
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]
92
126
  end
93
127
  end
94
128
 
@@ -101,10 +135,10 @@ module Rollbar
101
135
  random_filtered_value
102
136
  else
103
137
  '*' * (begin
104
- value.length
105
- rescue StandardError
106
- 8
107
- end)
138
+ value.length
139
+ rescue StandardError
140
+ 8
141
+ end)
108
142
  end
109
143
  end
110
144
 
@@ -2,7 +2,7 @@ module Rollbar
2
2
  module Scrubbers
3
3
  module_function
4
4
 
5
- def scrub_value(value)
5
+ def scrub_value(_value)
6
6
  if Rollbar.configuration.randomize_scrub_length
7
7
  random_filtered_value
8
8
  else
@@ -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
- return extract_title_from_trace(body['trace_chain'][0]) if body['trace_chain'] && body['trace_chain'][0]
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)