rollbar 2.10.0 → 2.11.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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -2
  3. data/CHANGELOG.md +20 -0
  4. data/README.md +73 -16
  5. data/docs/configuration.md +10 -0
  6. data/gemfiles/rails30.gemfile +2 -0
  7. data/gemfiles/rails31.gemfile +2 -0
  8. data/gemfiles/rails32.gemfile +2 -0
  9. data/gemfiles/rails40.gemfile +2 -0
  10. data/gemfiles/rails41.gemfile +2 -0
  11. data/gemfiles/rails42.gemfile +2 -0
  12. data/gemfiles/rails50.gemfile +2 -0
  13. data/gemfiles/ruby_1_8_and_1_9_2.gemfile +43 -0
  14. data/lib/rollbar.rb +139 -353
  15. data/lib/rollbar/configuration.rb +4 -0
  16. data/lib/rollbar/item.rb +225 -0
  17. data/lib/rollbar/item/backtrace.rb +97 -0
  18. data/lib/rollbar/js.rb +0 -28
  19. data/lib/rollbar/language_support.rb +10 -0
  20. data/lib/rollbar/{js/middleware.rb → middleware/js.rb} +3 -4
  21. data/lib/rollbar/plugin.rb +63 -0
  22. data/lib/rollbar/plugins.rb +41 -0
  23. data/lib/rollbar/{active_job.rb → plugins/active_job.rb} +0 -0
  24. data/lib/rollbar/plugins/basic_socket.rb +16 -0
  25. data/lib/rollbar/plugins/delayed_job.rb +12 -0
  26. data/lib/rollbar/plugins/delayed_job/job_data.rb +16 -0
  27. data/lib/rollbar/{delayed_job.rb → plugins/delayed_job/plugin.rb} +1 -17
  28. data/lib/rollbar/plugins/goalie.rb +46 -0
  29. data/lib/rollbar/plugins/rack.rb +16 -0
  30. data/lib/rollbar/plugins/rails.rb +77 -0
  31. data/lib/rollbar/{rails → plugins/rails}/controller_methods.rb +0 -0
  32. data/lib/rollbar/plugins/rails/railtie30.rb +17 -0
  33. data/lib/rollbar/plugins/rails/railtie32.rb +18 -0
  34. data/lib/rollbar/plugins/rails/railtie_mixin.rb +33 -0
  35. data/lib/rollbar/plugins/rake.rb +45 -0
  36. data/lib/rollbar/plugins/sidekiq.rb +35 -0
  37. data/lib/rollbar/{sidekiq.rb → plugins/sidekiq/plugin.rb} +0 -18
  38. data/lib/rollbar/plugins/thread.rb +13 -0
  39. data/lib/rollbar/plugins/validations.rb +33 -0
  40. data/lib/rollbar/request_data_extractor.rb +30 -18
  41. data/lib/rollbar/scrubbers/params.rb +4 -2
  42. data/lib/rollbar/scrubbers/url.rb +30 -28
  43. data/lib/rollbar/util.rb +10 -0
  44. data/lib/rollbar/version.rb +1 -1
  45. data/spec/controllers/home_controller_spec.rb +4 -3
  46. data/spec/dummyapp/app/models/post.rb +9 -0
  47. data/spec/dummyapp/app/models/user.rb +2 -0
  48. data/spec/dummyapp/config/initializers/rollbar.rb +1 -0
  49. data/spec/fixtures/plugins/dummy1.rb +5 -0
  50. data/spec/fixtures/plugins/dummy2.rb +5 -0
  51. data/spec/rollbar/item_spec.rb +635 -0
  52. data/spec/rollbar/logger_proxy_spec.rb +4 -0
  53. data/spec/rollbar/{js/middleware_spec.rb → middleware/js_spec.rb} +32 -3
  54. data/spec/rollbar/plugin_spec.rb +147 -0
  55. data/spec/rollbar/{active_job_spec.rb → plugins/active_job_spec.rb} +0 -1
  56. data/spec/rollbar/{delayed_job → plugins/delayed_job}/job_data.rb +0 -0
  57. data/spec/rollbar/{delayed_job_spec.rb → plugins/delayed_job_spec.rb} +3 -6
  58. data/spec/rollbar/{middleware/rack/builder_spec.rb → plugins/rack_spec.rb} +2 -1
  59. data/spec/rollbar/{js/frameworks/rails_spec.rb → plugins/rails_js_spec.rb} +1 -1
  60. data/spec/rollbar/{rake_spec.rb → plugins/rake_spec.rb} +2 -1
  61. data/spec/rollbar/{sidekiq_spec.rb → plugins/sidekiq_spec.rb} +2 -1
  62. data/spec/rollbar/plugins/validations_spec.rb +43 -0
  63. data/spec/rollbar/plugins_spec.rb +68 -0
  64. data/spec/rollbar/request_data_extractor_spec.rb +56 -10
  65. data/spec/rollbar/scrubbers/params_spec.rb +13 -10
  66. data/spec/rollbar/scrubbers/url_spec.rb +17 -12
  67. data/spec/rollbar/sidekig/clear_scope_spec.rb +2 -1
  68. data/spec/rollbar/util_spec.rb +61 -0
  69. data/spec/rollbar_bc_spec.rb +10 -10
  70. data/spec/rollbar_spec.rb +57 -706
  71. data/spec/spec_helper.rb +8 -0
  72. data/spec/support/notifier_helpers.rb +1 -0
  73. data/spec/support/rollbar_api.rb +57 -0
  74. metadata +57 -33
  75. data/lib/rollbar/active_record_extension.rb +0 -14
  76. data/lib/rollbar/core_ext/basic_socket.rb +0 -7
  77. data/lib/rollbar/core_ext/thread.rb +0 -9
  78. data/lib/rollbar/goalie.rb +0 -33
  79. data/lib/rollbar/js/frameworks.rb +0 -6
  80. data/lib/rollbar/js/frameworks/rails.rb +0 -49
  81. data/lib/rollbar/js/version.rb +0 -5
  82. data/lib/rollbar/rack.rb +0 -9
  83. data/lib/rollbar/railtie.rb +0 -46
  84. data/lib/rollbar/rake.rb +0 -40
