rollbar 2.8.3 → 3.6.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 (238) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +18 -0
  3. data/.github/pull_request_template.md +34 -0
  4. data/.github/workflows/ci.yml +67 -0
  5. data/.gitignore +3 -1
  6. data/.rubocop.yml +206 -7
  7. data/Appraisals +10 -10
  8. data/CHANGELOG.md +257 -3
  9. data/Gemfile +74 -13
  10. data/README.md +38 -833
  11. data/Rakefile +0 -0
  12. data/THANKS.md +1 -0
  13. data/data/rollbar.snippet.js +1 -1
  14. data/docs/configuration.md +64 -3
  15. data/docs/plugins.md +46 -0
  16. data/gemfiles/rails50.gemfile +56 -0
  17. data/gemfiles/rails51.gemfile +57 -0
  18. data/gemfiles/rails52.gemfile +56 -0
  19. data/gemfiles/rails60.gemfile +52 -0
  20. data/gemfiles/rails61.gemfile +52 -0
  21. data/gemfiles/rails70.gemfile +52 -0
  22. data/gemfiles/rails71.gemfile +52 -0
  23. data/lib/generators/rollbar/rollbar_generator.rb +24 -20
  24. data/lib/generators/rollbar/templates/{initializer.rb → initializer.erb} +19 -5
  25. data/lib/rails/rollbar_runner.rb +26 -22
  26. data/lib/rollbar/capistrano.rb +78 -38
  27. data/lib/rollbar/capistrano3.rb +62 -1
  28. data/lib/rollbar/capistrano_tasks.rb +166 -0
  29. data/lib/rollbar/configuration.rb +291 -71
  30. data/lib/rollbar/delay/active_job.rb +17 -0
  31. data/lib/rollbar/delay/delayed_job.rb +23 -0
  32. data/lib/rollbar/delay/girl_friday.rb +4 -9
  33. data/lib/rollbar/delay/resque.rb +3 -6
  34. data/lib/rollbar/delay/shoryuken.rb +36 -0
  35. data/lib/rollbar/delay/sidekiq.rb +6 -8
  36. data/lib/rollbar/delay/sucker_punch.rb +17 -22
  37. data/lib/rollbar/delay/thread.rb +74 -3
  38. data/lib/rollbar/deploy.rb +91 -0
  39. data/lib/rollbar/encoding/encoder.rb +22 -11
  40. data/lib/rollbar/encoding.rb +2 -7
  41. data/lib/rollbar/exception_reporter.rb +36 -12
  42. data/lib/rollbar/item/backtrace.rb +118 -0
  43. data/lib/rollbar/item/frame.rb +121 -0
  44. data/lib/rollbar/item/locals.rb +103 -0
  45. data/lib/rollbar/item.rb +314 -0
  46. data/lib/rollbar/js.rb +0 -28
  47. data/lib/rollbar/json.rb +7 -55
  48. data/lib/rollbar/language_support.rb +7 -19
  49. data/lib/rollbar/lazy_store.rb +8 -12
  50. data/lib/rollbar/logger.rb +71 -0
  51. data/lib/rollbar/logger_proxy.rb +18 -1
  52. data/lib/rollbar/middleware/js/json_value.rb +36 -0
  53. data/lib/rollbar/middleware/js.rb +297 -0
  54. data/lib/rollbar/middleware/rack/builder.rb +4 -4
  55. data/lib/rollbar/middleware/rack/test_session.rb +4 -4
  56. data/lib/rollbar/middleware/rack.rb +52 -0
  57. data/lib/rollbar/middleware/rails/rollbar.rb +19 -7
  58. data/lib/rollbar/middleware/rails/show_exceptions.rb +21 -9
  59. data/lib/rollbar/middleware/sinatra.rb +2 -40
  60. data/lib/rollbar/notifier/trace_with_bindings.rb +75 -0
  61. data/lib/rollbar/notifier.rb +913 -0
  62. data/lib/rollbar/plugin.rb +126 -0
  63. data/lib/rollbar/plugins/active_job.rb +54 -0
  64. data/lib/rollbar/plugins/basic_socket.rb +31 -0
  65. data/lib/rollbar/plugins/delayed_job/job_data.rb +50 -0
  66. data/lib/rollbar/plugins/delayed_job/plugin.rb +88 -0
  67. data/lib/rollbar/plugins/delayed_job.rb +12 -0
  68. data/lib/rollbar/plugins/error_context.rb +11 -0
  69. data/lib/rollbar/plugins/goalie.rb +65 -0
  70. data/lib/rollbar/plugins/rack.rb +18 -0
  71. data/lib/rollbar/plugins/rails/controller_methods.rb +56 -0
  72. data/lib/rollbar/plugins/rails/error_subscriber.rb +12 -0
  73. data/lib/rollbar/plugins/rails/railtie30.rb +18 -0
  74. data/lib/rollbar/plugins/rails/railtie32.rb +18 -0
  75. data/lib/rollbar/plugins/rails/railtie_mixin.rb +37 -0
  76. data/lib/rollbar/plugins/rails.rb +89 -0
  77. data/lib/rollbar/plugins/rake.rb +73 -0
  78. data/lib/rollbar/plugins/resque/failure.rb +39 -0
  79. data/lib/rollbar/plugins/resque.rb +11 -0
  80. data/lib/rollbar/plugins/sidekiq/plugin.rb +77 -0
  81. data/lib/rollbar/plugins/sidekiq.rb +37 -0
  82. data/lib/rollbar/plugins/thread.rb +14 -0
  83. data/lib/rollbar/plugins/validations.rb +45 -0
  84. data/lib/rollbar/plugins.rb +47 -0
  85. data/lib/rollbar/rails.rb +0 -1
  86. data/lib/rollbar/rake_tasks.rb +4 -66
  87. data/lib/rollbar/request_data_extractor.rb +157 -117
  88. data/lib/rollbar/rollbar_test.rb +38 -0
  89. data/lib/rollbar/scrubbers/params.rb +133 -0
  90. data/lib/rollbar/scrubbers/url.rb +90 -35
  91. data/lib/rollbar/scrubbers.rb +13 -0
  92. data/lib/rollbar/truncation/frames_strategy.rb +2 -1
  93. data/lib/rollbar/truncation/min_body_strategy.rb +3 -4
  94. data/lib/rollbar/truncation/mixin.rb +1 -1
  95. data/lib/rollbar/truncation/remove_any_key_strategy.rb +126 -0
  96. data/lib/rollbar/truncation/remove_extra_strategy.rb +37 -0
  97. data/lib/rollbar/truncation/remove_request_strategy.rb +21 -0
  98. data/lib/rollbar/truncation/strings_strategy.rb +6 -5
  99. data/lib/rollbar/truncation.rb +10 -4
  100. data/lib/rollbar/util/hash.rb +37 -6
  101. data/lib/rollbar/util/ip_anonymizer.rb +33 -0
  102. data/lib/rollbar/util/ip_obfuscator.rb +1 -1
  103. data/lib/rollbar/util.rb +101 -55
  104. data/lib/rollbar/version.rb +1 -1
  105. data/lib/rollbar.rb +91 -879
  106. data/lib/tasks/benchmark.rake +104 -0
  107. data/lib/tasks/tasks.rake +3 -3
  108. data/rollbar.gemspec +21 -32
  109. data/spec/support/rollbar_api.rb +67 -0
  110. metadata +78 -439
  111. data/.travis.yml +0 -155
  112. data/gemfiles/rails30.gemfile +0 -20
  113. data/gemfiles/rails31.gemfile +0 -16
  114. data/gemfiles/rails32.gemfile +0 -17
  115. data/gemfiles/rails40.gemfile +0 -17
  116. data/gemfiles/rails41.gemfile +0 -15
  117. data/gemfiles/rails42.gemfile +0 -15
  118. data/lib/rollbar/active_job.rb +0 -11
  119. data/lib/rollbar/active_record_extension.rb +0 -14
  120. data/lib/rollbar/core_ext/basic_socket.rb +0 -7
  121. data/lib/rollbar/core_ext/thread.rb +0 -9
  122. data/lib/rollbar/delayed_job.rb +0 -78
  123. data/lib/rollbar/encoding/legacy_encoder.rb +0 -20
  124. data/lib/rollbar/goalie.rb +0 -33
  125. data/lib/rollbar/js/frameworks/rails.rb +0 -29
  126. data/lib/rollbar/js/frameworks.rb +0 -6
  127. data/lib/rollbar/js/middleware.rb +0 -129
  128. data/lib/rollbar/js/version.rb +0 -5
  129. data/lib/rollbar/json/default.rb +0 -11
  130. data/lib/rollbar/json/oj.rb +0 -15
  131. data/lib/rollbar/rack.rb +0 -9
  132. data/lib/rollbar/rails/controller_methods.rb +0 -40
  133. data/lib/rollbar/railtie.rb +0 -46
  134. data/lib/rollbar/rake.rb +0 -38
  135. data/lib/rollbar/sidekiq.rb +0 -40
  136. data/lib/rollbar/tasks/rollbar.cap +0 -45
  137. data/spec/cacert.pem +0 -3988
  138. data/spec/controllers/home_controller_spec.rb +0 -455
  139. data/spec/delay/sidekiq_spec.rb +0 -61
  140. data/spec/delay/sucker_punch_spec.rb +0 -25
  141. data/spec/delayed/backend/test.rb +0 -139
  142. data/spec/delayed/serialization/test.rb +0 -0
  143. data/spec/dummyapp/.gitignore +0 -73
  144. data/spec/dummyapp/Rakefile +0 -7
  145. data/spec/dummyapp/app/assets/javascripts/application.js +0 -3
  146. data/spec/dummyapp/app/assets/stylesheets/application.css.scss +0 -37
  147. data/spec/dummyapp/app/controllers/application_controller.rb +0 -3
  148. data/spec/dummyapp/app/controllers/home_controller.rb +0 -60
  149. data/spec/dummyapp/app/controllers/users_controller.rb +0 -17
  150. data/spec/dummyapp/app/helpers/.gitkeep +0 -0
  151. data/spec/dummyapp/app/mailers/.gitkeep +0 -0
  152. data/spec/dummyapp/app/models/.gitkeep +0 -0
  153. data/spec/dummyapp/app/models/user.rb +0 -7
  154. data/spec/dummyapp/app/views/devise/registrations/edit.html.erb +0 -27
  155. data/spec/dummyapp/app/views/devise/registrations/new.html.erb +0 -20
  156. data/spec/dummyapp/app/views/devise/shared/_links.html.erb +0 -25
  157. data/spec/dummyapp/app/views/home/cause_exception.html.erb +0 -1
  158. data/spec/dummyapp/app/views/home/index.html.erb +0 -4
  159. data/spec/dummyapp/app/views/home/report_exception.html.erb +0 -1
  160. data/spec/dummyapp/app/views/js/test.html.erb +0 -1
  161. data/spec/dummyapp/app/views/layouts/_messages.html.erb +0 -5
  162. data/spec/dummyapp/app/views/layouts/_navigation.html.erb +0 -21
  163. data/spec/dummyapp/app/views/layouts/application.html.erb +0 -25
  164. data/spec/dummyapp/app/views/layouts/simple.html.erb +0 -18
  165. data/spec/dummyapp/app/views/users/index.html.erb +0 -8
  166. data/spec/dummyapp/app/views/users/show.html.erb +0 -3
  167. data/spec/dummyapp/config/application.rb +0 -59
  168. data/spec/dummyapp/config/boot.rb +0 -10
  169. data/spec/dummyapp/config/database.yml +0 -25
  170. data/spec/dummyapp/config/environment.rb +0 -5
  171. data/spec/dummyapp/config/environments/development.rb +0 -37
  172. data/spec/dummyapp/config/environments/production.rb +0 -67
  173. data/spec/dummyapp/config/environments/test.rb +0 -37
  174. data/spec/dummyapp/config/initializers/backtrace_silencers.rb +0 -7
  175. data/spec/dummyapp/config/initializers/inflections.rb +0 -15
  176. data/spec/dummyapp/config/initializers/mime_types.rb +0 -5
  177. data/spec/dummyapp/config/initializers/rollbar.rb +0 -23
  178. data/spec/dummyapp/config/initializers/secret_token.rb +0 -7
  179. data/spec/dummyapp/config/initializers/session_store.rb +0 -8
  180. data/spec/dummyapp/config/initializers/wrap_parameters.rb +0 -16
  181. data/spec/dummyapp/config/locales/devise.en.yml +0 -58
  182. data/spec/dummyapp/config/locales/en.yml +0 -5
  183. data/spec/dummyapp/config/routes.rb +0 -17
  184. data/spec/dummyapp/config.ru +0 -4
  185. data/spec/dummyapp/db/migrate/20121121184652_devise_create_users.rb +0 -46
  186. data/spec/dummyapp/db/migrate/20121121184654_add_name_to_users.rb +0 -5
  187. data/spec/dummyapp/db/schema.rb +0 -35
  188. data/spec/dummyapp/db/seeds.rb +0 -12
  189. data/spec/dummyapp/lib/assets/.gitkeep +0 -0
  190. data/spec/dummyapp/public/404.html +0 -26
  191. data/spec/dummyapp/public/422.html +0 -26
  192. data/spec/dummyapp/public/500.html +0 -25
  193. data/spec/dummyapp/public/favicon.ico +0 -0
  194. data/spec/dummyapp/script/rails +0 -6
  195. data/spec/fixtures/file1 +0 -1
  196. data/spec/fixtures/file2 +0 -1
  197. data/spec/fixtures/payloads/message.json +0 -25
  198. data/spec/fixtures/payloads/sample.trace.json +0 -275
  199. data/spec/fixtures/payloads/sample.trace_chain.json +0 -530
  200. data/spec/generators/rollbar/rollbar_generator_spec.rb +0 -24
  201. data/spec/requests/home_spec.rb +0 -49
  202. data/spec/rollbar/active_job_spec.rb +0 -33
  203. data/spec/rollbar/configuration_spec.rb +0 -24
  204. data/spec/rollbar/delay/girl_friday_spec.rb +0 -41
  205. data/spec/rollbar/delay/resque_spec.rb +0 -37
  206. data/spec/rollbar/delay/thread_spec.rb +0 -27
  207. data/spec/rollbar/delayed_job/job_data.rb +0 -35
  208. data/spec/rollbar/delayed_job_spec.rb +0 -90
  209. data/spec/rollbar/encoding/encoder_spec.rb +0 -63
  210. data/spec/rollbar/js/frameworks/rails_spec.rb +0 -19
  211. data/spec/rollbar/js/middleware_spec.rb +0 -162
  212. data/spec/rollbar/json/oj_spec.rb +0 -18
  213. data/spec/rollbar/json_spec.rb +0 -110
  214. data/spec/rollbar/lazy_store_spec.rb +0 -99
  215. data/spec/rollbar/logger_proxy_spec.rb +0 -34
  216. data/spec/rollbar/middleware/rack/builder_spec.rb +0 -151
  217. data/spec/rollbar/middleware/sinatra_spec.rb +0 -197
  218. data/spec/rollbar/rake_spec.rb +0 -34
  219. data/spec/rollbar/request_data_extractor_spec.rb +0 -82
  220. data/spec/rollbar/scrubbers/url_spec.rb +0 -111
  221. data/spec/rollbar/sidekiq_spec.rb +0 -90
  222. data/spec/rollbar/truncation/frames_strategy_spec.rb +0 -70
  223. data/spec/rollbar/truncation/min_body_strategy_spec.rb +0 -57
  224. data/spec/rollbar/truncation/strings_strategy_spec.rb +0 -89
  225. data/spec/rollbar/truncation_spec.rb +0 -27
  226. data/spec/rollbar/util/hash_spec.rb +0 -22
  227. data/spec/rollbar/util_spec.rb +0 -19
  228. data/spec/rollbar_bc_spec.rb +0 -380
  229. data/spec/rollbar_spec.rb +0 -2067
  230. data/spec/spec_helper.rb +0 -49
  231. data/spec/support/cause_exception.rb +0 -1
  232. data/spec/support/encoding_helpers.rb +0 -8
  233. data/spec/support/encodings/iso_8859_9 +0 -1
  234. data/spec/support/fixture_helpers.rb +0 -10
  235. data/spec/support/get_ip_raising.rb +0 -7
  236. data/spec/support/helpers.rb +0 -5
  237. data/spec/support/notifier_helpers.rb +0 -36
  238. data/spec/support/shared_contexts.rb +0 -12
