rollbar 2.19.1 → 2.27.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +5 -5
  2. data/.github/pull_request_template.md +25 -0
  3. data/.rubocop.yml +168 -0
  4. data/.travis.yml +63 -34
  5. data/Appraisals +10 -10
  6. data/Gemfile +35 -14
  7. data/README.md +5 -2
  8. data/Rakefile +0 -0
  9. data/data/rollbar.snippet.js +1 -1
  10. data/docs/configuration.md +17 -0
  11. data/gemfiles/rails30.gemfile +10 -10
  12. data/gemfiles/rails31.gemfile +10 -9
  13. data/gemfiles/rails32.gemfile +10 -9
  14. data/gemfiles/rails40.gemfile +10 -9
  15. data/gemfiles/rails41.gemfile +10 -9
  16. data/gemfiles/rails42.gemfile +12 -9
  17. data/gemfiles/rails50.gemfile +21 -14
  18. data/gemfiles/rails51.gemfile +21 -14
  19. data/gemfiles/rails52.gemfile +15 -12
  20. data/gemfiles/rails60.gemfile +67 -0
  21. data/lib/generators/rollbar/rollbar_generator.rb +1 -1
  22. data/lib/rails/rollbar_runner.rb +4 -2
  23. data/lib/rollbar/capistrano.rb +1 -1
  24. data/lib/rollbar/capistrano3.rb +6 -3
  25. data/lib/rollbar/capistrano_tasks.rb +29 -21
  26. data/lib/rollbar/configuration.rb +86 -16
  27. data/lib/rollbar/delay/girl_friday.rb +4 -8
  28. data/lib/rollbar/delay/resque.rb +3 -6
  29. data/lib/rollbar/delay/sidekiq.rb +4 -10
  30. data/lib/rollbar/delay/sucker_punch.rb +16 -19
  31. data/lib/rollbar/delay/thread.rb +16 -2
  32. data/lib/rollbar/deploy.rb +52 -29
  33. data/lib/rollbar/encoding/encoder.rb +17 -10
  34. data/lib/rollbar/exception_reporter.rb +19 -5
  35. data/lib/rollbar/item/backtrace.rb +13 -3
  36. data/lib/rollbar/item/frame.rb +9 -1
  37. data/lib/rollbar/item/locals.rb +100 -0
  38. data/lib/rollbar/item.rb +56 -17
  39. data/lib/rollbar/json.rb +6 -51
  40. data/lib/rollbar/language_support.rb +4 -20
  41. data/lib/rollbar/lazy_store.rb +5 -5
  42. data/lib/rollbar/logger.rb +1 -0
  43. data/lib/rollbar/logger_proxy.rb +6 -2
  44. data/lib/rollbar/middleware/js.rb +28 -18
  45. data/lib/rollbar/middleware/rack.rb +4 -1
  46. data/lib/rollbar/middleware/rails/rollbar.rb +10 -1
  47. data/lib/rollbar/notifier/trace_with_bindings.rb +65 -0
  48. data/lib/rollbar/notifier.rb +225 -89
  49. data/lib/rollbar/plugin.rb +54 -6
  50. data/lib/rollbar/plugins/active_job.rb +6 -2
  51. data/lib/rollbar/plugins/basic_socket.rb +21 -6
  52. data/lib/rollbar/plugins/delayed_job/job_data.rb +3 -3
  53. data/lib/rollbar/plugins/delayed_job/plugin.rb +13 -3
  54. data/lib/rollbar/plugins/error_context.rb +11 -0
  55. data/lib/rollbar/plugins/goalie.rb +11 -3
  56. data/lib/rollbar/plugins/rails/controller_methods.rb +15 -3
  57. data/lib/rollbar/plugins/rake.rb +2 -2
  58. data/lib/rollbar/plugins/sidekiq/plugin.rb +5 -4
  59. data/lib/rollbar/plugins.rb +7 -1
  60. data/lib/rollbar/rake_tasks.rb +4 -148
  61. data/lib/rollbar/request_data_extractor.rb +31 -21
  62. data/lib/rollbar/rollbar_test.rb +36 -0
  63. data/lib/rollbar/scrubbers/params.rb +19 -18
  64. data/lib/rollbar/scrubbers/url.rb +18 -9
  65. data/lib/rollbar/scrubbers.rb +3 -3
  66. data/lib/rollbar/truncation/frames_strategy.rb +1 -1
  67. data/lib/rollbar/truncation/min_body_strategy.rb +2 -3
  68. data/lib/rollbar/truncation/mixin.rb +1 -1
  69. data/lib/rollbar/truncation/remove_any_key_strategy.rb +123 -0
  70. data/lib/rollbar/truncation/remove_extra_strategy.rb +35 -0
  71. data/lib/rollbar/truncation/remove_request_strategy.rb +21 -0
  72. data/lib/rollbar/truncation/strings_strategy.rb +6 -5
  73. data/lib/rollbar/truncation.rb +9 -2
  74. data/lib/rollbar/util/hash.rb +15 -0
  75. data/lib/rollbar/util/ip_anonymizer.rb +8 -7
  76. data/lib/rollbar/util/ip_obfuscator.rb +1 -1
  77. data/lib/rollbar/util.rb +6 -2
  78. data/lib/rollbar/version.rb +1 -1
  79. data/lib/rollbar.rb +2 -3
  80. data/lib/tasks/benchmark.rake +103 -0
  81. data/rollbar.gemspec +13 -5
  82. data/spec/support/rollbar_api.rb +67 -0
  83. metadata +21 -23
  84. data/gemfiles/ruby_1_8_and_1_9_2.gemfile +0 -49
  85. data/lib/rollbar/json/default.rb +0 -11
  86. data/lib/rollbar/json/oj.rb +0 -16