@@ -6,6 +6,10 @@ describe Rollbar::LoggerProxy do
6
6
 
7
7
  subject { described_class.new(logger) }
8
8
 
9
+ before do
10
+ allow(Rollbar.configuration).to receive(:enabled).and_return(true)
11
+ end
12
+
9
13
  shared_examples 'delegate to logger' do
10
14
  it 'logs with correct level' do
11
15
  expect(logger).to receive(level).with(message)
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
- require 'rollbar/js/middleware'
2
+ require 'rollbar/middleware/js'
3
3
 
4
- describe Rollbar::Js::Middleware do
4
+ describe Rollbar::Middleware::Js do
5
5
  subject { described_class.new(app, config) }
6
6
 
7
7
  let(:env) { {} }
@@ -97,7 +97,7 @@ END
97
97
  end
98
98
  end
99
99
 
100
- context 'having a html 200 response and SecureHeaders defined' do
100
+ context 'having a html 200 response and SecureHeaders >= 3.0.0 defined' do
101
101
  let(:body) { [html] }
102
102
  let(:status) { 200 }
103
103
  let(:headers) do
@@ -106,9 +106,14 @@ END
106
106
 
107
107
  before do
108
108
  Object.const_set('SecureHeaders', Module.new)
109
+ SecureHeaders.const_set('VERSION', '3.0.0')
109
110
  allow(SecureHeaders).to receive(:content_security_policy_script_nonce) { 'lorem-ipsum-nonce' }
110
111
  end
111
112
 