@@ -0,0 +1,314 @@
1
+ require 'socket'
2
+ require 'forwardable'
3
+
4
+ begin
5
+ require 'securerandom'
6
+ rescue LoadError
7
+ nil
8
+ end
9
+
10
+ require 'rollbar/item/backtrace'
11
+ require 'rollbar/util'
12
+ require 'rollbar/encoding'
13
+ require 'rollbar/truncation'
14
+ require 'rollbar/json'
15
+ require 'rollbar/scrubbers/params'
16
+
17
+ module Rollbar
18
+ # This class represents the payload to be sent to the API.
19
+ # It contains the logic to build the payload, trucante it
20
+ # and dump the JSON.
21
+ class Item
22
+ extend Forwardable
23
+
24
+ attr_writer :payload
25
+
26
+ attr_reader :level, :message, :exception, :extra, :configuration, :scope, :logger,
27
+ :notifier, :context
28
+
29
+ def_delegators :payload, :[]
30
+
31
+ class << self
32
+ def build_with(payload, options = {})
33
+ new(options).tap do |item|
34
+ item.payload = item.add_access_token_to_payload(payload)
35
+ end
36
+ end
37
+ end
38
+
39
+ def initialize(options)
40
+ @level = options[:level]
41
+ @message = options[:message]
42
+ @exception = options[:exception]
43
+ @extra = options[:extra]
44
+ @configuration = options[:configuration]
45
+ @logger = options[:logger]
46
+ @scope = options[:scope]
47
+ @payload = nil
48
+ @notifier = options[:notifier]
49
+ @context = options[:context]
50
+ end
51
+
52
+ def payload
53
+ @payload ||= build
54
+ end
55
+
56
+ def build
57
+ data = build_data
58
+ self.payload = add_access_token_to_payload({ 'data' => data })
59
+
60
+ enforce_valid_utf8
61
+ transform
62
+ payload
63
+ end
64
+
65
+ def build_data
66
+ data = initial_data
67
+
68
+ build_optional_data(data)
69
+
70
+ Util.deep_merge(data, configuration.payload_options)
71
+ Util.deep_merge(data, scope)
72
+
73
+ # Our API doesn't allow null context values, so just delete
74
+ # the key if value is nil.
75
+ data.delete(:context) unless data[:context]
76
+
77
+ data
78
+ end
79
+
80
+ def initial_data
81
+ {
82
+ :timestamp => Time.now.to_i,
83
+ :environment => build_environment,
84
+ :level => level,
85
+ :language => 'ruby',
86
+ :framework => configuration.framework,
87
+ :server => server_data,
88
+ :notifier => {
89
+ :name => 'rollbar-gem',
90
+ :version => VERSION,
91
+ :configured_options => configured_options
92
+ },
93
+ :body => build_body
94
+ }
95
+ end
96
+
97
+ def build_optional_data(data)
98
+ if configuration.project_gem_paths.any?
99
+ data[:project_package_paths] = configuration.project_gem_paths
100
+ end
101
+
102
+ data[:code_version] = configuration.code_version if configuration.code_version
103
+
104
+ return unless defined?(SecureRandom) && SecureRandom.respond_to?(:uuid)
105
+
106
+ data[:uuid] = SecureRandom.uuid
107
+ end
108
+
109
+ def configured_options
110
+ if Gem.loaded_specs['activesupport'] &&
111
+ Gem.loaded_specs['activesupport'].version < Gem::Version.new('4.1')
112
+ # There are too many types that crash ActiveSupport JSON serialization,
113
+ # and not worth the risk just to send this diagnostic object.
114
+ # In versions < 4.1, ActiveSupport hooks Ruby's JSON.generate so deeply
115
+ # that there's no workaround.
116
+ 'not serialized in ActiveSupport < 4.1'
117
+ elsif configuration.use_async && !configuration.async_json_payload
118
+ # The setting allows serialization to be performed by each handler,
119
+ # and this usually means it is actually performed by ActiveSupport,
120
+ # which cannot safely serialize this key.
121
+ 'not serialized when async_json_payload is not set'
122
+ else
123
+ scrub(configuration.configured_options.configured)
124
+ end
125
+ end
126
+
127
+ def dump
128
+ # Ensure all keys are strings since we can receive the payload inline or
129
+ # from an async handler job, which can be serialized.
130
+ stringified_payload = Util::Hash.deep_stringify_keys(payload)
131
+ attempts = []
132
+ result = Truncation.truncate(stringified_payload, attempts)
133
+
134
+ return result unless Truncation.truncate?(result)
135
+
136
+ handle_too_large_payload(stringified_payload, result, attempts)
137
+
138
+ nil
139
+ end
140
+
141
+ def handle_too_large_payload(stringified_payload, _final_payload, attempts)
142
+ uuid = stringified_payload['data']['uuid']
143
+ host = stringified_payload['data'].fetch('server', {})['host']
144
+
145
+ original_error = {
146
+ :message => message,
147
+ :exception => exception,
148
+ :configuration => configuration,
149
+ :uuid => uuid,
150
+ :host => host
151
+ }
152
+
153
+ notifier.send_failsafe(too_large_payload_string(attempts), nil, original_error)
154
+
155
+ logger.error('[Rollbar] Payload too large to be sent for UUID ' \
156
+ "#{uuid}: #{Rollbar::JSON.dump(payload)}")
157
+ end
158
+
159
+ def too_large_payload_string(attempts)
160
+ 'Could not send payload due to it being too large after truncating attempts. ' \
161
+ "Original size: #{attempts.first} Attempts: #{attempts.join(', ')} " \
162
+ "Final size: #{attempts.last}"
163
+ end
164
+
165
+ def ignored?
166
+ data = payload['data']
167
+
168
+ return unless data[:person]
169
+
170
+ person_id = data[:person][configuration.person_id_method.to_sym]
171
+ configuration.ignored_person_ids.include?(person_id)
172
+ end
173
+
174
+ def add_access_token_to_payload(payload)
175
+ # Some use cases remain where the token is needed in the payload. For example:
176
+ #
177
+ # When using async senders, if the access token is changed dynamically in
178
+ # the main process config, the sender process won't see that change.
179
+ #
180
+ # Until the delayed sender interface is changed to allow passing dynamic
181
+ # config options, this workaround allows the main process to set the token
182
+ # by adding it to the payload.
183
+ if configuration && configuration.use_payload_access_token
184
+ payload['access_token'] ||= configuration.access_token
185
+ end
186
+
187
+ payload
188
+ end
189
+
190
+ private
191
+
192
+ def build_environment
193
+ env = configuration.environment
194
+ env = 'unspecified' if env.nil? || env.empty?
195
+
196
+ env
197
+ end
198
+
199
+ def build_body
200
+ exception ? build_backtrace_body : build_message_body
201
+ end
202
+
203
+ def build_backtrace_body
204
+ backtrace = Backtrace.new(exception,
205
+ :message => message,
206
+ :extra => build_extra,
207
+ :configuration => configuration)
208
+
209
+ backtrace.to_h
210
+ end
211
+
212
+ def build_extra
213
+ merged_extra = Util.deep_merge(scrub(extra), scrub(error_context))
214
+
215
+ if custom_data_method? && !Rollbar::Util.method_in_stack(:custom_data, __FILE__)
216
+ Util.deep_merge(scrub(custom_data), merged_extra)
217
+ else
218
+ # avoid putting an empty {} in the payload.
219
+ merged_extra.empty? ? nil : merged_extra
220
+ end
221
+ end
222
+
223
+ def error_context
224
+ exception.respond_to?(:rollbar_context) && exception.rollbar_context
225
+ end
226
+
227
+ def scrub(data)
228
+ return data unless data.is_a? Hash
229
+
230
+ options = {
231
+ :params => data,
232
+ :config => Rollbar.configuration.scrub_fields,
233
+ :whitelist => Rollbar.configuration.scrub_whitelist
234
+ }
235
+ Rollbar::Scrubbers::Params.call(options)
236
+ end
237
+
238
+ def custom_data_method?
239
+ !!configuration.custom_data_method
240
+ end
241
+
242
+ def custom_data
243
+ data = if configuration.custom_data_method.arity == 3
244
+ configuration.custom_data_method.call(message, exception, context)
245
+ else
246
+ configuration.custom_data_method.call
247
+ end
248
+
249
+ Rollbar::Util.deep_copy(data)
250
+ rescue StandardError => e
251
+ return {} if configuration.safely?
252
+
253
+ report_custom_data_error(e)
254
+ end
255
+
256
+ def report_custom_data_error(e)
257
+ data = notifier.safely.error(e)
258
+
259
+ return {} unless data.is_a?(Hash) && data[:uuid]
260
+
261
+ uuid_url = Util.uuid_rollbar_url(data, configuration)
262
+
263
+ { :_error_in_custom_data_method => uuid_url }
264
+ end
265
+
266
+ def build_message_body
267
+ extra = build_extra
268
+ result = { :body => message || 'Empty message' }
269
+ result[:extra] = extra if extra
270
+
271
+ { :message => result }
272
+ end
273
+
274
+ def server_data
275
+ data = {
276
+ :host => configuration.host || Socket.gethostname
277
+ }
278
+ data[:root] = configuration.root.to_s if configuration.root
279
+ data[:branch] = configuration.branch if configuration.branch
280
+ data[:pid] = Process.pid
281
+
282
+ data
283
+ end
284
+
285
+ def enforce_valid_utf8
286
+ Util.enforce_valid_utf8(payload)
287
+ end
288
+
289
+ def transform
290
+ handlers = configuration.transform
291
+
292
+ handlers.each do |handler|
293
+ begin
294
+ handler.call(transform_options)
295
+ rescue StandardError => e
296
+ logger.error("[Rollbar] Error calling the `transform` hook: #{e}")
297
+
298
+ break
299
+ end
300
+ end
301
+ end
302
+
303
+ def transform_options
304
+ {
305
+ :level => level,
306
+ :scope => scope,
307
+ :exception => exception,
308
+ :message => message,
309
+ :extra => extra,
310
+ :payload => payload
311
+ }
312
+ end
313
+ end
314
+ end
data/lib/rollbar/js.rb CHANGED
@@ -1,32 +1,4 @@
1
- require "rollbar/js/version"
2
-
3
1
  module Rollbar
