rollbar 2.15.5 → 2.15.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -25,7 +25,7 @@ module Rollbar
25
25
  app_result = app.call(env)
26
26
 
27
27
  begin
28
- return app_result unless add_js?(env, app_result[0], app_result[1])
28
+ return app_result unless add_js?(env, app_result[1])
29
29
 
30
30
  response_string = add_js(env, app_result[2])
31
31
  build_response(env, app_result, response_string)
@@ -40,8 +40,8 @@ module Rollbar
40
40
  !!config[:enabled]
41
41
  end
42
42
 
43
- def add_js?(env, status, headers)
44
- enabled? && status == 200 && !env[JS_IS_INJECTED_KEY] &&
43
+ def add_js?(env, headers)
44
+ enabled? && !env[JS_IS_INJECTED_KEY] &&
45
45
  html?(headers) && !attachment?(headers) && !streaming?(env)
46
46
  end
47
47
 
@@ -65,10 +65,10 @@ module Rollbar
65
65
 
66
66
  return nil unless body
67
67
 
68
- head_open_end = find_end_of_head_open(body)
69
- return nil unless head_open_end
68
+ insert_after_idx = find_insertion_point(body)
69
+ return nil unless insert_after_idx
70
70
 
71
- build_body_with_js(env, body, head_open_end)
71
+ build_body_with_js(env, body, insert_after_idx)
72
72
  rescue => e
73
73
  Rollbar.log_error("[Rollbar] Rollbar.js could not be added because #{e} exception")
74
74
  nil
@@ -91,9 +91,15 @@ module Rollbar
91
91
  body[head_open_end + 1..-1]
92
92
  end
93
93
 
94
- def find_end_of_head_open(body)
95
- head_open = body.index(/<head\W/)
96
- body.index('>', head_open) if head_open
94
+ def find_insertion_point(body)
95
+ find_end_after_regex(body, /<meta\s*charset=/i) ||
96
+ find_end_after_regex(body, /<meta\s*http-equiv="Content-Type"/i) ||
97
+ find_end_after_regex(body, /<head\W/i)
98
+ end
99
+
100
+ def find_end_after_regex(body, regex)
101
+ open_idx = body.index(regex)
102
+ body.index('>', open_idx) if open_idx
97
103
  end
98
104
 
99
105
  def join_body(response)
@@ -107,6 +107,11 @@ module Rollbar
107
107
  # will become the associated exception for the report. The last hash
108
108
  # argument will be used as the extra data for the report.
109
109
  #
110
+ # If the extra hash contains a symbol key :custom_data_method_context
111
+ # the value of the key will be used as the context for
112
+ # configuration.custom_data_method and will be removed from the extra
113
+ # hash.
114
+ #
110
115
  # @example
111
116
  # begin
112
117
  # foo = bar
@@ -123,7 +128,7 @@ module Rollbar
123
128
  def log(level, *args)
124
129
  return 'disabled' unless configuration.enabled
125
130
 
126
- message, exception, extra = extract_arguments(args)
131
+ message, exception, extra, context = extract_arguments(args)
127
132
  use_exception_level_filters = use_exception_level_filters?(extra)
128
133
 
129
134
  return 'ignored' if ignored?(exception, use_exception_level_filters)
@@ -141,7 +146,7 @@ module Rollbar
141
146
  use_exception_level_filters)
142
147
 
143
148
  begin
144
- report(level, message, exception, extra)
149
+ report(level, message, exception, extra, context)
145
150
  rescue StandardError, SystemStackError => e
146
151
  report_internal_error(e)
147
152
 
@@ -327,18 +332,26 @@ module Rollbar
327
332
  message = nil
328
333
  exception = nil
329
334
  extra = nil
335
+ context = nil
330
336
 
331
337
  args.each do |arg|
332
338
  if arg.is_a?(String)
333
339
  message = arg
334
340
  elsif arg.is_a?(Exception)
335
341
  exception = arg