113
+ after do
114
+ Object.send(:remove_const, 'SecureHeaders')
115
+ end
116
+
112
117
  it 'renders the snippet and config in the response with nonce in script tag when SecureHeaders installed' do
113
118
  res_status, res_headers, response = subject.call(env)
114
119
  new_body = response.body.join
@@ -116,9 +121,33 @@ END
116
121
  expect(new_body).to include('<script type="text/javascript" nonce="lorem-ipsum-nonce">')
117
122
  expect(new_body).to include("var _rollbarConfig = #{config[:options].to_json};")
118
123
  expect(new_body).to include(snippet)
124
+ end
125
+ end
126
+
127
+ context 'having a html 200 response and SecureHeaders < 3.0.0 defined' do
128
+ let(:body) { [html] }
129
+ let(:status) { 200 }
130
+ let(:headers) do
131
+ { 'Content-Type' => content_type }
132
+ end
119
133
 
134
+ before do
135
+ Object.const_set('SecureHeaders', Module.new)
136
+ SecureHeaders.const_set('VERSION', '2.4.0')
137
+ end
138
+
139
+ after do
120
140
  Object.send(:remove_const, 'SecureHeaders')
121
141
  end
142
+
143
+ it 'renders the snippet and config in the response without nonce in script tag when too old SecureHeaders installed' do
144
+ res_status, res_headers, response = subject.call(env)
145
+ new_body = response.body.join
146
+
147
+ expect(new_body).to include('<script type="text/javascript">')
148
+ expect(new_body).to include("var _rollbarConfig = #{config[:options].to_json};")
149
+ expect(new_body).to include(snippet)
150
+ end
122
151
  end
123
152
 
124
153
  context 'having a html 200 response without head', :add_js => false do
@@ -0,0 +1,147 @@
1
+ require 'spec_helper'
2
+ require 'rollbar/plugin'
3
+
4
+ describe Rollbar::Plugin do
5
+ describe '#load!' do
6
+ subject { described_class.new(:plugin) }
7
+
8
+ before { subject.instance_eval(&plugin_proc) }
9
+
10
+ context 'with true dependencies' do
11
+ let(:dummy_object) { '' }
12
+ let(:plugin_proc) do
13
+ dummy = dummy_object
14
+
15
+ proc do
16
+ dependency do
17
+ true
18
+ end
19
+
20
+ dependency do
21
+ 1 == 1.0
22
+ end
23
+
24
+ execute do
25
+ dummy.upcase
26
+ end
27
+
28
+ execute do
29
+ dummy.downcase
30
+ end
31
+ end
32
+ end
33
+
34
+ it 'calls the callables' do
35
+ expect(dummy_object).to receive(:upcase).once
36
+ expect(dummy_object).to receive(:downcase).once
37
+
38
+ subject.load!
39
+
40
+ expect(subject.loaded).to be_eql(true)
41
+ end
42
+ end
43
+
44
+ context 'with dependencies failing' do
45
+ let(:dummy_object) { '' }
46
+ let(:plugin_proc) do
47
+ dummy = dummy_object
48
+
49
+ proc do
50
+ dependency do
51
+ true
52
+ end
53
+
54
+ dependency do
55
+ raise StandardError.new('the-error')
56
+ end
57
+
58
+ execute do
59
+ dummy.upcase
60
+ end
61
+
62
+ execute do
63
+ dummy.downcase
64
+ end
65
+ end
66
+ end
67
+
68
+ it 'doesnt finish loading the plugin' do
69
+ expect(dummy_object).not_to receive(:upcase)
70
+ expect(dummy_object).not_to receive(:downcase)
71
+ expect(Rollbar).to receive(:log_error).with("Error trying to load plugin 'plugin': StandardError, the-error")
72
+
73
+ subject.load!
74
+
75
+ expect(subject.loaded).to be_eql(false)
76
+ end
77
+ end
78
+
79
+ context 'with callables failing' do
80
+ let(:dummy_object) { '' }
81
+ let(:plugin_proc) do
82
+ dummy = dummy_object
83
+
84
+ proc do
85
+ dependency do
86
+ true
87
+ end
88
+
89
+ dependency do
90
+ 1 == 1.0
91
+ end
92
+
93
+ execute do
94
+ raise StandardError.new('the-error')
95
+ end
96
+
97
+ execute do
98
+ dummy.downcase
99
+ end
100
+ end
101
+ end
102
+
103
+ it 'doesnt finish loading the plugin' do
104
+ expect(dummy_object).not_to receive(:downcase)
105
+ expect(Rollbar).to receive(:log_error).with("Error trying to load plugin 'plugin': StandardError, the-error")
106
+
107
+ subject.load!
108
+
109
+ expect(subject.loaded).to be_eql(true)
110
+ end
111
+ end
112
+
113
+ context 'with false dependencies' do
114
+ let(:dummy_object) { '' }
115
+ let(:plugin_proc) do
116
+ dummy = dummy_object
117
+
118
+ proc do
119
+ dependency do
120
+ true
121
+ end
122
+
123
+ dependency do
124
+ 1 == 2.0
125
+ end
126
+
127
+ execute do
128
+ dummy.upcase
129
+ end
130
+
131
+ execute do
132
+ dummy.downcase
133
+ end
134
+ end
135
+ end
136
+
137
+ it 'calls the callables' do
138
+ expect(dummy_object).not_to receive(:upcase)
139
+ expect(dummy_object).not_to receive(:downcase)
140
+
141
+ subject.load!
142
+
143
+ expect(subject.loaded).to be_eql(false)
144
+ end
145
+ end
146
+ end
147
+ end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  require 'active_support/rescuable'
4
- require 'rollbar/active_job'
5
4
 