4
2
  module Js
5
- extend self
6
-
7
- attr_reader :framework
8
- attr_reader :framework_loader
9
-
10
- def prepare
11
- @framework ||= detect_framework
12
- @framework_loader ||= load_framework_class.new
13
-
14
- @framework_loader.prepare
15
- end
16
-
17
- private
18
-
19
- def detect_framework
20
- case
21
- when defined?(::Rails::VERSION)
22
- :rails
23
- end
24
- end
25
-
26
- def load_framework_class
27
- require "rollbar/js/frameworks/#{framework}"
28
-
29
- Rollbar::Js::Frameworks.const_get(framework.to_s.capitalize)
30
- end
31
3
  end
32
4
  end
data/lib/rollbar/json.rb CHANGED
@@ -1,66 +1,18 @@
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
13
- extend self
14
-
15
- attr_writer :options_module
5
+ module JSON # :nodoc:
6
+ module_function
16
7
 
17
8
  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
9
+ Rollbar.plugins.get('basic_socket').load_scoped!(true) do
10
+ ::JSON.generate(object)
51
11
  end
52
12
  end
53
13
 
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]
14
+ def load(string)
15
+ ::JSON.parse(string)
63
16
  end
64
17
  end
65
18
  end
66
-
@@ -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 version?(version)
@@ -31,5 +15,9 @@ module Rollbar
31
15
 
