rollbar 1.1.0 → 1.2.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.
@@ -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