6
5
  describe Rollbar::ActiveJob do
7
6
  class TestJob
@@ -1,8 +1,10 @@
1
1
  require 'spec_helper'
2
+ require 'rollbar'
2
3
  require 'delayed_job'
3
- require 'rollbar/delayed_job'
4
4
  require 'delayed/backend/test'
5
5
 
6
+ Rollbar.plugins.load!
7
+
6
8
  describe Rollbar::Delayed, :reconfigure_notifier => true do
7
9
  class FailingJob
8
10
  class TestException < Exception; end
@@ -12,11 +14,6 @@ describe Rollbar::Delayed, :reconfigure_notifier => true do
12
14
  end
13
15
  end
14
16
 
15
- before(:all) do
16
- # technically, this is called once when rollbar hooks are required
17
- Rollbar::Delayed.wrap_worker!
18
- end
19
-
20
17
  before do
21
18
  Delayed::Backend::Test.prepare_worker
22
19
 
@@ -2,8 +2,9 @@ require 'spec_helper'
2
2
  require 'rack'
3
3
  require 'rack/builder'
4
4
  require 'rack/mock'
5
- require 'rollbar/middleware/rack/builder'
5
+ require 'rollbar'
6
6
 
7
+ Rollbar.plugins.load!
7
8
 
8
9
  describe Rollbar::Middleware::Rack::Builder, :reconfigure_notifier => true do
9
10
  class RackMockError < Exception; end
@@ -11,7 +11,7 @@ describe ApplicationController, :type => 'request' do
11
11
  it 'renders the snippet and config in the response', :type => 'request' do
12
12
  get '/test_rollbar_js'
13
13
 
14
- snippet_from_submodule = File.read(File.expand_path('../../../../../rollbar.js/dist/rollbar.snippet.js', __FILE__))
14
+ snippet_from_submodule = File.read(File.expand_path('../../../../rollbar.js/dist/rollbar.snippet.js', __FILE__))
15
15
 
16
16
  expect(response.body).to include("var _rollbarConfig = #{Rollbar::configuration.js_options.to_json};")
17
17
  expect(response.body).to include(snippet_from_submodule)
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
- require 'rollbar/rake'
2
+
3
+ Rollbar.plugins.load!
3
4
 
