rollbar 2.15.5 → 2.15.6

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.
@@ -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 }