342
+ elsif RUBY_PLATFORM == 'java' && arg.is_a?(java.lang.Exception)
343
+ exception = arg
336
344
  elsif arg.is_a?(Hash)
337
345
  extra = arg
346
+
347
+ context = extra[:custom_data_method_context]
348
+ extra.delete :custom_data_method_context
349
+
350
+ extra = nil if extra.empty?
338
351
  end
339
352
  end
340
353
 
341
- [message, exception, extra]
354
+ [message, exception, extra, context]
342
355
  end
343
356
 
344
357
  def lookup_exception_level(orig_level, exception, use_exception_level_filters)
@@ -369,14 +382,14 @@ module Rollbar
369
382
  end
370
383
  end
371
384
 
372
- def report(level, message, exception, extra)
385
+ def report(level, message, exception, extra, context)
373
386
  unless message || exception || extra
374
387
  log_error '[Rollbar] Tried to send a report with no message, exception or extra data.'
375
388
 
376
389
  return 'error'
377
390
  end
378
391
 
379
- item = build_item(level, message, exception, extra)
392
+ item = build_item(level, message, exception, extra, context)
380
393
 
381
394
  return 'ignored' if item.ignored?
382
395
 
@@ -396,7 +409,7 @@ module Rollbar
396
409
  log_error '[Rollbar] Reporting internal error encountered while sending data to Rollbar.'
397
410
 
398
411
  begin
399
- item = build_item('error', nil, exception, :internal => true)
412
+ item = build_item('error', nil, exception, { :internal => true }, nil)
400
413
  rescue => e
401
414
  send_failsafe('build_item in exception_data', e)
402
415
  return
@@ -419,7 +432,7 @@ module Rollbar
419
432
 
420
433
  ## Payload building functions
421
434
 
422
- def build_item(level, message, exception, extra)
435
+ def build_item(level, message, exception, extra, context)
423
436
  options = {
424
437
  :level => level,
425
438
  :message => message,
@@ -428,7 +441,8 @@ module Rollbar
428
441
  :configuration => configuration,
429
442
  :logger => logger,
430
443
  :scope => scope_object,
431
- :notifier => self
444
+ :notifier => self,
445
+ :context => context
432
446
  }
433
447
 
434
448
  item = Item.new(options)
@@ -11,7 +11,8 @@ module Rollbar
11
11
  callbacks do |lifecycle|
12
12
  lifecycle.around(:invoke_job, &Delayed::invoke_job_callback)
13
13
  lifecycle.after(:failure) do |_, job, _, _|
14
- Delayed.report(job.last_error, job)
14
+ data = Rollbar::Delayed.build_job_data(job)
15
+ ::Rollbar.scope(:request => data).error(job.last_error, :use_exception_level_filters => true) if job.last_error
15
16
  end
16
17
  end
17
18
  end
@@ -176,7 +176,12 @@ module Rollbar
176
176
  return {} unless correct_method
177
177
  return {} unless json_request?(rack_req)
178
178
 
179
- Rollbar::JSON.load(rack_req.body.read)
179
+ raw_body = rack_req.body.read
180
+ begin
181
+ Rollbar::JSON.load(raw_body)
182
+ rescue
183
+ raw_body
184
+ end
180
185
  rescue
181
186
  {}
182
187
  ensure
@@ -28,9 +28,34 @@ namespace :rollbar do
28
28
  info 'Rollbar notification complete.'
29
29
  end
30
30
  end
