rollbar 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,6 +5,7 @@ Dummy::Application.routes.draw do
5
5
  end
6
6
 
7
7
  get "/cause_exception" => "home#cause_exception"
8
+ put "/deprecated_report_exception" => "home#deprecated_report_exception"
8
9
  match "/report_exception" => "home#report_exception", :via => [:get, :post, :put]
9
10
  get "/current_user" => "home#current_user"
10
11
  end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rollbar::LoggerProxy do
4
+ let(:logger) { double(:logger) }
5
+ let(:message) { 'the-message' }
6
+
7
+ subject { described_class.new(logger) }
8
+
9
+ shared_examples 'delegate to logger' do
10
+ it 'logs with correct level' do
11
+ expect(logger).to receive(level).with(message)
12
+
13
+ subject.send(level, message)
14
+ end
15
+ end
16
+
17
+ %w(info error warn debug).each do |level|
18
+ describe "#{level}" do
19
+ it_should_behave_like 'delegate to logger' do
20
+ let(:level) { level }
21
+ end
22
+ end
23
+ end
24
+
25
+ describe '#call' do
26
+ context 'if the logger fails' do
27
+ let(:exception) { StandardError.new }
28
+ it 'doesnt raise' do
29
+ allow(logger).to receive(:info).and_raise(exception)
30
+
31
+ expect { subject.log('info', message) }.not_to raise_error(exception)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ require 'rack'
3
+ require 'rack/builder'
4
+ require 'rack/mock'
5
+ require 'rollbar/middleware/rack/builder'
6
+
7
+
8
+ describe Rollbar::Middleware::Rack::Builder do
9
+ class RackMockError < Exception; end
10
+
11
+ let(:action) do
12
+ proc { fail(RackMockError, 'the-error') }
13
+ end
14
+
15
+ let(:app) do
16
+ action_proc = action
17
+
18
+ Rack::Builder.new { run action_proc }
19
+ end
20
+
21
+ let(:request) do
22
+ Rack::MockRequest.new(app)
23
+ end
24
+
25
+ let(:exception) { kind_of(RackMockError) }
26
+ let(:uncaught_level) { Rollbar.configuration.uncaught_exception_level }
27
+
28
+ it 'reports the error to Rollbar' do
29
+ expect(Rollbar).to receive(:log).with(uncaught_level, exception)
30
+ expect { request.get('/will_crash') }.to raise_error(exception)
31
+ end
32
+
33
+ context 'with GET parameters' do
34
+ let(:params) do
35
+ { 'key' => 'value' }
36
+ end
37
+
38
+ it 'sends them to Rollbar' do
39
+ expect do
40
+ request.get('/will_crash', :params => params)
41
+ end.to raise_error(exception)
42
+
43
+
44
+ expect(Rollbar.last_report[:request][:params]).to be_eql(params)
45
+ end
46
+ end
47
+
48
+ context 'with POST parameters' do
49
+ let(:params) do
50
+ { 'key' => 'value' }
51
+ end
52
+
53
+ it 'sends them to Rollbar' do
54
+ expect do
55
+ request.post('/will_crash', :params => params, 'CONTENT_TYPE' => 'application/json')
56
+ end.to raise_error(exception)
57
+
58
+ expect(Rollbar.last_report[:request][:params]).to be_eql(params)
59
+ end
60
+ end
61
+ end
@@ -15,6 +15,10 @@ class SinatraDummy < Sinatra::Base
15
15
  get '/bar' do
16
16
  'this will not crash'
17
17
  end
18
+
19
+ post '/crash_post' do
20
+ raise DummyError.new
21
+ end
18
22
  end
19
23
 
20
24
  describe Rollbar::Middleware::Sinatra do
@@ -24,8 +28,21 @@ describe Rollbar::Middleware::Sinatra do
24
28
  SinatraDummy
25
29
  end
26
30
 
31
+ let(:logger_mock) { double('logger').as_null_object }
32
+
33
+ before do
34
+ Rollbar.reconfigure do |config|
35
+ config.logger = logger_mock
36
+ config.framework = 'Sinatra'
37
+ end
38
+ end
39
+
40
+ let(:uncaught_level) do
41
+ Rollbar.configuration.uncaught_exception_level
42
+ end
43
+
27
44
  let(:expected_report_args) do