32
16
  numbers == ::RUBY_VERSION.split('.')[0, numbers.size]
33
17
  end
18
+
19
+ def timeout_exceptions
20
+ [Net::ReadTimeout, Net::OpenTimeout]
21
+ end
34
22
  end
35
23
  end
@@ -1,10 +1,8 @@
1
1
  module Rollbar
2
2
  class LazyStore
3
- attr_reader :loaded_data
3
+ attr_reader :loaded_data, :raw
4
4
  private :loaded_data
5
5
 
6
- attr_reader :raw
7
-
8
6
  def initialize(initial_data)
9
7
  initial_data ||= {}
10
8
 
@@ -21,11 +19,11 @@ module Rollbar
21
19
  end
22
20
 
23
21
  def ==(other)
24
- if other.is_a?(self.class)
25
- raw == other.raw
26
- else
27
- raw == other
28
- end
22
+ raw == if other.is_a?(self.class)
23
+ other.raw
24
+ else
25
+ other
26
+ end
29
27
  end
30
28
 
31
29
  # With this version of clone we ensure that the loaded_data is empty
@@ -41,8 +39,6 @@ module Rollbar
41
39
  raw[key] = value
42
40
 
43
41
  loaded_data.delete(key)
44
-
45
- value
46
42
  end
47
43
 