@@ -1,9 +1,8 @@
1
1
  module Rollbar
2
2
  module Encoding
3
3
  class Encoder
4
- ALL_ENCODINGS = [::Encoding::UTF_8, ::Encoding::ISO_8859_1, ::Encoding::ASCII_8BIT, ::Encoding::US_ASCII]
5
- ASCII_ENCODINGS = [::Encoding::US_ASCII, ::Encoding::ASCII_8BIT, ::Encoding::ISO_8859_1]
6
- ENCODING_OPTIONS = { :invalid => :replace, :undef => :replace, :replace => '' }
4
+ ALL_ENCODINGS = [::Encoding::UTF_8, ::Encoding::ISO_8859_1, ::Encoding::ASCII_8BIT, ::Encoding::US_ASCII].freeze
5
+ ASCII_ENCODINGS = [::Encoding::US_ASCII, ::Encoding::ASCII_8BIT, ::Encoding::ISO_8859_1].freeze
7
6
  UTF8 = 'UTF-8'.freeze
8
7
  BINARY = 'binary'.freeze
9
8
 
@@ -18,13 +17,22 @@ module Rollbar
18
17
  encoding = value.encoding
19
18
 
20
19
  # This will be most of cases so avoid force anything for them
21
- if encoding == ::Encoding::UTF_8 && value.valid_encoding?
22
- encoded_value = value
23
- else
24
- encoded_value = force_encoding(value).encode(*encoding_args(value))
25
- end
20
+ encoded_value = if encoding == ::Encoding::UTF_8 && value.valid_encoding?
21
+ value
22
+ else
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
+ )
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
@@ -45,7 +53,7 @@ module Rollbar
45
53
  # Seems #codepoints is faster than #valid_encoding?
46
54
  value.force_encoding(encoding).encode(::Encoding::UTF_8).codepoints
47
55
  true
48
- rescue
56
+ rescue StandardError
49
57
  false
50
58
  end
51
59
  end
@@ -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
@@ -1,10 +1,11 @@
1
1
  module Rollbar
2
- module ExceptionReporter
2
+ module ExceptionReporter # :nodoc:
3
3
  def report_exception_to_rollbar(env, exception)
4
- exception_message = exception.respond_to?(:message) ? exception.message : 'No Exception Message'
5
- Rollbar.log_debug "[Rollbar] Reporting exception: #{exception_message}"
4
+ return unless capture_uncaught?
5
+
6
+ log_exception_message(exception)
6
7
 
7
- exception_data = Rollbar.log(Rollbar.configuration.uncaught_exception_level, exception, :use_exception_level_filters => true)
8
+ exception_data = exception_data(exception)
8
9
 
9
10
  if exception_data.is_a?(Hash)
10
11
  env['rollbar.exception_uuid'] = exception_data[:uuid]
@@ -14,8 +15,21 @@ module Rollbar
14
15
  elsif exception_data == 'ignored'
15
16
  Rollbar.log_debug '[Rollbar] Exception not reported because it was ignored'
16
17
  end
17
- rescue => e
18
+ rescue StandardError => e
18
19
  Rollbar.log_warning "[Rollbar] Exception while reporting exception to Rollbar: #{e.message}"
19
20
  end
