rollbar 2.22.1 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.github/pull_request_template.md +34 -0
  3. data/.github/workflows/ci.yml +104 -0
  4. data/.rubocop.yml +185 -33
  5. data/Gemfile +26 -28
  6. data/README.md +32 -8
  7. data/data/rollbar.snippet.js +1 -1
  8. data/docs/configuration.md +8 -0
  9. data/gemfiles/rails30.gemfile +17 -35
  10. data/gemfiles/rails31.gemfile +20 -37
  11. data/gemfiles/rails32.gemfile +13 -31
  12. data/gemfiles/rails40.gemfile +12 -32
  13. data/gemfiles/rails41.gemfile +11 -31
  14. data/gemfiles/rails42.gemfile +12 -32
  15. data/gemfiles/rails50.gemfile +16 -30
  16. data/gemfiles/rails51.gemfile +16 -30
  17. data/gemfiles/rails52.gemfile +10 -19
  18. data/gemfiles/rails60.gemfile +10 -25
  19. data/gemfiles/rails61.gemfile +52 -0
  20. data/gemfiles/rails70.gemfile +52 -0
  21. data/lib/generators/rollbar/rollbar_generator.rb +18 -14
  22. data/lib/rails/rollbar_runner.rb +11 -20
  23. data/lib/rollbar/capistrano.rb +17 -9
  24. data/lib/rollbar/capistrano3.rb +8 -2
  25. data/lib/rollbar/capistrano_tasks.rb +44 -8
  26. data/lib/rollbar/configuration.rb +138 -84
  27. data/lib/rollbar/delay/girl_friday.rb +3 -7
  28. data/lib/rollbar/delay/resque.rb +2 -3
  29. data/lib/rollbar/delay/shoryuken.rb +4 -3
  30. data/lib/rollbar/delay/sidekiq.rb +5 -5
  31. data/lib/rollbar/delay/sucker_punch.rb +4 -6
  32. data/lib/rollbar/delay/thread.rb +17 -2
  33. data/lib/rollbar/deploy.rb +8 -7
  34. data/lib/rollbar/encoding/encoder.rb +17 -6
  35. data/lib/rollbar/encoding.rb +2 -7
  36. data/lib/rollbar/exception_reporter.rb +17 -8
  37. data/lib/rollbar/item/backtrace.rb +22 -10
  38. data/lib/rollbar/item/frame.rb +8 -5
  39. data/lib/rollbar/item/locals.rb +49 -2
  40. data/lib/rollbar/item.rb +80 -50
  41. data/lib/rollbar/json.rb +2 -1
  42. data/lib/rollbar/language_support.rb +0 -6
  43. data/lib/rollbar/lazy_store.rb +3 -7
  44. data/lib/rollbar/logger.rb +2 -0
  45. data/lib/rollbar/logger_proxy.rb +3 -1
  46. data/lib/rollbar/middleware/js/json_value.rb +15 -5
  47. data/lib/rollbar/middleware/js.rb +70 -38
  48. data/lib/rollbar/middleware/rack/builder.rb +3 -3
  49. data/lib/rollbar/middleware/rack/test_session.rb +3 -3
  50. data/lib/rollbar/middleware/rack.rb +4 -4
  51. data/lib/rollbar/middleware/rails/rollbar.rb +9 -6
  52. data/lib/rollbar/middleware/rails/show_exceptions.rb +8 -4
  53. data/lib/rollbar/notifier/trace_with_bindings.rb +13 -3
  54. data/lib/rollbar/notifier.rb +309 -172
  55. data/lib/rollbar/plugin.rb +8 -8
  56. data/lib/rollbar/plugins/active_job.rb +20 -3
  57. data/lib/rollbar/plugins/delayed_job/plugin.rb +19 -2
  58. data/lib/rollbar/plugins/error_context.rb +11 -0
  59. data/lib/rollbar/plugins/goalie.rb +27 -16
  60. data/lib/rollbar/plugins/rails/controller_methods.rb +18 -14
  61. data/lib/rollbar/plugins/rails/railtie30.rb +2 -1
  62. data/lib/rollbar/plugins/rails/railtie32.rb +2 -1
  63. data/lib/rollbar/plugins/rails/railtie_mixin.rb +2 -2
  64. data/lib/rollbar/plugins/rails.rb +5 -2
  65. data/lib/rollbar/plugins/rake.rb +2 -1
  66. data/lib/rollbar/plugins/sidekiq/plugin.rb +39 -21
  67. data/lib/rollbar/plugins/sidekiq.rb +1 -1
  68. data/lib/rollbar/plugins/thread.rb +8 -7
  69. data/lib/rollbar/plugins/validations.rb +3 -1
  70. data/lib/rollbar/rake_tasks.rb +1 -2
  71. data/lib/rollbar/request_data_extractor.rb +53 -19
  72. data/lib/rollbar/rollbar_test.rb +9 -118
  73. data/lib/rollbar/scrubbers/params.rb +13 -7
  74. data/lib/rollbar/scrubbers/url.rb +56 -17
  75. data/lib/rollbar/scrubbers.rb +2 -6
  76. data/lib/rollbar/truncation/frames_strategy.rb +1 -1
  77. data/lib/rollbar/truncation/mixin.rb +1 -1
  78. data/lib/rollbar/truncation/remove_any_key_strategy.rb +4 -1
  79. data/lib/rollbar/truncation/remove_extra_strategy.rb +3 -1
  80. data/lib/rollbar/truncation/strings_strategy.rb +4 -2
  81. data/lib/rollbar/util/hash.rb +14 -7
  82. data/lib/rollbar/util/ip_anonymizer.rb +1 -1
  83. data/lib/rollbar/util.rb +23 -13
  84. data/lib/rollbar/version.rb +1 -1
  85. data/lib/rollbar.rb +12 -7
  86. data/lib/tasks/benchmark.rake +2 -1
  87. data/rollbar.gemspec +6 -3
  88. data/spec/support/rollbar_api.rb +67 -0
  89. metadata +19 -12
  90. data/.travis.yml +0 -281
  91. data/lib/rollbar/encoding/legacy_encoder.rb +0 -20
  92. /data/lib/generators/rollbar/templates/{initializer.rb → initializer.erb} +0 -0