48
44
  def data
@@ -76,8 +72,8 @@ module Rollbar
76
72
  super
77
73
  end
78
74
 
79
- def respond_to?(method_sym)
80
- super || raw.respond_to?(method_sym)
75
+ def respond_to_missing?(method_sym, include_all)
76
+ raw.respond_to?(method_sym, include_all)
81
77
  end
82
78
  end
83
79
  end
@@ -0,0 +1,71 @@
1
+ require 'logger'
2
+ require 'rollbar'
3
+
4
+ module Rollbar
5
+ # This class provides logger interface that can be used to replace
6
+ # the application logger and send all the log messages to Rollbar
7
+ #
8
+ # Usage:
9
+ # require 'rollbar/logger'
10
+ # logger = Rollbar::Logger.new
11
+ # logger.error('Error processing purchase')
12
+ #
13
+ # If using Rails, you can extend the Rails logger so messages are logged
14
+ # normally and also to Rollbar:
15
+ #
16
+ # Rails.logger.extend(ActiveSupport::Logger.broadcast(Rollbar::Logger.new))
17
+ class Logger < ::Logger
18
+ class Error < RuntimeError; end
19
+
20
+ def initialize
21
+ super(nil)
22
+
23
+ self.level = ERROR
24
+ end
25
+
26
+ def add(severity, message = nil, progname = nil)
27
+ return true if severity < @level
28
+
29
+ message ||= block_given? ? yield : progname
30
+
31
+ return true if blank?(message)
32
+
33
+ rollbar.log(rollbar_level(severity), message)
34
+ end
35
+
36
+ def <<(message)
37
+ error(message)
38
+ end
39
+
40
+ # Returns a Rollbar::Notifier instance with the current global scope and
41
+ # with a logger writing to /dev/null so we don't have a infinite loop
42
+ # when Rollbar.configuration.logger is Rails.logger.
43
+ def rollbar
44
+ notifier = Rollbar.scope
45
+ notifier.configuration.logger = ::Logger.new('/dev/null')
46
+
47
+ notifier
48
+ end
49
+
50
+ private
51
+
52
+ def blank?(message)
53
+ return message.blank? if message.respond_to?(:blank?)
54
+
55
+ message.respond_to?(:empty?) ? !!message.empty? : !message
56
+ end
57
+
58
+ # Find correct Rollbar level to use using the indexes in Logger::Severity
59
+ # DEBUG = 0
60
+ # INFO = 1
61
+ # WARN = 2
62
+ # ERROR = 3
63
+ # FATAL = 4
64
+ # UNKNOWN = 5
65
+ #
66
+ # If not found we'll use 'error' as the used level
67
+ def rollbar_level(severity)
68
+ [:debug, :info, :warning, :error, :critical, :error][severity] || :error
69
+ end
70
+ end
71
+ end
@@ -23,10 +23,27 @@ module Rollbar
23
23
  end