21
+
22
+ def capture_uncaught?
23
+ Rollbar.configuration.capture_uncaught != false
24
+ end
25
+
26
+ def log_exception_message(exception)
27
+ exception_message = exception.respond_to?(:message) ? exception.message : 'No Exception Message'
28
+ Rollbar.log_debug "[Rollbar] Reporting exception: #{exception_message}"
29
+ end
30
+
31
+ def exception_data(exception)
32
+ Rollbar.log(Rollbar.configuration.uncaught_exception_level, exception, :use_exception_level_filters => true)
33
+ end
20
34
  end
21
35
  end
@@ -32,7 +32,7 @@ module Rollbar
32
32
  end
33
33
  end
34
34
 
35
- alias_method :build, :to_h
35
+ alias build to_h
36
36
 
37
37
  def get_file_lines(filename)
38
38
  files[filename] ||= read_file(filename)
@@ -44,7 +44,7 @@ module Rollbar
44
44
  return unless File.exist?(filename)
45
45
 
46
46
  File.read(filename).split("\n")
47
- rescue
47
+ rescue StandardError
48
48
  nil
49
49
  end
50
50
 
@@ -74,10 +74,20 @@ module Rollbar
74
74
  end
75
75
 
76
76
  def map_frames(current_exception)
77
- exception_backtrace(current_exception).reverse.map do |frame|
77
+ frames = cleaned_backtrace(current_exception).map do |frame|
78
78
  Rollbar::Item::Frame.new(self, frame,
79
79
  :configuration => configuration).to_h
80
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:
@@ -1,5 +1,6 @@
1
1
  # We want to use Gem.path
2
2
  require 'rubygems'
3
+ require 'rollbar/item/locals'
3
4
 
4
5
  module Rollbar
5
6
  class Item
@@ -47,7 +48,8 @@ module Rollbar
47
48
 
48
49
  {
49
50
  :code => code_data(file_lines, lineno),
50
- :context => context_data(file_lines, lineno)
51
+ :context => context_data(file_lines, lineno),
52
+ :locals => locals_data(filename, lineno)
51
53
  }
52
54
  end
53
55
 
@@ -94,6 +96,12 @@ module Rollbar
94
96
  }
95
97
  end
96
98
 
99
+ def locals_data(filename, lineno)
100
+ return unless configuration.locals[:enabled]
101
+
102
+ ::Rollbar::Item::Locals.locals_for_location(filename, lineno)
103
+ end
104
+
97
105
  def post_data(file_lines, lineno)
98
106
  from_line = lineno
99
107
  number_of_lines = [from_line + MAX_CONTEXT_LENGTH, file_lines.size].min - from_line
@@ -0,0 +1,100 @@
1
+ require 'rollbar/notifier'
2
+ require 'rollbar/scrubbers/params'
3
+ require 'rollbar/util'
4
+
5
+ module Rollbar
6
+ class Item
7
+ class Locals # :nodoc:
8
+ class << self
9
+ def exception_frames
10
+ Rollbar.notifier.exception_bindings
11
+ end
12
+
13
+ def locals_for_location(filename, lineno)
14
+ if (frame = frame_for_location(filename, lineno))
15
+ scrub(locals_for(frame[:binding]))
16
+ else
17
+ {}
18
+ end
19
+ end
20
+
21
+ def frame_for_location(filename, lineno)
22
+ while (frame = exception_frames.pop)
23
+ return nil unless frame
24
+ return frame if matching_frame?(frame, filename, lineno)
25
+ end
26
+ nil
27
+ end
28
+
29
+ private
30
+
31
+ def matching_frame?(frame, filename, lineno)
32
+ frame[:path] == filename && frame[:lineno].to_i <= lineno.to_i
33
+ end
34
+
35
+ def locals_for(frame)
36
+ {}.tap do |hash|
37
+ frame.local_variables.map do |var|
38
+ hash[var] = prepare_value(frame.local_variable_get(var))
39
+ end
40
+ end
41
+ end
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
+ #
61
+ def prepare_value(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
88
+ end
89
+
90
+ def scrub(hash)
91
+ Rollbar::Scrubbers::Params.call(
92
+ :params => hash,
93
+ :config => Rollbar.configuration.scrub_fields,
94
+ :whitelist => Rollbar.configuration.scrub_whitelist
95
+ )
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
data/lib/rollbar/item.rb CHANGED
@@ -12,6 +12,7 @@ require 'rollbar/util'
12
12
  require 'rollbar/encoding'
13
13
  require 'rollbar/truncation'
14
14
  require 'rollbar/json'
15
+ require 'rollbar/scrubbers/params'
15
16
 
16
17
  module Rollbar
17
18
  # This class represents the payload to be sent to the API.
@@ -64,7 +65,6 @@ module Rollbar
64
65
  def build
65
66
  data = build_data
66
67
  self.payload = {
67
- 'access_token' => configuration.access_token,
68
68
  'data' => data
69
69
  }
70
70
 
@@ -83,7 +83,8 @@ module Rollbar
83
83
  :server => server_data,
84
84
  :notifier => {
85
85
  :name => 'rollbar-gem',
86
- :version => VERSION
86
+ :version => VERSION,
87
+ :configured_options => configured_options
87
88
  },
88
89
  :body => build_body
89
90
  }