4
5
  describe Rollbar::Rake do
5
6
  let(:application) { Rake::Application.new }
@@ -2,9 +2,10 @@ require 'spec_helper'
2
2
 
3
3
  unless RUBY_VERSION == '1.8.7'
4
4
  require 'sidekiq'
5
- require 'rollbar/sidekiq'
6
5
  end
7
6
 
7
+ Rollbar.plugins.load!
8
+
8
9
  describe Rollbar::Sidekiq, :reconfigure_notifier => false do
9
10
  describe '.handle_exception' do
10
11
  let(:msg_or_context) { ['hello', 'error_backtrace', 'backtrace', 'goodbye'] }
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ require 'rollbar'
3
+
4
+ Rollbar.plugins.load!
5
+
6
+ describe Rollbar::ActiveRecordExtension do
7
+ it 'has the extensions loaded into ActiveRecord::Base' do
8
+ expect(ActiveModel::Validations.ancestors).to include(described_class)
9
+ expect(ActiveModel::Validations.instance_methods.map(&:to_sym)).to include(:report_validation_errors_to_rollbar)
10
+ end
11
+
12
+ context 'with an ActiveRecord::Base instance' do
13
+ let(:user) { User.new }
14
+
15
+ it 'calls report_validation_errors_to_rollbar' do
16
+ expect(user).to receive(:report_validation_errors_to_rollbar)
17
+
18
+ user.valid?
19
+ end
20
+ end
21
+
22
+ context 'with class using ActiveModel::Validations' do
23
+ let(:post) { Post.new }
24
+
25
+ it 'calls report_validation_errors_to_rollbar' do
26
+ expect(post).to receive(:report_validation_errors_to_rollbar)
27
+
28
+ post.valid?
29
+ end
30
+ end
31
+
32
+ describe '#report_validation_errors_to_rollbar', :reconfigure_notifier => true do
33
+ context 'having validation errors' do
34
+ let(:user) { User.new }
35
+
36
+ it 'send the errors to Rollbar' do
37
+ expect(Rollbar).to receive(:warning)
38
+
39
+ user.valid?
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+ require 'rollbar/plugins'
3
+ require 'rollbar/plugin'
4
+
5
+ describe Rollbar::Plugins do
6
+ let(:plugin_files_path) do
7
+ File.expand_path('../../fixtures/plugins/**/*.rb', __FILE__)
8
+ end
9
+ let!(:current_plugins) do
10
+ Rollbar.plugins
11
+ end
12
+
13
+ let(:plugin1_proc) do
14
+ proc do
15
+ dependency { true }
16
+ end
17
+ end
18
+
19
+ before do
20
+ Rollbar.plugins = nil
21
+ allow_any_instance_of(described_class).to receive(:plugin_files).and_return(plugin_files_path)
22
+ end
23
+
24
+ after do
25
+ Rollbar.plugins = current_plugins
26
+ end
27
+
28
+ describe '#require_all' do
29
+ it 'loads the plugins' do
30
+ expect(Rollbar.plugins).to receive(:define).with(:dummy1)
31
+ expect(Rollbar.plugins).to receive(:define).with(:dummy2)
32
+
33
+ subject.require_all
34
+ end
35
+ end
36
+
37
+ describe '#define' do
38
+ it 'evals the plugin DSL and adds it to the collection' do
39
+ expect_any_instance_of(Rollbar::Plugin).to receive(:dependency)
40
+ expect do
41
+ subject.define(:name, &plugin1_proc)
42
+ end.to change(subject.collection, :size).by(1)
43
+ end
44
+
45
+ context 'with a plugin already defined' do
46
+ it 'doesnt load the plugin twice' do
47
+ subject.define(:name, &plugin1_proc)
48
+
49
+ expect_any_instance_of(Rollbar::Plugin).not_to receive(:instance_eval)
50
+ expect do
51
+ subject.define(:name, &plugin1_proc)
52
+ end.to change(subject.collection, :size).by(0)
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#load!' do
58
+ before do
59
+ subject.define(:plugin1, &plugin1_proc)
60
+ end
61
+
62
+ it 'calls load! in the plugins' do
63
+ expect_any_instance_of(Rollbar::Plugin).to receive(:load!).once
64
+
65
+ subject.load!
66
+ end
67
+ end
68
+ end
@@ -14,18 +14,64 @@ describe Rollbar::RequestDataExtractor do
14
14
  Rack::MockRequest.env_for('/', 'HTTP_HOST' => 'localhost:81', 'HTTP_X_FORWARDED_HOST' => 'example.org:9292')