31
+
32
+ desc 'Upload sourcemaps to Rollbar.'
33
+ task :sourcemap do
34
+ on primary fetch(:rollbar_role) do
35
+ info "Uploading source maps from #{fetch(:rollbar_sourcemaps_target_dir)}"
36
+ warn("You need to upgrade capistrano to '>= 3.1' version in order to correctly upload sourcemaps to Rollbar. (On 3.0, the reported revision will be incorrect.)") if Capistrano::VERSION =~ /^3\.0/
37
+ url_base = fetch(:rollbar_sourcemaps_minified_url_base)
38
+ unless url_base
39
+ warn "No #{rollbar_sourcemaps_minified_url_base} was specified. Sourcemaps won't be uploaded."
40
+ return
41
+ end
42
+ url_base = "http://#{url_base}" unless url_base.index(/https?:\/\//)
43
+ within release_path do
44
+ within 'public' do
45
+ source_maps = capture(:find, '-name', "'*.js.map'").split("\n")
46
+ source_maps = source_maps.map { |file| file.gsub(/^\.\//, '') }
47
+ source_maps.each do |source_map|
48
+ minified_url = File.join(url_base, source_map)
49
+ execute(:curl, *%W(https://api.rollbar.com/api/1/sourcemap -F access_token=#{fetch(:rollbar_token)} -F version=#{fetch(:rollbar_revision)} -F minified_url=#{minified_url} -F source_map=@./#{source_map}))
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
31
55
  end
32
56
 
33
57
  namespace :deploy do
58
+ after 'deploy:compile_assets', 'rollbar:sourcemap'
34
59
  after 'deploy:finished', 'rollbar:deploy'
35
60
  end
36
61
 
@@ -1,3 +1,3 @@
1
1
  module Rollbar
2
- VERSION = '2.15.5'
2
+ VERSION = '2.15.6'
3
3
  end
@@ -1,6 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
3
 
4
+ def wrap_process_args(*args)
5
+ if ::Gem::Version.new(::Rails.version) >= ::Gem::Version.new('5.0')
6
+ [{ :params => args[0], :headers => args[1] }]
7
+ else
8
+ args
9
+ end
10
+ end
11
+
4
12
  describe HomeController do
5
13
  let(:logger_mock) { double("Rails.logger").as_null_object }
6
14
  let(:notifier) { Rollbar.notifier }
@@ -20,7 +28,7 @@ describe HomeController do
20
28
 
21
29
  context "rollbar base_data" do
22
30
  it 'should have the Rails environment' do
23
- data = Rollbar.notifier.send(:build_item, 'error', 'message', nil, nil)
31
+ data = Rollbar.notifier.send(:build_item, 'error', 'message', nil, nil, nil)
24
32
  data['data'][:environment].should == ::Rails.env
25
33
  end
26
34
 
@@ -29,7 +37,7 @@ describe HomeController do
29
37
  config.environment = 'dev'
30
38
  end
31
39
 
32
- data = Rollbar.notifier.send(:build_item, 'error', 'message', nil, nil)
40
+ data = Rollbar.notifier.send(:build_item, 'error', 'message', nil, nil, nil)
33
41
  data['data'][:environment].should == 'dev'
34
42
  end
35
43
 
@@ -37,7 +45,7 @@ describe HomeController do
37
45
  old_env, ::Rails.env = ::Rails.env, ''
38
46
  preconfigure_rails_notifier
39
47
 
40
- data = Rollbar.notifier.send(:build_item, 'error', 'message', nil, nil)
48
+ data = Rollbar.notifier.send(:build_item, 'error', 'message', nil, nil, nil)
41
49
  data['data'][:environment].should == 'unspecified'
42
50
 
43
51
  ::Rails.env = old_env
@@ -193,7 +201,7 @@ describe HomeController do
193
201
  :secret_token => "f6805fea1cae0fb79c5e63bbdcd12bc6",
194
202
  }
195
203
 
196
- post '/report_exception', params
204
+ post '/report_exception', *wrap_process_args(params)
197
205
 
198
206
  filtered = Rollbar.last_report[:request][:POST]
199
207
 
@@ -216,7 +224,7 @@ describe HomeController do
216
224
  :notpass => "hidden"
217
225
  }
218
226
 
219
- post '/report_exception', params
227
+ post '/report_exception', *wrap_process_args(params)
220
228
 
221
229
  filtered = Rollbar.last_report[:request][:POST]
222
230
 
@@ -248,7 +256,7 @@ describe HomeController do
248
256
  it "should raise a NameError and have PUT params in the reported exception" do
249
257
  logger_mock.should_receive(:info).with('[Rollbar] Success')
250
258
 
251
- put '/report_exception', { :putparam => "putval" }
259
+ put '/report_exception', *wrap_process_args({ :putparam => "putval" })
252
260
 
253
261
  Rollbar.last_report.should_not be_nil
254
262
  Rollbar.last_report[:request][:POST]["putparam"].should == "putval"
@@ -258,7 +266,7 @@ describe HomeController do
258
266
  it 'reports the errors successfully' do
259
267
  logger_mock.should_receive(:info).with('[Rollbar] Success')
260
268
 
261
- put '/deprecated_report_exception', { :putparam => "putval" }
269
+ put '/deprecated_report_exception', *wrap_process_args({ :putparam => "putval" })
262
270
 
263
271
  Rollbar.last_report.should_not be_nil
264
272
  Rollbar.last_report[:request][:POST]["putparam"].should == "putval"
@@ -270,7 +278,7 @@ describe HomeController do
270
278
  @request.env["HTTP_ACCEPT"] = "application/json"
271
279
 
272
280
  params = { :jsonparam => 'jsonval' }.to_json
273
- post '/report_exception', params, { 'CONTENT_TYPE' => 'application/json' }
281
+ post '/report_exception', *wrap_process_args(params, { 'CONTENT_TYPE' => 'application/json' })
274
282
 
275
283
  Rollbar.last_report.should_not be_nil
276
284
  expect(Rollbar.last_report[:request][:body]).to be_eql(params)
@@ -328,7 +336,7 @@ describe HomeController do
328
336
  before { cookies[:session_id] = user.id }
329
337
 
330
338
  it 'sends the current user data' do
331
- put '/report_exception', { 'foo' => 'bar' }
339
+ put '/report_exception', *wrap_process_args({ 'foo' => 'bar' })
332
340
 
333
341
  person_data = Rollbar.last_report[:person]
334
342
 
@@ -342,7 +350,7 @@ describe HomeController do
342
350
 
343
351
  context 'with routing errors', :type => :request do
344
352
  it 'raises a RoutingError exception' do
345
- expect { get '/foo/bar', { :foo => :bar } }.to raise_exception(ActionController::RoutingError)
353
+ expect { get '/foo/bar', *wrap_process_args({ :foo => :bar }) }.to raise_exception(ActionController::RoutingError)
346
354
 
347
355
  report = Rollbar.last_report
348
356
  expect(report[:request][:GET]['foo']).to be_eql('bar')
@@ -365,7 +373,7 @@ describe HomeController do
365
373
 
366
374
  context 'with a single upload' do
367
375
  it "saves attachment data" do
368
- expect { post '/file_upload', { :upload => file1 } }.to raise_exception(NameError)
376
+ expect { post '/file_upload', *wrap_process_args({ :upload => file1 }) }.to raise_exception(NameError)
369
377
 
370
378
  upload_param = Rollbar.last_report[:request][:POST]['upload']
371
379
 
@@ -380,7 +388,7 @@ describe HomeController do
380
388
 
381
389
  context 'with multiple uploads', :type => :request do
382
390
  it "saves attachment data for all uploads" do
383
- expect { post '/file_upload', { :upload => [file1, file2] } }.to raise_exception(NameError)
391
+ expect { post '/file_upload', *wrap_process_args({ :upload => [file1, file2] }) }.to raise_exception(NameError)
384
392
  sent_params = Rollbar.last_report[:request][:POST]['upload']
385
393
 
386
394
  expect(sent_params).to be_kind_of(Array)
@@ -406,7 +414,7 @@ describe HomeController do
406
414
 
407
415
  it 'parses the correct headers' do
408
416
  expect do
409
- post '/cause_exception', params, { 'ACCEPT' => 'application/vnd.github.v3+json' }
417
+ post '/cause_exception', *wrap_process_args(params, { 'ACCEPT' => 'application/vnd.github.v3+json' })
410
418
  end.to raise_exception(NameError)
411
419
 
412
420
  expect(Rollbar.last_report[:request][:POST]['foo']).to be_eql('bar')
@@ -429,7 +437,7 @@ describe HomeController do
429
437
  end
430
438
 
431
439
  it 'scrubs sensible data from URL' do
432
- expect { get '/cause_exception', { :password => 'my-secret-password' }, headers }.to raise_exception(NameError)
440
+ expect { get '/cause_exception', *wrap_process_args({ :password => 'my-secret-password' }, headers) }.to raise_exception(NameError)
433
441
 
434
442
  request_data = Rollbar.last_report[:request]
435
443
 
@@ -1,5 +1,5 @@
1
1
  class UsersController < ApplicationController
2
- before_filter :authenticate_user!
2
+ respond_to?(:before_action) ? (before_action :authenticate_user!) : (before_filter :authenticate_user!)
3
3
 
4
4
  def index
5
5
  @users = User.all
@@ -20,6 +20,7 @@ describe Rollbar::Item do
20
20
  let(:exception) {}
21
21
  let(:extra) {}
22
22
  let(:scope) {}
23
+ let(:context) {}
23
24
 
24
25
  let(:options) do
25
26
  {
@@ -30,7 +31,8 @@ describe Rollbar::Item do
30
31
  :configuration => configuration,
31
32
  :logger => logger,
32
33
  :scope => scope,
33
- :notifier => notifier
34
+ :notifier => notifier,
35
+ :context => context
34
36
  }
35
37
  end
36
38
 
@@ -120,6 +122,47 @@ describe Rollbar::Item do
120
122
  payload['data'][:body][:message][:extra][:a].should == 1
121
123
  payload['data'][:body][:message][:extra][:b][2].should == 4
122
124
  end
125
+
126
+ context do
127
+ let(:context) { { :controller => "ExampleController" } }
128
+
129
+ it 'should have access to the context in custom_data_method' do
130
+ configuration.custom_data_method = lambda do |message, exception, context|
131
+ { :result => "MyApp#" + context[:controller] }
132
+ end
133
+
134
+ payload['data'][:body][:message][:extra].should_not be_nil
135
+ payload['data'][:body][:message][:extra][:result].should == "MyApp#"+context[:controller]
136
+ end
137
+
138
+ it 'should not include data passed in :context if there is no custom_data_method configured' do
139
+ configuration.custom_data_method = nil
140
+
141
+ payload['data'][:body][:message][:extra].should be_nil
142
+ end
143
+
144
+ it 'should have access to the message in custom_data_method' do
145
+ configuration.custom_data_method = lambda do |message, exception, context|
146
+ { :result => "Transformed in custom_data_method: " + message }
147
+ end
148
+
149
+ payload['data'][:body][:message][:extra].should_not be_nil
150
+ payload['data'][:body][:message][:extra][:result].should == "Transformed in custom_data_method: " + message
151
+ end
152
+
153
+ context do
154
+ let(:exception) { Exception.new "Exception to test custom_data_method" }
155
+
156
+ it 'should have access to the current exception in custom_data_method' do
157
+ configuration.custom_data_method = lambda do |message, exception, context|
158
+ { :result => "Transformed in custom_data_method: " + exception.message }
159
+ end
160
+
161
+ payload['data'][:body][:trace][:extra].should_not be_nil
162
+ payload['data'][:body][:trace][:extra][:result].should == "Transformed in custom_data_method: " + exception.message
163
+ end
164
+ end
165
+ end
123
166
 
124
167
  context do
125
168
  let(:extra) do
@@ -58,6 +58,16 @@ describe Rollbar::Logger do
58
58
  subject.add(10, message)
59
59
  end
60
60
  end
61
+
62
+ context 'without active_support/core_ext/object/blank' do
63
+ let(:message) { 'foo'.tap { |message| message.instance_eval('undef :blank?') } }
64
+
65
+ it 'calls Rollbar to send the message' do
66
+ expect_any_instance_of(Rollbar::Notifier).to receive(:log).with(:error, message)
67
+
68
+ subject.add(Logger::ERROR, message)
69
+ end
70
+ end
61
71
  end
62
72
 
63
73
  describe '#<<' do
@@ -27,6 +27,35 @@ END
27
27
  let(:minified_html) do
28
28
  <<-END
29
29
  <html><head><link rel="stylesheet" href="url" type="text/css" media="screen" /><script type="text/javascript" src="foo"></script></head><body><h1>Testing the middleware</h1></body></html>
30
+ END
31
+ end
32
+ let(:meta_charset_html) do
33
+ <<-END
34
+ <html>
35
+ <head>
36
+ <meta charset="UTF-8"/>
37
+ <link rel="stylesheet" href="url" type="text/css" media="screen" />
38
+ <script type="text/javascript" src="foo"></script>
39
+ </head>
40
+ <body>
41
+ <h1>Testing the middleware</h1>
42
+ </body>
43
+ </html>
44
+ END
45
+ end
46
+ let(:meta_content_html) do
47
+ <<-END
48
+ <html>
49
+ <head>
50
+ <meta content="origin" id="mref" name="referrer">
51
+ <link rel="stylesheet" href="url" type="text/css" media="screen" />
52
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
53
+ <script type="text/javascript" src="foo"></script>
54
+ </head>
55
+ <body>
56
+ <h1>Testing the middleware</h1>
57
+ </body>
58
+ </html>
30
59
  END
31
60
  end
32
61
  let(:snippet) { 'THIS IS THE SNIPPET' }
@@ -97,6 +126,46 @@ END
97
126
  end
98
127
  end
99
128
 
129
+ context 'having a html 200 resposne with meta charset tag' do
130
+ let(:body) { [meta_charset_html] }
131
+ let(:status) { 200 }
132
+ let(:headers) do
133
+ { 'Content-Type' => content_type }
134
+ end
135
+ it 'adds the config and the snippet to the response' do
136
+ res_status, res_headers, response = subject.call(env)
137
+ new_body = response.body.join
138
+
139
+ expect(new_body).to_not include('>>')
140
+ expect(new_body).to include(snippet)
141
+ expect(new_body).to include(config[:options].to_json)
142
+ expect(res_status).to be_eql(status)
143
+ expect(res_headers['Content-Type']).to be_eql(content_type)
144
+ meta_tag = '<meta charset="UTF-8"/>'
145
+ expect(new_body.index(snippet)).to be > new_body.index(meta_tag)
146
+ end
147
+ end
148
+
149
+ context 'having a html 200 resposne with meta content-type tag' do
150
+ let(:body) { [meta_content_html] }
151
+ let(:status) { 200 }
152
+ let(:headers) do
153
+ { 'Content-Type' => content_type }
154
+ end
155
+ it 'adds the config and the snippet to the response' do
156
+ res_status, res_headers, response = subject.call(env)
157
+ new_body = response.body.join
158
+
159
+ expect(new_body).to_not include('>>')
160
+ expect(new_body).to include(snippet)
161
+ expect(new_body).to include(config[:options].to_json)
162
+ expect(res_status).to be_eql(status)
163
+ expect(res_headers['Content-Type']).to be_eql(content_type)
164
+ meta_tag = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>'
165
+ expect(new_body.index(snippet)).to be > new_body.index(meta_tag)
166
+ end
167
+ end
168
+
100
169
  context 'having a html 200 response and SecureHeaders >= 3.0.0 defined' do
101
170
  let(:body) { [html] }
102
171
  let(:status) { 200 }