@@ -101,29 +102,61 @@ module Rollbar
101
102
  data
102
103
  end
103
104
 
105
+ def configured_options
106
+ if Gem.loaded_specs['activesupport'] && Gem.loaded_specs['activesupport'].version < Gem::Version.new('4.1')
107
+ # There are too many types that crash ActiveSupport JSON serialization, and not worth
108
+ # the risk just to send this diagnostic object. In versions < 4.1, ActiveSupport hooks
109
+ # Ruby's JSON.generate so deeply there's no workaround.
110
+ 'not serialized in ActiveSupport < 4.1'
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'
116
+ else
117
+ scrub(configuration.configured_options.configured)
118
+ end
119
+ end
120
+
104
121
  def dump
105
122
  # Ensure all keys are strings since we can receive the payload inline or
106
123
  # from an async handler job, which can be serialized.
107
124
  stringified_payload = Util::Hash.deep_stringify_keys(payload)
108
- result = Truncation.truncate(stringified_payload)
125
+ attempts = []
126
+ result = Truncation.truncate(stringified_payload, attempts)
109
127
 
110
128
  return result unless Truncation.truncate?(result)
111
129
 
112
- handle_too_large_payload(stringified_payload, result)
130
+ handle_too_large_payload(stringified_payload, result, attempts)
113
131
 
114
132
  nil
115
133
  end
116
134
 
117
- def handle_too_large_payload(stringified_payload, final_payload)
118
- original_size = Rollbar::JSON.dump(stringified_payload).bytesize
119
- final_size = final_payload.bytesize
135
+ def handle_too_large_payload(stringified_payload, final_payload, attempts)
120
136
  uuid = stringified_payload['data']['uuid']
121
137
  host = stringified_payload['data'].fetch('server', {})['host']
122
138
 
123
- notifier.send_failsafe("Could not send payload due to it being too large after truncating attempts. Original size: #{original_size} Final size: #{final_size}", nil, uuid, host)
139
+ original_error = {
140
+ :message => message,
141
+ :exception => exception,
142
+ :configuration => configuration,
143
+ :uuid => uuid,
144
+ :host => host
145
+ }
146
+
147
+ notifier.send_failsafe(
148
+ too_large_payload_string(attempts),
149
+ nil,
150
+ original_error
151
+ )
124
152
  logger.error("[Rollbar] Payload too large to be sent for UUID #{uuid}: #{Rollbar::JSON.dump(payload)}")
125
153
  end
126
154
 
155
+ def too_large_payload_string(attempts)
156
+ 'Could not send payload due to it being too large after truncating attempts. ' \
157
+ "Original size: #{attempts.first} Attempts: #{attempts.join(', ')} Final size: #{attempts.last}"
158
+ end
159
+
127
160
  def ignored?
128
161
  data = payload['data']
129
162
 
@@ -156,13 +189,19 @@ module Rollbar
156
189
  end
157
190
 
158
191
  def build_extra
192
+ merged_extra = Util.deep_merge(scrub(extra), scrub(error_context))
193
+
159
194
  if custom_data_method? && !Rollbar::Util.method_in_stack(:custom_data, __FILE__)
160
- Util.deep_merge(scrub(custom_data), scrub(extra) || {})
195
+ Util.deep_merge(scrub(custom_data), merged_extra)
161
196
  else
162
- scrub(extra)
197
+ merged_extra.empty? ? nil : merged_extra # avoid putting an empty {} in the payload.
163
198
  end
164
199
  end
165
200
 
201
+ def error_context
202
+ exception.respond_to?(:rollbar_context) && exception.rollbar_context
203
+ end
204
+
166
205
  def scrub(data)
167
206
  return data unless data.is_a? Hash
168
207
 