15
15
  end
16
16
 
17
- describe '#extract_request_data_from_rack' do
18
- let(:scrubber) { double }
17
+ describe '#scrub_url' do
18
+ let(:url) { 'http://this-is-the-url.com/foobar?param1=value1' }
19
+ let(:sensitive_params) { [:param1, :param2] }
20
+ let(:scrub_fields) { [:password, :secret] }
19
21
 
20
- it 'returns a Hash object' do
21
- scrubber_config = {
22
- :scrub_fields => kind_of(Array),
23
- :scrub_user => Rollbar.configuration.scrub_user,
24
- :scrub_password => Rollbar.configuration.scrub_password,
25
- :randomize_scrub_length => Rollbar.configuration.randomize_scrub_length
22
+ before do
23
+ allow(Rollbar.configuration).to receive(:scrub_fields).and_return(scrub_fields)
24
+ allow(Rollbar.configuration).to receive(:scrub_user).and_return(true)
25
+ allow(Rollbar.configuration).to receive(:scrub_password).and_return(true)
26
+ allow(Rollbar.configuration).to receive(:randomize_secret_length).and_return(true)
27
+ end
28
+
29
+ it 'calls the scrubber with the correct options' do
30
+ expected_options = {
31
+ :url => url,
32
+ :scrub_fields => [:password, :secret, :param1, :param2],
33
+ :scrub_user => true,
34
+ :scrub_password => true,
35
+ :randomize_scrub_length => true
36
+ }
37
+
38
+ expect(Rollbar::Scrubbers::URL).to receive(:call).with(expected_options)
39
+
40
+ subject.scrub_url(url, sensitive_params)
41
+ end
42
+ end
43
+
44
+ describe '#scrub_params' do
45
+ let(:params) do
46
+ {
47
+ :param1 => 'value1',
48
+ :param2 => 'value2'
49
+ }
50
+ end
51
+ let(:sensitive_params) { [:param1, :param2] }
52
+ let(:scrub_fields) { [:password, :secret] }
53
+
54
+ before do
55
+ allow(Rollbar.configuration).to receive(:scrub_fields).and_return(scrub_fields)
56
+ end
57
+
58
+ it 'calls the scrubber with the correct options' do
59
+ expected_options = {
60
+ :params => params,
61
+ :config => scrub_fields,
62
+ :extra_fields => sensitive_params
26
63
  }
27
- expect(Rollbar::Scrubbers::URL).to receive(:new).with(scrubber_config).and_return(scrubber)
28
- expect(scrubber).to receive(:call).with(kind_of(String))
64
+
65
+ expect(Rollbar::Scrubbers::Params).to receive(:call).with(expected_options)
66
+
67
+ subject.scrub_params(params, sensitive_params)
68
+ end
69
+ end
70
+
71
+ describe '#extract_request_data_from_rack' do
72
+ it 'returns a Hash object' do
73
+ expect(Rollbar::Scrubbers::URL).to receive(:call).with(kind_of(Hash)).and_call_original
74
+ expect(Rollbar::Scrubbers::Params).to receive(:call).with(kind_of(Hash)).and_call_original.exactly(7)
29
75
 
30
76
  result = subject.extract_request_data_from_rack(env)
31
77