@@ -10,11 +10,11 @@ module Rollbar
10
10
  class Js
11
11
  include Rollbar::RequestDataExtractor
12
12
 
13
- attr_reader :app
14
- attr_reader :config
13
+ attr_reader :app, :config
15
14
 
16
15
  JS_IS_INJECTED_KEY = 'rollbar.js_is_injected'.freeze
17
- SNIPPET = File.read(File.expand_path('../../../../data/rollbar.snippet.js', __FILE__))
16
+ SNIPPET = File.read(File.expand_path('../../../../data/rollbar.snippet.js',
17
+ __FILE__))
18
18
 
19
19
  def initialize(app, config)
20
20
  @app = app
@@ -30,7 +30,9 @@ module Rollbar
30
30
  response_string = add_js(env, app_result[2])
31
31
  build_response(env, app_result, response_string)
32
32
  rescue StandardError => e
33
- Rollbar.log_error("[Rollbar] Rollbar.js could not be added because #{e} exception")
33
+ Rollbar.log_error(
34
+ "[Rollbar] Rollbar.js could not be added because #{e} exception"
35
+ )
34
36
 
35
37
  app_result
36
38
  end
@@ -58,7 +60,8 @@ module Rollbar
58
60
  def streaming?(env)
59
61
  return false unless defined?(ActionController::Live)
60
62
 
61
- env['action_controller.instance'].class.included_modules.include?(ActionController::Live)
63
+ env['action_controller.instance']
64
+ .class.included_modules.include?(ActionController::Live)
62
65
  end
63
66
 
64
67
  def add_js(env, response)
@@ -72,7 +75,9 @@ module Rollbar
72
75
 
73
76
  build_body_with_js(env, body, insert_after_idx)
74
77
  rescue StandardError => e
75
- Rollbar.log_error("[Rollbar] Rollbar.js could not be added because #{e} exception")
78
+ Rollbar.log_error(
79
+ "[Rollbar] Rollbar.js could not be added because #{e} exception"
80
+ )
76
81
  nil
77
82
  end
78
83
 
@@ -80,10 +85,22 @@ module Rollbar
80
85
  return app_result unless response_string
81
86
 
82
87
  env[JS_IS_INJECTED_KEY] = true
83
- response = ::Rack::Response.new(response_string, app_result[0],
84
- app_result[1])
85
88
 
86
- response.finish
89
+ status, headers, = app_result
90
+ if headers.key?('Content-Length')
91
+ headers['Content-Length'] =
92
+ response_string.bytesize.to_s
93
+ end
94
+
95
+ response = ::Rack::Response.new(response_string, status, headers)
96
+
97
+ finished = response.finish
98
+
99
+ # Rack < 2.x Response#finish returns self in array[2].
100
+ # Rack >= 2.x returns self.body.
101
+ # Always return with the response object here regardless of rack version.
102
+ finished[2] = response
103
+ finished
87
104
  end