28
- [exception, kind_of(Hash), kind_of(Hash)]
45
+ [uncaught_level, exception]
29
46
  end
30
47
 
31
48
  describe '#call' do
@@ -39,7 +56,7 @@ describe Rollbar::Middleware::Sinatra do
39
56
  end
40
57
 
41
58
  it 'reports the error to Rollbar API and raises error' do
42
- expect(Rollbar).to receive(:report_exception).with(*expected_report_args)
59
+ expect(Rollbar).to receive(:log).with(*expected_report_args)
43
60
 
44
61
  expect do
45
62
  get '/foo'
@@ -55,7 +72,7 @@ describe Rollbar::Middleware::Sinatra do
55
72
  end
56
73
 
57
74
  it 'reports the error to Rollbar, but nothing is raised' do
58
- expect(Rollbar).to receive(:report_exception).with(*expected_report_args)
75
+ expect(Rollbar).to receive(:log).with(*expected_report_args)
59
76
  get '/foo'
60
77
  end
61
78
  end
@@ -63,7 +80,7 @@ describe Rollbar::Middleware::Sinatra do
63
80
 
64
81
  context 'for a NOT crashing endpoint' do
65
82
  it 'doesnt report any error to Rollbar API' do
66
- expect(Rollbar).not_to receive(:report_exception)
83
+ expect(Rollbar).not_to receive(:log)
67
84
  get '/bar'
68
85
  end
69
86
  end
@@ -77,12 +94,73 @@ describe Rollbar::Middleware::Sinatra do
77
94
  end
78
95
 
79
96
  it 'reports the report error' do
80
- expect(Rollbar).to receive(:report_exception).with(*expected_report_args)
97
+ expect(Rollbar).to receive(:log).with(*expected_report_args)
81
98
 
82
99
  expect do
83
100
  get '/foo'
84
101
  end.to raise_error(exception)
85
102
  end
86
103
  end
104
+
105
+ context 'with GET parameters' do
106
+ let(:exception) { kind_of(SinatraDummy::DummyError) }
107
+ let(:params) do
108
+ {
109
+ 'key' => 'value'
110
+ }
111
+ end
112
+
113
+ it 'appear in the sent payload' do
114
+ expect do
115
+ get '/foo', params
116
+ end.to raise_error(exception)
117
+
118
+ expect(Rollbar.last_report[:request][:params]).to be_eql(params)
119
+ end
120
+ end
121
+
122
+ context 'with POST parameters' do
123
+ let(:exception) { kind_of(SinatraDummy::DummyError) }
124
+ let(:params) do
125
+ {
126
+ 'key' => 'value'
127
+ }
128
+ end
129
+
130
+ it 'appear in the sent payload' do
131
+ expect do
132
+ post '/crash_post', params
133
+ end.to raise_error(exception)
134
+
135
+ expect(Rollbar.last_report[:request][:params]).to be_eql(params)
136
+ end
137
+ end
138
+
139
+ context 'with JSON POST parameters' do
140
+ let(:exception) { kind_of(SinatraDummy::DummyError) }
141
+ let(:params) do
142
+ {
143
+ 'key' => 'value'
144
+ }
145
+ end
146
+
147
+ it 'appear in the sent payload' do
148
+ expect do
149
+ post '/crash_post', params.to_json, { 'CONTENT_TYPE' => 'application/json' }
150
+ end.to raise_error(exception)
151
+
152
+ expect(Rollbar.last_report[:request][:params]).to be_eql(params)
153
+ end
154
+ end
155
+
156
+ it 'resets the notifier in every request' do
157
+ get '/bar'
158
+ id1 = Rollbar.notifier.object_id
159
+
160
+ get '/bar'
161
+ id2 = Rollbar.notifier.object_id
162
+
163
+ expect(id1).not_to be_eql(id2)
164
+ end
87
165
  end
88
166
  end