@@ -179,14 +218,14 @@ module Rollbar
179
218
  end
180
219
 
181
220
  def custom_data
182
- if configuration.custom_data_method.arity == 3
183
- data = configuration.custom_data_method.call(message, exception, context)
184
- else
185
- data = configuration.custom_data_method.call
186
- end
221
+ data = if configuration.custom_data_method.arity == 3
222
+ configuration.custom_data_method.call(message, exception, context)
223
+ else
224
+ configuration.custom_data_method.call
225
+ end
187
226
 
188
227
  Rollbar::Util.deep_copy(data)
189
- rescue => e
228
+ rescue StandardError => e
190
229
  return {} if configuration.safely?
191
230
 
192
231
  report_custom_data_error(e)
@@ -231,7 +270,7 @@ module Rollbar
231
270
  handlers.each do |handler|
232
271
  begin
233
272
  handler.call(transform_options)
234
- rescue => e
273
+ rescue StandardError => e
235
274
  logger.error("[Rollbar] Error calling the `transform` hook: #{e}")
236
275
 
237
276
  break
data/lib/rollbar/json.rb CHANGED
@@ -1,65 +1,20 @@
1
- require 'multi_json'
2
- require 'rollbar/json/oj'
3
- require 'rollbar/json/default'
4
1
  require 'rollbar/language_support'
5
-
6
- begin
7
- require 'oj'
8
- rescue LoadError
9
- end
2
+ require 'json'
10
3
 
11
4
  module Rollbar
12
- module JSON
5
+ module JSON # :nodoc:
13
6
  extend self
14
7
 
15
8
  attr_writer :options_module
16
9
 
17
10
  def dump(object)
18
- with_adapter { MultiJson.dump(object, adapter_options) }
19
- end
20
-
21
- def load(string)
22
- with_adapter { MultiJson.load(string, adapter_options) }
23
- end
24
-
25
- def with_adapter(&block)
26
- MultiJson.with_adapter(detect_multi_json_adapter, &block)
27
- end
28
-
29
- def detect_multi_json_adapter
30
- options = {}
31
- options[:adapter] = :oj if defined?(::Oj)
32
-
33
- MultiJson.current_adapter(options)
34
- end
35
-
36
- def adapter_options
37
- options_module.options
38
- end
39
-
40
- def options_module
41
- @options_module ||= find_options_module
42
- end
43
-
44
- def find_options_module
45
- module_name = multi_json_adapter_module_name
46
-
47
- if LanguageSupport.const_defined?(Rollbar::JSON, module_name, false)
48
- LanguageSupport.const_get(Rollbar::JSON, module_name, false)
49
- else
50
- Default
11
+ Rollbar.plugins.get('basic_socket').load_scoped!(true) do
12
+ ::JSON.generate(object)
51
13
  end
52
14
  end
53
15
 
54
- # MultiJson adapters have this name structure:
55
- # "MultiJson::Adapters::{AdapterModule}"
56
- #
57
- # Ex: MultiJson::Adapters::Oj
58
- # Ex: MultiJson::Adapters::JsonGem
59
- #
60
- # In this method we just get the last module name.
61
- def multi_json_adapter_module_name
62
- detect_multi_json_adapter.name[/^MultiJson::Adapters::(.*)$/, 1]
16
+ def load(string)
17
+ ::JSON.parse(string)
63
18
  end
64
19
  end
65
20
  end
@@ -1,29 +1,13 @@
1
1
  module Rollbar
2
2
  module LanguageSupport
3
- extend self
3
+ module_function
4
4
 
5
5
  def const_defined?(mod, target, inherit = true)
6
- if ruby_18?
7
- mod.const_defined?(target)
8
- else
9
- mod.const_defined?(target, inherit)
10
- end
6
+ mod.const_defined?(target, inherit)
11
7
  end
12
8
 
13
9
  def const_get(mod, target, inherit = true)
14
- if ruby_18?
15
- mod.const_get(target)
16
- else
17
- mod.const_get(target, inherit)
18
- end
19
- end
20
-
21
- def can_scrub_url?
22
- !version?('1.8')
23
- end
24
-
25
- def ruby_18?
26
- version?('1.8')
10
+ mod.const_get(target, inherit)
27
11
  end
28
12
 
29
13
  def ruby_19?
@@ -37,7 +21,7 @@ module Rollbar
37
21
  end
38
22
 
39
23
  def timeout_exceptions
40
- return [] if ruby_18? || ruby_19?
24
+ return [] if ruby_19?
41
25
 