88
105
 
89
106
  def build_body_with_js(env, body, head_open_end)
@@ -116,13 +133,16 @@ module Rollbar
116
133
  end
117
134
 
118
135
  def config_js_tag(env)
136
+ require 'json'
137
+ require 'rollbar/middleware/js/json_value'
138
+
119
139
  js_config = Rollbar::Util.deep_copy(config[:options])
120
140
 
121
141
  add_person_data(js_config, env)
122
142
 
123
143
  # MUST use the Ruby JSON encoder (JSON#generate).
124
144
  # See lib/rollbar/middleware/js/json_value
125
- json = ::JSON.generate(js_config)
145
+ json = ::JSON.generate(js_config, Rollbar::JSON::JsOptionsState.new)
126
146
 
127
147
  script_tag("var _rollbarConfig = #{json};", env)
128
148
  end
@@ -145,14 +165,12 @@ module Rollbar
145
165
  end
146
166
 
147
167
  def script_tag(content, env)
148
- if (nonce = rails5_nonce(env))
149
- script_tag_content = "\n<script type=\"text/javascript\" nonce=\"#{nonce}\">#{content}</script>"
150
- elsif secure_headers_nonce?
151
- nonce = ::SecureHeaders.content_security_policy_script_nonce(::Rack::Request.new(env))
152
- script_tag_content = "\n<script type=\"text/javascript\" nonce=\"#{nonce}\">#{content}</script>"
153
- else
154
- script_tag_content = "\n<script type=\"text/javascript\">#{content}</script>"
155
- end
168
+ nonce = rails5_nonce(env) || secure_headers_nonce(env)
169
+ script_tag_content = if nonce
170
+ "\n<script nonce=\"#{nonce}\">#{content}</script>"
171
+ else
172
+ "\n<script>#{content}</script>"
173
+ end
156
174
 
157
175
  html_safe_if_needed(script_tag_content)
158
176
  end
@@ -162,34 +180,46 @@ module Rollbar
162
180
  string
163
181
  end
164
182
 
165
- # Rails 5.2 Secure Content Policy
183
+ # Rails 5.2+ Secure Content Policy
166
184
  def rails5_nonce(env)
167
- # The nonce is the preferred method, however 'unsafe-inline' is also possible.
168
- # The app gets to decide, so we handle both. If the script_src key is missing,
169
- # Rails will not add the nonce to the headers, so we should not add it either.
170
- # If the 'unsafe-inline' value is present, the app should not add a nonce and
171
- # we should ignore it if they do.
172
- req = ::ActionDispatch::Request.new env
185
+ req = ::ActionDispatch::Request.new(env)
186
+
187
+ # Rails will only return a nonce if the app has set a nonce generator.
188
+ # So if we get a valid nonce here, we know we should use it.
189
+ #
190
+ # Having both 'unsafe-inline' and a nonce is a valid and preferred
191
+ # browser compatibility configuration.
192
+ #
193
+ # If the script_src key is missing, Rails will not add the nonce to the headers,
194
+ # so we detect this and will not add it in this case.
173
195
  req.respond_to?(:content_security_policy) &&
174
196
  req.content_security_policy &&
175
197
  req.content_security_policy.directives['script-src'] &&
176
- !req.content_security_policy.directives['script-src'].include?("'unsafe-inline'") &&
177
198
  req.content_security_policy_nonce
178
199
  end
179
200
 
180
201
  # Secure Headers gem
181
- def secure_headers_nonce?
182
- secure_headers.append_nonce?
202
+ def secure_headers_nonce(env)
203
+ req = ::Rack::Request.new(env)
204
+
205
+ return unless secure_headers(req).append_nonce?
206
+
207
+ ::SecureHeaders.content_security_policy_script_nonce(req)
183
208
  end
184
209
 
185
- def secure_headers
210
+ def secure_headers(req)
186
211
  return SecureHeadersFalse.new unless defined?(::SecureHeaders::Configuration)
187
212
 
188
- config = ::SecureHeaders::Configuration
213
+ # If the nonce key has been set, the app is using nonces for this request.
214
+ # If it hasn't, we shouldn't cause one to be added to script_src, so return now.
215
+ return SecureHeadersFalse.new unless secure_headers_nonce_key(req)
189
216
 
190
- secure_headers_cls = nil
217
+ config = ::SecureHeaders::Configuration
191
218
 