@@ -0,0 +1,388 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'logger'
4
+ require 'spec_helper'
5
+
6
+ describe Rollbar do
7
+ let(:notifier) { Rollbar.notifier }
8
+
9
+ context 'bc_report_message' do
10
+ before do
11
+ configure
12
+ Rollbar.configure do |config|
13
+ config.logger = logger_mock
14
+ end
15
+ end
16
+
17
+ let(:logger_mock) { double('Rails.logger').as_null_object }
18
+ let(:user) do
19
+ User.create(:email => 'email@example.com',
20
+ :encrypted_password => '',
21
+ :created_at => Time.now,
22
+ :updated_at => Time.now)
23
+ end
24
+
25
+ it 'should report simple messages' do
26
+ logger_mock.should_receive(:info).with('[Rollbar] Scheduling payload')
27
+ logger_mock.should_receive(:info).with('[Rollbar] Success')
28
+
29
+ Rollbar.report_message('Test message')
30
+ end
31
+
32
+ it 'should not report anything when disabled' do
33
+ logger_mock.should_not_receive(:info).with('[Rollbar] Success')
34
+
35
+ Rollbar.configure do |config|
36
+ config.enabled = false
37
+ end
38
+
39
+ Rollbar.report_message('Test message that should be ignored')
40
+ end
41
+
42
+ it 'should report messages with extra data' do
43
+ logger_mock.should_receive(:info).with('[Rollbar] Success')
44
+ Rollbar.report_message('Test message with extra data', 'debug', :foo => 'bar',
45
+ :hash => { :a => 123, :b => 'xyz' })
46
+ end
47
+
48
+ it 'should not crash with circular extra_data' do
49
+ a = { :foo => 'bar' }
50
+ b = { :a => a }
51
+ c = { :b => b }
52
+ a[:c] = c
53
+
54
+ logger_mock.should_receive(:error).with(/\[Rollbar\] Reporting internal error encountered while sending data to Rollbar./)
55
+
56
+ Rollbar.report_message('Test message with circular extra data', 'debug', a)
57
+ end
58
+
59
+ it 'should be able to report form validation errors when they are present' do
60
+ logger_mock.should_receive(:info).with('[Rollbar] Success')
61
+ user.errors.add(:example, 'error')
62
+ user.report_validation_errors_to_rollbar
63
+ end
64
+
65
+ it 'should not report form validation errors when they are not present' do
66
+ logger_mock.should_not_receive(:info).with('[Rollbar] Success')
67
+ user.errors.clear
68
+ user.report_validation_errors_to_rollbar
69
+ end
70
+ end
71
+
72
+ context 'bc_report_message_with_request' do
73
+ before(:each) do
74
+ configure
75
+ Rollbar.configure do |config|
76
+ config.logger = logger_mock
77
+ end
78
+ end
79
+
80
+ after(:each) do
81
+ Rollbar.unconfigure
82
+ configure
83
+ end
84
+
85
+ let(:logger_mock) { double('Rails.logger').as_null_object }
86
+ let(:user) { User.create(:email => 'email@example.com', :encrypted_password => '', :created_at => Time.now, :updated_at => Time.now) }
87
+
88
+ it 'should report simple messages' do
89
+ allow(Rollbar).to receive(:notifier).and_return(notifier)
90
+ logger_mock.should_receive(:info).with('[Rollbar] Scheduling payload')
91
+ logger_mock.should_receive(:info).with('[Rollbar] Success')
92
+ Rollbar.report_message_with_request('Test message')
93
+
94
+ Rollbar.last_report[:request].should be_nil
95
+ Rollbar.last_report[:person].should be_nil
96
+ end
97
+
98
+ it 'should report messages with request, person data and extra data' do
99
+ Rollbar.last_report = nil
100
+
101
+ logger_mock.should_receive(:info).with('[Rollbar] Scheduling payload')
102
+ logger_mock.should_receive(:info).with('[Rollbar] Success')
103
+
104
+ request_data = {
105
+ :params => {:foo => 'bar'}
106
+ }
107
+
108
+ person_data = {
109
+ :id => 123,
110
+ :username => 'username'
111
+ }
112
+
113
+ extra_data = {
114
+ :extra_foo => 'extra_bar'
115
+ }
116
+
117
+ Rollbar.report_message_with_request('Test message', 'info', request_data, person_data, extra_data)
118
+
119
+ Rollbar.last_report[:request].should == request_data
120
+ Rollbar.last_report[:person].should == person_data
121
+ Rollbar.last_report[:body][:message][:extra][:extra_foo].should == 'extra_bar'
122
+ end
123
+ end
124
+
125
+ context 'bc_report_exception' do
126
+ before(:each) do
127
+ configure
128
+ Rollbar.configure do |config|
129
+ config.logger = logger_mock
130
+ end
131
+
132
+ begin
133
+ foo = bar
134
+ rescue => e
135
+ @exception = e
136
+ end
137
+ end
138
+
139
+ after(:each) do
140
+ Rollbar.unconfigure
141
+ configure
142
+ end
143
+
144
+ let(:logger_mock) { double('Rails.logger').as_null_object }
145
+
146
+ it 'should report exceptions without person or request data' do
147
+ logger_mock.should_receive(:info).with('[Rollbar] Success')
148
+ Rollbar.report_exception(@exception)
149
+ end
150
+
151
+ it 'should not report anything when disabled' do
152
+ logger_mock.should_not_receive(:info).with('[Rollbar] Success')
153
+ Rollbar.configure do |config|
154
+ config.enabled = false
155
+ end
156
+
157
+ Rollbar.report_exception(@exception)
158
+ end
159
+
160
+ it 'should be enabled when freshly configured' do
161
+ Rollbar.configuration.enabled.should == true
162
+ end
163
+
164
+ it 'should not be enabled when not configured' do
165
+ Rollbar.unconfigure
166
+
167
+ Rollbar.configuration.enabled.should be_nil
168
+ Rollbar.report_exception(@exception).should == 'disabled'
169
+ end
170
+
171
+ it 'should stay disabled if configure is called again' do
172
+ Rollbar.unconfigure
173
+
174
+ # configure once, setting enabled to false.
175
+ Rollbar.configure do |config|
176
+ config.enabled = false
177
+ end
178
+
179
+ # now configure again (perhaps to change some other values)
180
+ Rollbar.configure do |config| end
181
+
182
+ Rollbar.configuration.enabled.should == false
183
+ Rollbar.report_exception(@exception).should == 'disabled'
184
+ end
185
+
186
+ it 'should report exceptions with request and person data' do
187
+ logger_mock.should_receive(:info).with('[Rollbar] Success')
188
+ request_data = {
189
+ :params => { :foo => 'bar' },
190
+ :url => 'http://localhost/',
191
+ :user_ip => '127.0.0.1',
192
+ :headers => {},
193
+ :GET => { 'baz' => 'boz' },
194
+ :session => { :user_id => 123 },
195
+ :method => 'GET',
196
+ }
197
+ person_data = {
198
+ :id => 1,
199
+ :username => 'test',
200
+ :email => 'test@example.com'
201
+ }
202
+ Rollbar.report_exception(@exception, request_data, person_data)
203
+ end
204
+
205
+ it 'should work with an IO object as rack.errors' do
206
+ logger_mock.should_receive(:info).with('[Rollbar] Success')
207
+
208
+ request_data = {
209
+ :params => { :foo => 'bar' },
210
+ :url => 'http://localhost/',
211
+ :user_ip => '127.0.0.1',
212
+ :headers => {},
213
+ :GET => { 'baz' => 'boz' },
214
+ :session => { :user_id => 123 },
215
+ :method => 'GET',
216
+ :env => { :'rack.errors' => IO.new(2, File::WRONLY) },
217
+ }
218
+
219
+ person_data = {
220
+ :id => 1,
221
+ :username => 'test',
222
+ :email => 'test@example.com'
223
+ }
224
+
225
+ Rollbar.report_exception(@exception, request_data, person_data)
226
+ end
227
+
228
+ it 'should ignore ignored exception classes' do
229
+ Rollbar.configure do |config|
230
+ config.exception_level_filters = { 'NameError' => 'ignore' }
231
+ end
232
+
233
+ logger_mock.should_not_receive(:info)
234
+ logger_mock.should_not_receive(:error)
235
+
236
+ Rollbar.report_exception(@exception)
237
+ end
238
+
239
+ it 'should ignore ignored persons' do
240
+ Rollbar.configure do |config|
241
+ config.ignored_person_ids += [1]
242
+ end
243
+
244
+ logger_mock.should_not_receive(:info)
245
+ logger_mock.should_not_receive(:error)
246
+
247
+ person_data = {
248
+ :id => 1,
249
+ :username => 'test',
250
+ :email => 'test@example.com'
251
+ }
252
+ Rollbar.report_exception(@exception, {}, person_data)
253
+ end
254
+
255
+ it 'should not ignore non-ignored persons' do
256
+ Rollbar.configure do |config|
257
+ config.ignored_person_ids += [1]
258
+ end
259
+
260
+ Rollbar.last_report = nil
261
+
262
+ person_data = {
263
+ :id => 1,
264
+ :username => 'test',
265
+ :email => 'test@example.com'
266
+ }
267
+ Rollbar.report_exception(@exception, {}, person_data)
268
+ Rollbar.last_report.should be_nil
269
+
270
+ person_data = {
271
+ :id => 2,
272
+ :username => 'test2',
273
+ :email => 'test2@example.com'
274
+ }
275
+ Rollbar.report_exception(@exception, {}, person_data)
276
+ Rollbar.last_report.should_not be_nil
277
+ end
278
+
279
+ it 'should allow callables to set exception filtered level' do
280
+ callable_mock = double
281
+ Rollbar.configure do |config|
282
+ config.exception_level_filters = { 'NameError' => callable_mock }
283
+ end
284
+
285
+ callable_mock.should_receive(:call).with(@exception).at_least(:once).and_return('info')
286
+ logger_mock.should_receive(:info)
287
+ logger_mock.should_not_receive(:error)
288
+
289
+ Rollbar.report_exception(@exception)
290
+ end
291
+
292
+ it 'should not report exceptions when silenced' do
293
+ notifier.should_not_receive :schedule_payload
294
+
295
+ begin
296
+ test_var = 1
297
+ Rollbar.silenced do
298
+ test_var = 2
299
+ raise
300
+ end
301
+ rescue => e
302
+ Rollbar.report_exception(e)
303
+ end
304
+
305
+ test_var.should == 2
306
+ end
307
+
308
+ it 'should report exception objects with no backtrace' do
309
+ allow(Rollbar).to receive(:notifier).and_return(notifier)
310
+
311
+ payload = nil
312
+
313
+ notifier.stub(:schedule_payload) do |*args|
314
+ payload = args[0]
315
+ end
316
+
317
+ Rollbar.report_exception(StandardError.new('oops'))
318
+
319
+ payload['data'][:body][:trace][:frames].should == []
320
+ payload['data'][:body][:trace][:exception][:class].should == 'StandardError'
321
+ payload['data'][:body][:trace][:exception][:message].should == 'oops'
322
+ end
323
+
324
+ it 'should return the exception data with a uuid, on platforms with SecureRandom' do
325
+ if defined?(SecureRandom) and SecureRandom.respond_to?(:uuid)
326
+ notifier.stub(:schedule_payload) do |*args| end
327
+
328
+ exception_data = Rollbar.report_exception(StandardError.new('oops'))
329
+ exception_data[:uuid].should_not be_nil
330
+ end
331
+ end
332
+
333
+ it 'should report exception objects with nonstandard backtraces' do
334
+ allow(Rollbar).to receive(:notifier).and_return(notifier)
335
+
336
+ payload = nil
337
+
338
+ notifier.stub(:schedule_payload) do |*args|
339
+ payload = args[0]
340
+ end
341
+
342
+ class CustomException < StandardError
343
+ def backtrace
344
+ ['custom backtrace line']
345
+ end
346
+ end
347
+
348
+ exception = CustomException.new('oops')
349
+
350
+ Rollbar.report_exception(exception)
351
+
352
+ payload['data'][:body][:trace][:frames][0][:method].should == 'custom backtrace line'
353
+ end
354
+
355
+ it 'should report exceptions with a custom level' do
356
+ allow(Rollbar).to receive(:notifier).and_return(notifier)
357
+ payload = nil
358
+
359
+ notifier.stub(:schedule_payload) do |*args|
360
+ payload = args[0]
361
+ end
362
+
363
+ Rollbar.report_exception(@exception)
364
+
365
+ payload['data'][:level].should == 'error'
366
+
367
+ Rollbar.report_exception(@exception, nil, nil, 'debug')
368
+
369
+ payload['data'][:level].should == 'debug'
370
+ end
371
+ end
372
+
373
+ # configure with some basic params
374
+ def configure
375
+ Rollbar.reconfigure do |config|
376
+ # special test access token
377
+ config.access_token = test_access_token
378
+ config.logger = ::Rails.logger
379
+ config.root = ::Rails.root
380
+ config.framework = "Rails: #{::Rails::VERSION::STRING}"
381
+ config.request_timeout = 60
382
+ end
383
+ end
384
+
385
+ def test_access_token
386
+ 'aaaabbbbccccddddeeeeffff00001111'
387
+ end
388
+ end