42
26
  [Net::ReadTimeout, Net::OpenTimeout]
43
27
  end
@@ -21,11 +21,11 @@ module Rollbar
21
21
  end
22
22
 
23
23
  def ==(other)
24
- if other.is_a?(self.class)
25
- raw == other.raw
26
- else
27
- raw == other
28
- end
24
+ raw == if other.is_a?(self.class)
25
+ other.raw
26
+ else
27
+ other
28
+ end
29
29
  end
30
30
 
31
31
  # With this version of clone we ensure that the loaded_data is empty
@@ -67,6 +67,7 @@ module Rollbar
67
67
 
68
68
  def blank?(message)
69
69
  return message.blank? if message.respond_to?(:blank?)
70
+
70
71
  message.respond_to?(:empty?) ? !!message.empty? : !message
71
72
  end
72
73
 
@@ -26,7 +26,7 @@ module Rollbar
26
26
  return unless Rollbar.configuration.enabled && acceptable_levels.include?(level.to_sym)
27
27
 
28
28
  @object.send(level, message)
29
- rescue
29
+ rescue StandardError
30
30
  puts "[Rollbar] Error logging #{level}:"
31
31
  puts "[Rollbar] #{message}"
32
32
  end
@@ -36,7 +36,11 @@ module Rollbar
36
36
  def acceptable_levels
37
37
  @acceptable_levels ||= begin
38
38
  levels = [:debug, :info, :warn, :error]
39
- levels[levels.find_index(Rollbar.configuration.logger_level)..-1]
39
+ if Rollbar.configuration.logger_level
40
+ levels[levels.find_index(Rollbar.configuration.logger_level)..-1]
41
+ else
42
+ []
43
+ end
40
44
  end
41
45
  end
42
46
  end
@@ -13,7 +13,7 @@ module Rollbar
13
13
  attr_reader :app
14
14
  attr_reader :config
15
15
 
16
- JS_IS_INJECTED_KEY = 'rollbar.js_is_injected'
16
+ JS_IS_INJECTED_KEY = 'rollbar.js_is_injected'.freeze
17
17
  SNIPPET = File.read(File.expand_path('../../../../data/rollbar.snippet.js', __FILE__))
18
18
 
19
19
  def initialize(app, config)
@@ -29,7 +29,7 @@ module Rollbar
29
29
 
30
30
  response_string = add_js(env, app_result[2])
31
31
  build_response(env, app_result, response_string)
32
- rescue => e
32
+ rescue StandardError => e
33
33
  Rollbar.log_error("[Rollbar] Rollbar.js could not be added because #{e} exception")
34
34
 
35
35
  app_result
@@ -71,7 +71,7 @@ module Rollbar
71
71
  return nil unless insert_after_idx
72
72
 
73
73
  build_body_with_js(env, body, insert_after_idx)
74
- rescue => e
74
+ rescue StandardError => e
75
75
  Rollbar.log_error("[Rollbar] Rollbar.js could not be added because #{e} exception")
76
76
  nil
77
77
  end
@@ -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
- response.finish
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)
@@ -189,17 +199,17 @@ module Rollbar
189
199
 
190
200
  secure_headers_cls = nil
191
201
 
192
- if !::SecureHeaders::respond_to?(:content_security_policy_script_nonce)
193
- secure_headers_cls = SecureHeadersFalse
194
- elsif config.respond_to?(:get)
195
- secure_headers_cls = SecureHeaders3To5
196
- elsif config.dup.respond_to?(:csp)
197
- secure_headers_cls = SecureHeaders6
198
- else
199
- secure_headers_cls = SecureHeadersFalse
200
- end
201
-
202
- secure_headers_cls.new
202
+ secure_headers_cls = if !::SecureHeaders.respond_to?(:content_security_policy_script_nonce)
203
+ SecureHeadersFalse
204
+ elsif config.respond_to?(:get)
205
+ SecureHeaders3To5
206
+ elsif config.dup.respond_to?(:csp)
207
+ SecureHeaders6
208
+ else
209
+ SecureHeadersFalse
210
+ end
211
+
212
+ secure_headers_cls.new
203
213
  end
204
214
 
205
215
  class SecureHeadersResolver
@@ -217,7 +227,7 @@ module Rollbar
217
227
  !opt_out?(csp) && !unsafe_inline?(csp)
218
228
  end
219
229
 
220
- def opt_out?(csp)
230
+ def opt_out?(_csp)
221
231
  raise NotImplementedError
222
232
  end
223
233