192
- secure_headers_cls = if !::SecureHeaders.respond_to?(:content_security_policy_script_nonce)
219
+ has_nonce = ::SecureHeaders.respond_to?(
220
+ :content_security_policy_script_nonce
221
+ )
222
+ secure_headers_cls = if !has_nonce
193
223
  SecureHeadersFalse
194
224
  elsif config.respond_to?(:get)
195
225
  SecureHeaders3To5
@@ -202,6 +232,11 @@ module Rollbar
202
232
  secure_headers_cls.new
203
233
  end
204
234
 
235
+ def secure_headers_nonce_key(req)
236
+ defined?(::SecureHeaders::NONCE_KEY) &&
237
+ req.env[::SecureHeaders::NONCE_KEY]
238
+ end
239
+
205
240
  class SecureHeadersResolver
206
241
  def append_nonce?
207
242
  csp_needs_nonce?(find_csp)
@@ -214,16 +249,12 @@ module Rollbar
214
249
  end
215
250
 
216
251
  def csp_needs_nonce?(csp)
217
- !opt_out?(csp) && !unsafe_inline?(csp)
252
+ !opt_out?(csp)
218
253
  end
219
254
 
220
255
  def opt_out?(_csp)
221
256
  raise NotImplementedError
222
257
  end
223
-
224
- def unsafe_inline?(csp)
225
- csp[:script_src].to_a.include?("'unsafe-inline'")
226
- end
227
258
  end
228
259
 
229
260
  class SecureHeadersFalse < SecureHeadersResolver
@@ -243,7 +274,8 @@ module Rollbar
243
274
  if csp.respond_to?(:opt_out?) && csp.opt_out?
244
275
  csp.opt_out?
245
276
  # secure_headers csp 3.0.x-3.4.x doesn't respond to 'opt_out?'
246
- elsif defined?(::SecureHeaders::OPT_OUT) && ::SecureHeaders::OPT_OUT.is_a?(Symbol)
277
+ elsif defined?(::SecureHeaders::OPT_OUT) &&
278
+ ::SecureHeaders::OPT_OUT.is_a?(Symbol)
247
279
  csp == ::SecureHeaders::OPT_OUT
248
280
  end
249
281
  end
@@ -14,8 +14,8 @@ module Rollbar
14
14
  Rollbar.scoped(fetch_scope(env)) do
15
15
  begin
16
16
  call_without_rollbar(env)
17
- rescue ::Exception => exception
18
- report_exception_to_rollbar(env, exception)
17
+ rescue ::Exception => e # rubocop:disable Lint/RescueException
18
+ report_exception_to_rollbar(env, e)
19
19
  raise
20
20
  end
21
21
  end
@@ -26,7 +26,7 @@ module Rollbar
26
26
  :request => proc { extract_request_data_from_rack(env) },
27
27
  :person => person_data_proc(env)
28
28
  }
29
- rescue Exception => e
29
+ rescue Exception => e # rubocop:disable Lint/RescueException
30
30
  report_exception_to_rollbar(env, e)
31
31
  raise
32
32
  end
@@ -6,9 +6,9 @@ module Rollbar
6
6
 
7
7
  def env_for_with_rollbar(path, env)
8
8
  env_for_without_rollbar(path, env)
9
- rescue Exception => exception
10
- report_exception_to_rollbar(env, exception)
11
- raise exception
9
+ rescue Exception => e # rubocop:disable Lint/RescueException
10
+ report_exception_to_rollbar(env, e)
11
+ raise e
12
12
  end
13
13
 
14
14
  def self.included(base)
@@ -21,7 +21,7 @@ module Rollbar
21
21
  response = @app.call(env)
22
22
  report_exception_to_rollbar(env, framework_error(env)) if framework_error(env)
23
23
  response
24
- rescue Exception => e
24
+ rescue Exception => e # rubocop:disable Lint/RescueException
25
25
  report_exception_to_rollbar(env, e)
26
26
  raise
27
27
  ensure
@@ -35,7 +35,7 @@ module Rollbar
35
35
  :request => proc { extract_request_data_from_rack(env) },
36
36
  :person => person_data_proc(env)
37
37
  }
38
- rescue Exception => e
38
+ rescue Exception => e # rubocop:disable Lint/RescueException
39
39
  report_exception_to_rollbar(env, e)
40
40
  raise
41
41
  end
@@ -44,8 +44,8 @@ module Rollbar
44
44
  proc { extract_person_data_from_controller(env) }