24
24
 
25
25
  def log(level, message)
26
+ unless Rollbar.configuration.enabled && acceptable_levels.include?(level.to_sym)
27
+ return
28
+ end
29
+
26
30
  @object.send(level, message)
27
- rescue
31
+ rescue StandardError
28
32
  puts "[Rollbar] Error logging #{level}:"
29
33
  puts "[Rollbar] #{message}"
30
34
  end
35
+
36
+ protected
37
+
38
+ def acceptable_levels
39
+ @acceptable_levels ||= begin
40
+ levels = [:debug, :info, :warn, :error]
41
+ if Rollbar.configuration.logger_level
42
+ levels[levels.find_index(Rollbar.configuration.logger_level)..-1]
43
+ else
44
+ []
45
+ end
46
+ end
47
+ end
31
48
  end
32
49
  end
@@ -0,0 +1,36 @@
1
+ # Allows a Ruby String to be used to pass native Javascript objects/functions
2
+ # when calling JSON#generate with a Rollbar::JSON::JsOptionsState instance.
3
+ #
4
+ # Example:
5
+ # JSON.generate(
6
+ # { foo: Rollbar::JSON::Value.new('function(){ alert("bar") }') },
7
+ # Rollbar::JSON::JsOptionsState.new
8
+ # )
9
+ #
10
+ # => '{"foo":function(){ alert(\"bar\") }}'
11
+ #
12
+ # MUST use the Ruby JSON encoder, as in the example. The ActiveSupport encoder,
13
+ # which is installed with Rails, is invoked when calling Hash#to_json and #as_json,
14
+ # and will not work.
15
+ #
16
+ module Rollbar
17
+ module JSON
18
+ class JsOptionsState < ::JSON::State; end
19
+
20
+ class Value # :nodoc:
21
+ attr_accessor :value
22
+
23
+ def initialize(value)
24
+ @value = value
25
+ end
26
+
27
+ def to_json(opts = {})
28
+ # Return the raw value if this is from the js middleware
29
+ return value if opts.class == Rollbar::JSON::JsOptionsState
30
+
31
+ # Otherwise convert to a string
32
+ %Q["#{value}"]
33
+ end
34
+ end
35
+ end
36
+ end