45
45
  end
46
46
 
47
- def framework_error(_env)
48
- nil
47
+ def framework_error(env)
48
+ env['rack.exception']
49
49
  end
50
50
  end
51
51
  end
@@ -29,8 +29,8 @@ module Rollbar
29
29
  end
30
30
 
31
31
  response
32
- rescue Exception => exception
33
- report_exception_to_rollbar(env, exception)
32
+ rescue Exception => e # rubocop:disable Lint/RescueException
33
+ report_exception_to_rollbar(env, e)
34
34
  raise
35
35
  ensure
36
36
  Rollbar.notifier.disable_locals
@@ -63,7 +63,9 @@ module Rollbar
63
63
 
64
64
  def person_data_proc(env)
65
65
  block = proc { extract_person_data_from_controller(env) }
66
- return block unless defined?(ActiveRecord::Base) && ActiveRecord::Base.connected?
66
+ unless defined?(ActiveRecord::Base) && ActiveRecord::Base.connected?
67
+ return block
68
+ end
67
69
 
68
70
  proc do
69
71
  begin
@@ -75,11 +77,12 @@ module Rollbar
75
77
  end
76
78
 
77
79
  def context(request_data)
78
- return unless request_data[:params]
79
-
80
80
  route_params = request_data[:params]
81
+
81
82
  # make sure route is a hash built by RequestDataExtractor
82
- return route_params[:controller].to_s + '#' + route_params[:action].to_s if route_params.is_a?(Hash) && !route_params.empty?
83
+ return unless route_params.is_a?(Hash) && !route_params.empty?
84
+
85
+ "#{route_params[:controller]}##{route_params[:action]}"
83
86
  end
84
87
  end
85
88
  end
@@ -20,20 +20,24 @@ module Rollbar
20
20
 
21
21
  def call_with_rollbar(env)
22
22
  call_without_rollbar(env)
23
- rescue ActionController::RoutingError => exception
23
+ rescue ActionController::RoutingError => e
24
24
  # won't reach here if show_detailed_exceptions is true
25
25
  scope = extract_scope_from(env)
26
26
 
27
27
  Rollbar.scoped(scope) do
28
- report_exception_to_rollbar(env, exception)
28
+ report_exception_to_rollbar(env, e)
29
29
  end
30
30
 
31
- raise exception
31
+ raise e
32
32
  end
33
33
 
34
34
  def extract_scope_from(env)
35
35
  scope = env['rollbar.scope']
36
- Rollbar.log_warn('[Rollbar] rollbar.scope key has been removed from Rack env.') unless scope
36
+ unless scope
37
+ Rollbar.log_warn(
38
+ '[Rollbar] rollbar.scope key has been removed from Rack env.'
39
+ )
40
+ end
37
41
 
38
42
  scope || {}
39
43
  end
@@ -36,7 +36,8 @@ module Rollbar
36
36
  def trace_point
37
37
  return unless defined?(TracePoint)
38
38
 
39
- @trace_point ||= TracePoint.new(:call, :return, :b_call, :b_return, :c_call, :c_return, :raise) do |tp|
39
+ @trace_point ||= TracePoint.new(:call, :return, :b_call, :b_return, :c_call,
40
+ :c_return, :raise) do |tp|
40
41
  case tp.event
41
42
  when :call, :b_call, :c_call, :class
42
43
  frames.push frame(tp)
@@ -44,7 +45,8 @@ module Rollbar
44
45
  frames.pop
45
46
  when :raise
46
47
  unless detect_reraise(tp) # ignore reraised exceptions
47
- @exception_frames = @frames.dup # may be possible to optimize better than #dup
48
+ # may be possible to optimize better than #dup
49
+ @exception_frames = @frames.dup
48
50
  @exception_signature = exception_signature(tp)
49
51
  end
50
52
  end
@@ -53,13 +55,21 @@ module Rollbar
53
55
 
54
56
  def frame(trace)
55
57
  {
56
- :binding => trace.binding,
58
+ :binding => binding(trace),
57
59
  :defined_class => trace.defined_class,
58
60
  :method_id => trace.method_id,
59
61
  :path => trace.path,
60
62
  :lineno => trace.lineno
61
63
  }
62
64
  end
65
+
66
+ def binding(trace)
67
+ trace.binding
68
+ rescue StandardError
69
+ # Ruby internals will raise if we're on a Fiber,
70
+ # since bindings aren't valid on Fibers.
71
+ nil
72
+ end
63
73
  end
64
74
  end
65
75
  end