rollbar 2.8.3 → 3.6.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 (238) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +18 -0
  3. data/.github/pull_request_template.md +34 -0
  4. data/.github/workflows/ci.yml +67 -0
  5. data/.gitignore +3 -1
  6. data/.rubocop.yml +206 -7
  7. data/Appraisals +10 -10
  8. data/CHANGELOG.md +257 -3
  9. data/Gemfile +74 -13
  10. data/README.md +38 -833
  11. data/Rakefile +0 -0
  12. data/THANKS.md +1 -0
  13. data/data/rollbar.snippet.js +1 -1
  14. data/docs/configuration.md +64 -3
  15. data/docs/plugins.md +46 -0
  16. data/gemfiles/rails50.gemfile +56 -0
  17. data/gemfiles/rails51.gemfile +57 -0
  18. data/gemfiles/rails52.gemfile +56 -0
  19. data/gemfiles/rails60.gemfile +52 -0
  20. data/gemfiles/rails61.gemfile +52 -0
  21. data/gemfiles/rails70.gemfile +52 -0
  22. data/gemfiles/rails71.gemfile +52 -0
  23. data/lib/generators/rollbar/rollbar_generator.rb +24 -20
  24. data/lib/generators/rollbar/templates/{initializer.rb → initializer.erb} +19 -5
  25. data/lib/rails/rollbar_runner.rb +26 -22
  26. data/lib/rollbar/capistrano.rb +78 -38
  27. data/lib/rollbar/capistrano3.rb +62 -1
  28. data/lib/rollbar/capistrano_tasks.rb +166 -0
  29. data/lib/rollbar/configuration.rb +291 -71
  30. data/lib/rollbar/delay/active_job.rb +17 -0
  31. data/lib/rollbar/delay/delayed_job.rb +23 -0
  32. data/lib/rollbar/delay/girl_friday.rb +4 -9
  33. data/lib/rollbar/delay/resque.rb +3 -6
  34. data/lib/rollbar/delay/shoryuken.rb +36 -0
  35. data/lib/rollbar/delay/sidekiq.rb +6 -8
  36. data/lib/rollbar/delay/sucker_punch.rb +17 -22
  37. data/lib/rollbar/delay/thread.rb +74 -3
  38. data/lib/rollbar/deploy.rb +91 -0
  39. data/lib/rollbar/encoding/encoder.rb +22 -11
  40. data/lib/rollbar/encoding.rb +2 -7
  41. data/lib/rollbar/exception_reporter.rb +36 -12
  42. data/lib/rollbar/item/backtrace.rb +118 -0
  43. data/lib/rollbar/item/frame.rb +121 -0
  44. data/lib/rollbar/item/locals.rb +103 -0
  45. data/lib/rollbar/item.rb +314 -0
  46. data/lib/rollbar/js.rb +0 -28
  47. data/lib/rollbar/json.rb +7 -55
  48. data/lib/rollbar/language_support.rb +7 -19
  49. data/lib/rollbar/lazy_store.rb +8 -12
  50. data/lib/rollbar/logger.rb +71 -0
  51. data/lib/rollbar/logger_proxy.rb +18 -1
  52. data/lib/rollbar/middleware/js/json_value.rb +36 -0
  53. data/lib/rollbar/middleware/js.rb +297 -0
  54. data/lib/rollbar/middleware/rack/builder.rb +4 -4
  55. data/lib/rollbar/middleware/rack/test_session.rb +4 -4
  56. data/lib/rollbar/middleware/rack.rb +52 -0
  57. data/lib/rollbar/middleware/rails/rollbar.rb +19 -7
  58. data/lib/rollbar/middleware/rails/show_exceptions.rb +21 -9
  59. data/lib/rollbar/middleware/sinatra.rb +2 -40
  60. data/lib/rollbar/notifier/trace_with_bindings.rb +75 -0
  61. data/lib/rollbar/notifier.rb +913 -0
  62. data/lib/rollbar/plugin.rb +126 -0
  63. data/lib/rollbar/plugins/active_job.rb +54 -0
  64. data/lib/rollbar/plugins/basic_socket.rb +31 -0
  65. data/lib/rollbar/plugins/delayed_job/job_data.rb +50 -0
  66. data/lib/rollbar/plugins/delayed_job/plugin.rb +88 -0
  67. data/lib/rollbar/plugins/delayed_job.rb +12 -0
  68. data/lib/rollbar/plugins/error_context.rb +11 -0
  69. data/lib/rollbar/plugins/goalie.rb +65 -0
  70. data/lib/rollbar/plugins/rack.rb +18 -0
  71. data/lib/rollbar/plugins/rails/controller_methods.rb +56 -0
  72. data/lib/rollbar/plugins/rails/error_subscriber.rb +12 -0
  73. data/lib/rollbar/plugins/rails/railtie30.rb +18 -0
  74. data/lib/rollbar/plugins/rails/railtie32.rb +18 -0
  75. data/lib/rollbar/plugins/rails/railtie_mixin.rb +37 -0
  76. data/lib/rollbar/plugins/rails.rb +89 -0
  77. data/lib/rollbar/plugins/rake.rb +73 -0
  78. data/lib/rollbar/plugins/resque/failure.rb +39 -0
  79. data/lib/rollbar/plugins/resque.rb +11 -0
  80. data/lib/rollbar/plugins/sidekiq/plugin.rb +77 -0
  81. data/lib/rollbar/plugins/sidekiq.rb +37 -0
  82. data/lib/rollbar/plugins/thread.rb +14 -0
  83. data/lib/rollbar/plugins/validations.rb +45 -0
  84. data/lib/rollbar/plugins.rb +47 -0
  85. data/lib/rollbar/rails.rb +0 -1
  86. data/lib/rollbar/rake_tasks.rb +4 -66
  87. data/lib/rollbar/request_data_extractor.rb +157 -117
  88. data/lib/rollbar/rollbar_test.rb +38 -0
  89. data/lib/rollbar/scrubbers/params.rb +133 -0
  90. data/lib/rollbar/scrubbers/url.rb +90 -35
  91. data/lib/rollbar/scrubbers.rb +13 -0
  92. data/lib/rollbar/truncation/frames_strategy.rb +2 -1
  93. data/lib/rollbar/truncation/min_body_strategy.rb +3 -4
  94. data/lib/rollbar/truncation/mixin.rb +1 -1
  95. data/lib/rollbar/truncation/remove_any_key_strategy.rb +126 -0
  96. data/lib/rollbar/truncation/remove_extra_strategy.rb +37 -0
  97. data/lib/rollbar/truncation/remove_request_strategy.rb +21 -0
  98. data/lib/rollbar/truncation/strings_strategy.rb +6 -5
  99. data/lib/rollbar/truncation.rb +10 -4
  100. data/lib/rollbar/util/hash.rb +37 -6
  101. data/lib/rollbar/util/ip_anonymizer.rb +33 -0
  102. data/lib/rollbar/util/ip_obfuscator.rb +1 -1
  103. data/lib/rollbar/util.rb +101 -55
  104. data/lib/rollbar/version.rb +1 -1
  105. data/lib/rollbar.rb +91 -879
  106. data/lib/tasks/benchmark.rake +104 -0
  107. data/lib/tasks/tasks.rake +3 -3
  108. data/rollbar.gemspec +21 -32
  109. data/spec/support/rollbar_api.rb +67 -0
  110. metadata +78 -439
  111. data/.travis.yml +0 -155
  112. data/gemfiles/rails30.gemfile +0 -20
  113. data/gemfiles/rails31.gemfile +0 -16
  114. data/gemfiles/rails32.gemfile +0 -17
  115. data/gemfiles/rails40.gemfile +0 -17
  116. data/gemfiles/rails41.gemfile +0 -15
  117. data/gemfiles/rails42.gemfile +0 -15
  118. data/lib/rollbar/active_job.rb +0 -11
  119. data/lib/rollbar/active_record_extension.rb +0 -14
  120. data/lib/rollbar/core_ext/basic_socket.rb +0 -7
  121. data/lib/rollbar/core_ext/thread.rb +0 -9
  122. data/lib/rollbar/delayed_job.rb +0 -78
  123. data/lib/rollbar/encoding/legacy_encoder.rb +0 -20
  124. data/lib/rollbar/goalie.rb +0 -33
  125. data/lib/rollbar/js/frameworks/rails.rb +0 -29
  126. data/lib/rollbar/js/frameworks.rb +0 -6
  127. data/lib/rollbar/js/middleware.rb +0 -129
  128. data/lib/rollbar/js/version.rb +0 -5
  129. data/lib/rollbar/json/default.rb +0 -11
  130. data/lib/rollbar/json/oj.rb +0 -15
  131. data/lib/rollbar/rack.rb +0 -9
  132. data/lib/rollbar/rails/controller_methods.rb +0 -40
  133. data/lib/rollbar/railtie.rb +0 -46
  134. data/lib/rollbar/rake.rb +0 -38
  135. data/lib/rollbar/sidekiq.rb +0 -40
  136. data/lib/rollbar/tasks/rollbar.cap +0 -45
  137. data/spec/cacert.pem +0 -3988
  138. data/spec/controllers/home_controller_spec.rb +0 -455
  139. data/spec/delay/sidekiq_spec.rb +0 -61
  140. data/spec/delay/sucker_punch_spec.rb +0 -25
  141. data/spec/delayed/backend/test.rb +0 -139
  142. data/spec/delayed/serialization/test.rb +0 -0
  143. data/spec/dummyapp/.gitignore +0 -73
  144. data/spec/dummyapp/Rakefile +0 -7
  145. data/spec/dummyapp/app/assets/javascripts/application.js +0 -3
  146. data/spec/dummyapp/app/assets/stylesheets/application.css.scss +0 -37
  147. data/spec/dummyapp/app/controllers/application_controller.rb +0 -3
  148. data/spec/dummyapp/app/controllers/home_controller.rb +0 -60
  149. data/spec/dummyapp/app/controllers/users_controller.rb +0 -17
  150. data/spec/dummyapp/app/helpers/.gitkeep +0 -0
  151. data/spec/dummyapp/app/mailers/.gitkeep +0 -0
  152. data/spec/dummyapp/app/models/.gitkeep +0 -0
  153. data/spec/dummyapp/app/models/user.rb +0 -7
  154. data/spec/dummyapp/app/views/devise/registrations/edit.html.erb +0 -27
  155. data/spec/dummyapp/app/views/devise/registrations/new.html.erb +0 -20
  156. data/spec/dummyapp/app/views/devise/shared/_links.html.erb +0 -25
  157. data/spec/dummyapp/app/views/home/cause_exception.html.erb +0 -1
  158. data/spec/dummyapp/app/views/home/index.html.erb +0 -4
  159. data/spec/dummyapp/app/views/home/report_exception.html.erb +0 -1
  160. data/spec/dummyapp/app/views/js/test.html.erb +0 -1
  161. data/spec/dummyapp/app/views/layouts/_messages.html.erb +0 -5
  162. data/spec/dummyapp/app/views/layouts/_navigation.html.erb +0 -21
  163. data/spec/dummyapp/app/views/layouts/application.html.erb +0 -25
  164. data/spec/dummyapp/app/views/layouts/simple.html.erb +0 -18
  165. data/spec/dummyapp/app/views/users/index.html.erb +0 -8
  166. data/spec/dummyapp/app/views/users/show.html.erb +0 -3
  167. data/spec/dummyapp/config/application.rb +0 -59
  168. data/spec/dummyapp/config/boot.rb +0 -10
  169. data/spec/dummyapp/config/database.yml +0 -25
  170. data/spec/dummyapp/config/environment.rb +0 -5
  171. data/spec/dummyapp/config/environments/development.rb +0 -37
  172. data/spec/dummyapp/config/environments/production.rb +0 -67
  173. data/spec/dummyapp/config/environments/test.rb +0 -37
  174. data/spec/dummyapp/config/initializers/backtrace_silencers.rb +0 -7
  175. data/spec/dummyapp/config/initializers/inflections.rb +0 -15
  176. data/spec/dummyapp/config/initializers/mime_types.rb +0 -5
  177. data/spec/dummyapp/config/initializers/rollbar.rb +0 -23
  178. data/spec/dummyapp/config/initializers/secret_token.rb +0 -7
  179. data/spec/dummyapp/config/initializers/session_store.rb +0 -8
  180. data/spec/dummyapp/config/initializers/wrap_parameters.rb +0 -16
  181. data/spec/dummyapp/config/locales/devise.en.yml +0 -58
  182. data/spec/dummyapp/config/locales/en.yml +0 -5
  183. data/spec/dummyapp/config/routes.rb +0 -17
  184. data/spec/dummyapp/config.ru +0 -4
  185. data/spec/dummyapp/db/migrate/20121121184652_devise_create_users.rb +0 -46
  186. data/spec/dummyapp/db/migrate/20121121184654_add_name_to_users.rb +0 -5
  187. data/spec/dummyapp/db/schema.rb +0 -35
  188. data/spec/dummyapp/db/seeds.rb +0 -12
  189. data/spec/dummyapp/lib/assets/.gitkeep +0 -0
  190. data/spec/dummyapp/public/404.html +0 -26
  191. data/spec/dummyapp/public/422.html +0 -26
  192. data/spec/dummyapp/public/500.html +0 -25
  193. data/spec/dummyapp/public/favicon.ico +0 -0
  194. data/spec/dummyapp/script/rails +0 -6
  195. data/spec/fixtures/file1 +0 -1
  196. data/spec/fixtures/file2 +0 -1
  197. data/spec/fixtures/payloads/message.json +0 -25
  198. data/spec/fixtures/payloads/sample.trace.json +0 -275
  199. data/spec/fixtures/payloads/sample.trace_chain.json +0 -530
  200. data/spec/generators/rollbar/rollbar_generator_spec.rb +0 -24
  201. data/spec/requests/home_spec.rb +0 -49
  202. data/spec/rollbar/active_job_spec.rb +0 -33
  203. data/spec/rollbar/configuration_spec.rb +0 -24
  204. data/spec/rollbar/delay/girl_friday_spec.rb +0 -41
  205. data/spec/rollbar/delay/resque_spec.rb +0 -37
  206. data/spec/rollbar/delay/thread_spec.rb +0 -27
  207. data/spec/rollbar/delayed_job/job_data.rb +0 -35
  208. data/spec/rollbar/delayed_job_spec.rb +0 -90
  209. data/spec/rollbar/encoding/encoder_spec.rb +0 -63
  210. data/spec/rollbar/js/frameworks/rails_spec.rb +0 -19
  211. data/spec/rollbar/js/middleware_spec.rb +0 -162
  212. data/spec/rollbar/json/oj_spec.rb +0 -18
  213. data/spec/rollbar/json_spec.rb +0 -110
  214. data/spec/rollbar/lazy_store_spec.rb +0 -99
  215. data/spec/rollbar/logger_proxy_spec.rb +0 -34
  216. data/spec/rollbar/middleware/rack/builder_spec.rb +0 -151
  217. data/spec/rollbar/middleware/sinatra_spec.rb +0 -197
  218. data/spec/rollbar/rake_spec.rb +0 -34
  219. data/spec/rollbar/request_data_extractor_spec.rb +0 -82
  220. data/spec/rollbar/scrubbers/url_spec.rb +0 -111
  221. data/spec/rollbar/sidekiq_spec.rb +0 -90
  222. data/spec/rollbar/truncation/frames_strategy_spec.rb +0 -70
  223. data/spec/rollbar/truncation/min_body_strategy_spec.rb +0 -57
  224. data/spec/rollbar/truncation/strings_strategy_spec.rb +0 -89
  225. data/spec/rollbar/truncation_spec.rb +0 -27
  226. data/spec/rollbar/util/hash_spec.rb +0 -22
  227. data/spec/rollbar/util_spec.rb +0 -19
  228. data/spec/rollbar_bc_spec.rb +0 -380
  229. data/spec/rollbar_spec.rb +0 -2067
  230. data/spec/spec_helper.rb +0 -49
  231. data/spec/support/cause_exception.rb +0 -1
  232. data/spec/support/encoding_helpers.rb +0 -8
  233. data/spec/support/encodings/iso_8859_9 +0 -1
  234. data/spec/support/fixture_helpers.rb +0 -10
  235. data/spec/support/get_ip_raising.rb +0 -7
  236. data/spec/support/helpers.rb +0 -5
  237. data/spec/support/notifier_helpers.rb +0 -36
  238. data/spec/support/shared_contexts.rb +0 -12
data/spec/rollbar_spec.rb DELETED
@@ -1,2067 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'logger'
4
- require 'socket'
5
- require 'girl_friday'
6
- require 'redis'
7
- require 'active_support/core_ext/object'
8
- require 'active_support/json/encoding'
9
-
10
- begin
11
- require 'sucker_punch'
12
- require 'sucker_punch/testing/inline'
13
- rescue LoadError
14
- end
15
-
16
- require 'spec_helper'
17
-
18
- describe Rollbar do
19
- let(:notifier) { Rollbar.notifier }
20
- before do
21
- Rollbar.unconfigure
22
- configure
23
- end
24
-
25
- context 'when notifier has been used before configure it' do
26
- before do
27
- Rollbar.unconfigure
28
- Rollbar.reset_notifier!
29
- end
30
-
31
- it 'is finally reset' do
32
- Rollbar.log_debug('Testing notifier')
33
- expect(Rollbar.error('error message')).to be_eql('disabled')
34
-
35
- reconfigure_notifier
36
-
37
- expect(Rollbar.error('error message')).not_to be_eql('disabled')
38
- end
39
- end
40
-
41
- context 'Notifier' do
42
- describe '#log' do
43
- let(:exception) do
44
- begin
45
- foo = bar
46
- rescue => e
47
- e
48
- end
49
- end
50
-
51
- let(:configuration) { Rollbar.configuration }
52
-
53
- context 'executing a Thread before Rollbar is configured' do
54
- before do
55
- Rollbar.reset_notifier!
56
- Rollbar.unconfigure
57
-
58
- Thread.new {}
59
-
60
- Rollbar.configure do |config|
61
- config.access_token = 'my-access-token'
62
- end
63
- end
64
-
65
- it 'sets correct configuration for Rollbar.notifier' do
66
- expect(Rollbar.notifier.configuration.enabled).to be_truthy
67
- end
68
- end
69
-
70
- it 'should report a simple message' do
71
- expect(notifier).to receive(:report).with('error', 'test message', nil, nil)
72
- notifier.log('error', 'test message')
73
- end
74
-
75
- it 'should report a simple message with extra data' do
76
- extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
77
-
78
- expect(notifier).to receive(:report).with('error', 'test message', nil, extra_data)
79
- notifier.log('error', 'test message', extra_data)
80
- end
81
-
82
- it 'should report an exception' do
83
- expect(notifier).to receive(:report).with('error', nil, exception, nil)
84
- notifier.log('error', exception)
85
- end
86
-
87
- it 'should report an exception with extra data' do
88
- extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
89
-
90
- expect(notifier).to receive(:report).with('error', nil, exception, extra_data)
91
- notifier.log('error', exception, extra_data)
92
- end
93
-
94
- it 'should report an exception with a description' do
95
- expect(notifier).to receive(:report).with('error', 'exception description', exception, nil)
96
- notifier.log('error', exception, 'exception description')
97
- end
98
-
99
- it 'should report an exception with a description and extra data' do
100
- extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
101
-
102
- expect(notifier).to receive(:report).with('error', 'exception description', exception, extra_data)
103
- notifier.log('error', exception, extra_data, 'exception description')
104
- end
105
- end
106
-
107
- context 'with before_process handlers in configuration' do
108
- let!(:notifier) { Rollbar::Notifier.new }
109
- let(:scope) { { :bar => :foo } }
110
- let(:configuration) do
111
- config = Rollbar::Configuration.new
112
- config.enabled = true
113
- config
114
- end
115
- let(:message) { 'message' }
116
- let(:exception) { Exception.new }
117
- let(:extra) { {:foo => :bar } }
118
- let(:level) { 'error' }
119
-
120
- before do
121
- notifier.configuration = configuration
122
- notifier.scope!(scope)
123
- end
124
-
125
- context 'without raise Rollbar::Ignore' do
126
- let(:handler) do
127
- proc do |options|
128
-
129
- end
130
- end
131
-
132
- before do
133
- configuration.before_process = handler
134
- end
135
-
136
- it 'calls the handler with the correct options' do
137
- options = {
138
- :level => level,
139
- :scope => Rollbar::LazyStore.new(scope),
140
- :exception => exception,
141
- :message => message,
142
- :extra => extra
143
- }
144
-
145
- expect(handler).to receive(:call).with(options)
146
- expect(notifier).to receive(:report).with(level, message, exception, extra)
147
-
148
- notifier.log(level, message, exception, extra)
149
- end
150
- end
151
-
152
- context 'raising Rollbar::Ignore in the handler' do
153
- let(:handler) do
154
- proc do |options|
155
- raise Rollbar::Ignore
156
- end
157
- end
158
-
159
- before do
160
- configuration.before_process = handler
161
- end
162
-
163
- it "calls the handler with correct options and doesn't call #report" do
164
- options = {
165
- :level => level,
166
- :scope => Rollbar::LazyStore.new(scope),
167
- :exception => exception,
168
- :message => message,
169
- :extra => extra
170
- }
171
- expect(handler).to receive(:call).with(options).and_call_original
172
- expect(notifier).not_to receive(:report)
173
-
174
- result = notifier.log(level, message, exception, extra)
175
-
176
- expect(result).to be_eql('ignored')
177
- end
178
- end
179
-
180
- context 'with 2 handlers, raising Rollbar::Ignore in the first one' do
181
- let(:handler1) do
182
- proc do |options|
183
- raise Rollbar::Ignore
184
- end
185
- end
186
-
187
- let(:handler2) do
188
- proc do |options|
189
-
190
- end
191
- end
192
-
193
- before do
194
- configuration.before_process << handler1
195
- configuration.before_process << handler2
196
- end
197
-
198
- it "calls only the first handler and doesn't calls #report" do
199
- options = {
200
- :level => level,
201
- :scope => Rollbar::LazyStore.new(scope),
202
- :exception => exception,
203
- :message => message,
204
- :extra => extra
205
- }
206
- expect(handler1).to receive(:call).with(options).and_call_original
207
- expect(handler2).not_to receive(:call)
208
- expect(notifier).not_to receive(:report)
209
-
210
- result = notifier.log(level, message, exception, extra)
211
-
212
- expect(result).to be_eql('ignored')
213
- end
214
-
215
- context 'if the first handler fails' do
216
- let(:exception) { StandardError.new('foo') }
217
- let(:handler1) do
218
- proc { |options| raise exception }
219
- end
220
-
221
- it 'doesnt call the second handler and logs the error' do
222
- expect(handler2).not_to receive(:call)
223
- expect(notifier).to receive(:log_error).with("[Rollbar] Error calling the `before_process` hook: #{exception}")
224
-
225
- notifier.log(level, message, exception, extra)
226
- end
227
- end
228
- end
229
- end
230
-
231
- context 'with transform handlers in configuration' do
232
- let!(:notifier) { Rollbar::Notifier.new }
233
- let(:scope) { { :bar => :foo } }
234
- let(:configuration) do
235
- config = Rollbar::Configuration.new
236
- config.enabled = true
237
- config
238
- end
239
- let(:message) { 'message' }
240
- let(:exception) { Exception.new }
241
- let(:extra) { {:foo => :bar } }
242
- let(:level) { 'error' }
243
-
244
- before do
245
- notifier.configuration = configuration
246
- notifier.scope!(scope)
247
- end
248
-
249
- context 'without mutation in payload' do
250
- let(:handler) do
251
- proc do |options|
252
-
253
- end
254
- end
255
-
256
- before do
257
- configuration.transform = handler
258
- end
259
-
260
- it 'calls the handler with the correct options' do
261
- options = {
262
- :level => level,
263
- :scope => Rollbar::LazyStore.new(scope),
264
- :exception => exception,
265
- :message => message,
266
- :extra => extra,
267
- :payload => kind_of(Hash)
268
- }
269
- expect(handler).to receive(:call).with(options).and_call_original
270
- expect(notifier).to receive(:schedule_payload).with(kind_of(Hash))
271
-
272
- notifier.log(level, message, exception, extra)
273
- end
274
- end
275
-
276
- context 'with mutation in payload' do
277
- let(:new_payload) do
278
- {
279
- 'access_token' => notifier.configuration.access_token,
280
- 'data' => {
281
- }
282
- }
283
- end
284
- let(:handler) do
285
- proc do |options|
286
- payload = options[:payload]
287
-
288
- payload.replace(new_payload)
289
- end
290
- end
291
-
292
- before do
293
- configuration.transform = handler
294
- end
295
-
296
- it 'calls the handler with the correct options' do
297
- options = {
298
- :level => level,
299
- :scope => Rollbar::LazyStore.new(scope),
300
- :exception => exception,
301
- :message => message,
302
- :extra => extra,
303
- :payload => kind_of(Hash)
304
- }
305
- expect(handler).to receive(:call).with(options).and_call_original
306
- expect(notifier).to receive(:schedule_payload).with(new_payload)
307
-
308
- notifier.log(level, message, exception, extra)
309
- end
310
- end
311
-
312
- context 'with two handlers' do
313
- let(:handler1) { proc { |options|} }
314
- let(:handler2) { proc { |options|} }
315
-
316
- before do
317
- configuration.transform << handler1
318
- configuration.transform << handler2
319
- end
320
-
321
- context 'and the first one fails' do
322
- let(:exception) { StandardError.new('foo') }
323
- let(:handler1) do
324
- proc { |options| raise exception }
325
- end
326
-
327
- it 'doesnt call the second handler and logs the error' do
328
- expect(handler2).not_to receive(:call)
329
- expect(notifier).to receive(:log_error).with("[Rollbar] Error calling the `transform` hook: #{exception}")
330
-
331
- notifier.log(level, message, exception, extra)
332
- end
333
- end
334
- end
335
- end
336
-
337
- context 'debug/info/warning/error/critical' do
338
- let(:exception) do
339
- begin
340
- foo = bar
341
- rescue => e
342
- e
343
- end
344
- end
345
-
346
- let(:extra_data) { {:key => 'value', :hash => {:inner_key => 'inner_value'}} }
347
-
348
- it 'should report with a debug level' do
349
- expect(notifier).to receive(:report).with('debug', nil, exception, nil)
350
- notifier.debug(exception)
351
-
352
- expect(notifier).to receive(:report).with('debug', 'description', exception, nil)
353
- notifier.debug(exception, 'description')
354
-
355
- expect(notifier).to receive(:report).with('debug', 'description', exception, extra_data)
356
- notifier.debug(exception, 'description', extra_data)
357
- end
358
-
359
- it 'should report with an info level' do
360
- expect(notifier).to receive(:report).with('info', nil, exception, nil)
361
- notifier.info(exception)
362
-
363
- expect(notifier).to receive(:report).with('info', 'description', exception, nil)
364
- notifier.info(exception, 'description')
365
-
366
- expect(notifier).to receive(:report).with('info', 'description', exception, extra_data)
367
- notifier.info(exception, 'description', extra_data)
368
- end
369
-
370
- it 'should report with a warning level' do
371
- expect(notifier).to receive(:report).with('warning', nil, exception, nil)
372
- notifier.warning(exception)
373
-
374
- expect(notifier).to receive(:report).with('warning', 'description', exception, nil)
375
- notifier.warning(exception, 'description')
376
-
377
- expect(notifier).to receive(:report).with('warning', 'description', exception, extra_data)
378
- notifier.warning(exception, 'description', extra_data)
379
- end
380
-
381
- it 'should report with an error level' do
382
- expect(notifier).to receive(:report).with('error', nil, exception, nil)
383
- notifier.error(exception)
384
-
385
- expect(notifier).to receive(:report).with('error', 'description', exception, nil)
386
- notifier.error(exception, 'description')
387
-
388
- expect(notifier).to receive(:report).with('error', 'description', exception, extra_data)
389
- notifier.error(exception, 'description', extra_data)
390
- end
391
-
392
- it 'should report with a critical level' do
393
- expect(notifier).to receive(:report).with('critical', nil, exception, nil)
394
- notifier.critical(exception)
395
-
396
- expect(notifier).to receive(:report).with('critical', 'description', exception, nil)
397
- notifier.critical(exception, 'description')
398
-
399
- expect(notifier).to receive(:report).with('critical', 'description', exception, extra_data)
400
- notifier.critical(exception, 'description', extra_data)
401
- end
402
- end
403
-
404
- context 'scope' do
405
- it 'should create a new notifier object' do
406
- notifier2 = notifier.scope
407
-
408
- notifier2.should_not eq(notifier)
409
- notifier2.should be_instance_of(Rollbar::Notifier)
410
- end
411
-
412
- it 'should create a copy of the parent notifier\'s configuration' do
413
- notifier.configure do |config|
414
- config.code_version = '123'
415
- config.payload_options = {
416
- :a => 'a',
417
- :b => {:c => 'c'}
418
- }
419
- end
420
-
421
- notifier2 = notifier.scope
422
-
423
- notifier2.configuration.code_version.should == '123'
424
- notifier2.configuration.should_not equal(notifier.configuration)
425
- notifier2.configuration.payload_options.should_not equal(notifier.configuration.payload_options)
426
- notifier2.configuration.payload_options.should == notifier.configuration.payload_options
427
- notifier2.configuration.payload_options.should == {
428
- :a => 'a',
429
- :b => {:c => 'c'}
430
- }
431
- end
432
-
433
- it 'should not modify any parent notifier configuration' do
434
- configure
435
- Rollbar.configuration.code_version.should be_nil
436
- Rollbar.configuration.payload_options.should be_empty
437
-
438
- notifier.configure do |config|
439
- config.code_version = '123'
440
- config.payload_options = {
441
- :a => 'a',
442
- :b => {:c => 'c'}
443
- }
444
- end
445
-
446
- notifier2 = notifier.scope
447
-
448
- notifier2.configure do |config|
449
- config.payload_options[:c] = 'c'
450
- end
451
-
452
- notifier.configuration.payload_options[:c].should be_nil
453
-
454
- notifier3 = notifier2.scope({
455
- :b => {:c => 3, :d => 'd'}
456
- })
457
-
458
- notifier3.configure do |config|
459
- config.code_version = '456'
460
- end
461
-
462
- notifier.configuration.code_version.should == '123'
463
- notifier.configuration.payload_options.should == {
464
- :a => 'a',
465
- :b => {:c => 'c'}
466
- }
467
- notifier2.configuration.code_version.should == '123'
468
- notifier2.configuration.payload_options.should == {
469
- :a => 'a',
470
- :b => {:c => 'c'},
471
- :c => 'c'
472
- }
473
- notifier3.configuration.code_version.should == '456'
474
- notifier3.configuration.payload_options.should == {
475
- :a => 'a',
476
- :b => {:c => 'c'},
477
- :c => 'c'
478
- }
479
-
480
- Rollbar.configuration.code_version.should be_nil
481
- Rollbar.configuration.payload_options.should be_empty
482
- end
483
- end
484
-
485
- context 'report' do
486
- let(:logger_mock) { double("Rails.logger").as_null_object }
487
-
488
- before(:each) do
489
- configure
490
- Rollbar.configure do |config|
491
- config.logger = logger_mock
492
- end
493
- end
494
-
495
- after(:each) do
496
- Rollbar.unconfigure
497
- configure
498
- end
499
-
500
- it 'should reject input that doesn\'t contain an exception, message or extra data' do
501
- expect(logger_mock).to receive(:error).with('[Rollbar] Tried to send a report with no message, exception or extra data.')
502
- expect(notifier).not_to receive(:schedule_payload)
503
-
504
- result = notifier.send(:report, 'info', nil, nil, nil)
505
- result.should == 'error'
506
- end
507
-
508
- it 'should be ignored if the person is ignored' do
509
- person_data = {
510
- :id => 1,
511
- :username => "test",
512
- :email => "test@example.com"
513
- }
514
-
515
- notifier.configure do |config|
516
- config.ignored_person_ids += [1]
517
- config.payload_options = { :person => person_data }
518
- end
519
-
520
- expect(notifier).not_to receive(:schedule_payload)
521
-
522
- result = notifier.send(:report, 'info', 'message', nil, nil)
523
- result.should == 'ignored'
524
- end
525
- end
526
-
527
- context 'build_payload' do
528
- context 'a basic payload' do
529
- let(:extra_data) { {:key => 'value', :hash => {:inner_key => 'inner_value'}} }
530
- let(:payload) { notifier.send(:build_payload, 'info', 'message', nil, extra_data) }
531
-
532
- it 'should have the correct root-level keys' do
533
- payload.keys.should match_array(['access_token', 'data'])
534
- end
535
-
536
- it 'should have the correct data keys' do
537
- payload['data'].keys.should include(:timestamp, :environment, :level, :language, :framework, :server,
538
- :notifier, :body)
539
- end
540
-
541
- it 'should have the correct notifier name and version' do
542
- payload['data'][:notifier][:name].should == 'rollbar-gem'
543
- payload['data'][:notifier][:version].should == Rollbar::VERSION
544
- end
545
-
546
- it 'should have the correct language and framework' do
547
- payload['data'][:language].should == 'ruby'
548
- payload['data'][:framework].should == Rollbar.configuration.framework
549
- payload['data'][:framework].should match(/^Rails/)
550
- end
551
-
552
- it 'should have the correct server keys' do
553
- payload['data'][:server].keys.should match_array([:host, :root, :pid])
554
- end
555
-
556
- it 'should have the correct level and message body' do
557
- payload['data'][:level].should == 'info'
558
- payload['data'][:body][:message][:body].should == 'message'
559
- end
560
- end
561
-
562
- it 'should merge in a new key from payload_options' do
563
- notifier.configure do |config|
564
- config.payload_options = { :some_new_key => 'some new value' }
565
- end
566
-
567
- payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
568
-
569
- payload['data'][:some_new_key].should == 'some new value'
570
- end
571
-
572
- it 'should overwrite existing keys from payload_options' do
573
- reconfigure_notifier
574
-
575
- payload_options = {
576
- :notifier => 'bad notifier',
577
- :server => { :host => 'new host', :new_server_key => 'value' }
578
- }
579
-
580
- notifier.configure do |config|
581
- config.payload_options = payload_options
582
- end
583
-
584
- payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
585
-
586
- payload['data'][:notifier].should == 'bad notifier'
587
- payload['data'][:server][:host].should == 'new host'
588
- payload['data'][:server][:root].should_not be_nil
589
- payload['data'][:server][:new_server_key].should == 'value'
590
- end
591
-
592
- it 'should have default environment "unspecified"' do
593
- Rollbar.unconfigure
594
- payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
595
- payload['data'][:environment].should == 'unspecified'
596
- end
597
-
598
- it 'should have an overridden environment' do
599
- Rollbar.configure do |config|
600
- config.environment = 'overridden'
601
- end
602
-
603
- payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
604
- payload['data'][:environment].should == 'overridden'
605
- end
606
-
607
- it 'should not have custom data under default configuration' do
608
- payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
609
- payload['data'][:body][:message][:extra].should be_nil
610
- end
611
-
612
- it 'should have custom message data when custom_data_method is configured' do
613
- Rollbar.configure do |config|
614
- config.custom_data_method = lambda { {:a => 1, :b => [2, 3, 4]} }
615
- end
616
-
617
- payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
618
- payload['data'][:body][:message][:extra].should_not be_nil
619
- payload['data'][:body][:message][:extra][:a].should == 1
620
- payload['data'][:body][:message][:extra][:b][2].should == 4
621
- end
622
-
623
- it 'should merge extra data into custom message data' do
624
- custom_method = lambda do
625
- { :a => 1,
626
- :b => [2, 3, 4],
627
- :c => { :d => 'd', :e => 'e' },
628
- :f => ['1', '2']
629
- }
630
- end
631
-
632
- Rollbar.configure do |config|
633
- config.custom_data_method = custom_method
634
- end
635
-
636
- payload = notifier.send(:build_payload, 'info', 'message', nil, {:c => {:e => 'g'}, :f => 'f'})
637
- payload['data'][:body][:message][:extra].should_not be_nil
638
- payload['data'][:body][:message][:extra][:a].should == 1
639
- payload['data'][:body][:message][:extra][:b][2].should == 4
640
- payload['data'][:body][:message][:extra][:c][:d].should == 'd'
641
- payload['data'][:body][:message][:extra][:c][:e].should == 'g'
642
- payload['data'][:body][:message][:extra][:f].should == 'f'
643
- end
644
-
645
- context 'with custom_data_method crashing' do
646
- next unless defined?(SecureRandom) and SecureRandom.respond_to?(:uuid)
647
-
648
- let(:crashing_exception) { StandardError.new }
649
- let(:custom_method) { proc { raise crashing_exception } }
650
- let(:extra) { { :foo => :bar } }
651
- let(:custom_data_report) do
652
- { :_error_in_custom_data_method => SecureRandom.uuid }
653
- end
654
- let(:expected_extra) { extra.merge(custom_data_report) }
655
-
656
- before do
657
- notifier.configure do |config|
658
- config.custom_data_method = custom_method
659
- end
660
- end
661
-
662
- it 'doesnt crash the report' do
663
- expect(notifier).to receive(:report_custom_data_error).once.and_return(custom_data_report)
664
- payload = notifier.send(:build_payload, 'info', 'message', nil, extra)
665
-
666
- expect(payload['data'][:body][:message][:extra]).to be_eql(expected_extra)
667
- end
668
-
669
- context 'and for some reason the safely.error returns a String' do
670
- it 'returns an empty Hash' do
671
- allow_any_instance_of(Rollbar::Notifier).to receive(:error).and_return('ignored')
672
-
673
- payload = notifier.send(:build_payload, 'info', 'message', nil, extra)
674
-
675
- expect(payload['data'][:body][:message][:extra]).to be_eql(extra)
676
- end
677
- end
678
- end
679
-
680
- it 'should include project_gem_paths' do
681
- notifier.configure do |config|
682
- config.project_gems = ['rails', 'rspec']
683
- end
684
-
685
- payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
686
-
687
- expect(payload['data'][:project_package_paths].count).to eq 2
688
- end
689
-
690
- it 'should include a code_version' do
691
- notifier.configure do |config|
692
- config.code_version = 'abcdef'
693
- end
694
-
695
- payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
696
-
697
- payload['data'][:code_version].should == 'abcdef'
698
- end
699
-
700
- it 'should have the right hostname' do
701
- payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
702
-
703
- payload['data'][:server][:host].should == Socket.gethostname
704
- end
705
-
706
- it 'should have root and branch set when configured' do
707
- configure
708
- Rollbar.configure do |config|
709
- config.root = '/path/to/root'
710
- config.branch = 'master'
711
- end
712
-
713
- payload = notifier.send(:build_payload, 'info', 'message', nil, nil)
714
-
715
- payload['data'][:server][:root].should == '/path/to/root'
716
- payload['data'][:server][:branch].should == 'master'
717
- end
718
-
719
- context "with Redis instance in payload and ActiveSupport is enabled" do
720
- let(:redis) { ::Redis.new }
721
- let(:payload) do
722
- {
723
- :key => {
724
- :value => redis
725
- }
726
- }
727
- end
728
- it 'dumps to JSON correctly' do
729
- redis.set('foo', 'bar')
730
- json = notifier.send(:dump_payload, payload)
731
-
732
- expect(json).to be_kind_of(String)
733
- end
734
- end
735
- end
736
-
737
- context 'build_payload_body' do
738
- let(:exception) do
739
- begin
740
- foo = bar
741
- rescue => e
742
- e
743
- end
744
- end
745
-
746
- it 'should build a message body when no exception is passed in' do
747
- body = notifier.send(:build_payload_body, 'message', nil, nil)
748
- body[:message][:body].should == 'message'
749
- body[:message][:extra].should be_nil
750
- body[:trace].should be_nil
751
- end
752
-
753
- it 'should build a message body when no exception and extra data is passed in' do
754
- body = notifier.send(:build_payload_body, 'message', nil, {:a => 'b'})
755
- body[:message][:body].should == 'message'
756
- body[:message][:extra].should == {:a => 'b'}
757
- body[:trace].should be_nil
758
- end
759
-
760
- it 'should build an exception body when one is passed in' do
761
- body = notifier.send(:build_payload_body, 'message', exception, nil)
762
- body[:message].should be_nil
763
-
764
- trace = body[:trace]
765
- trace.should_not be_nil
766
- trace[:extra].should be_nil
767
-
768
- trace[:exception][:class].should_not be_nil
769
- trace[:exception][:message].should_not be_nil
770
- end
771
-
772
- it 'should build an exception body when one is passed in along with extra data' do
773
- body = notifier.send(:build_payload_body, 'message', exception, {:a => 'b'})
774
- body[:message].should be_nil
775
-
776
- trace = body[:trace]
777
- trace.should_not be_nil
778
-
779
- trace[:exception][:class].should_not be_nil
780
- trace[:exception][:message].should_not be_nil
781
- trace[:extra].should == {:a => 'b'}
782
- end
783
- end
784
-
785
- context 'build_payload_body_exception' do
786
- let(:exception) do
787
- begin
788
- foo = bar
789
- rescue => e
790
- e
791
- end
792
- end
793
-
794
- after(:each) do
795
- Rollbar.unconfigure
796
- configure
797
- end
798
-
799
- it 'should build valid exception data' do
800
- body = notifier.send(:build_payload_body_exception, nil, exception, nil)
801
- body[:message].should be_nil
802
-
803
- trace = body[:trace]
804
-
805
- frames = trace[:frames]
806
- frames.should be_a_kind_of(Array)
807
- frames.each do |frame|
808
- frame[:filename].should be_a_kind_of(String)
809
- frame[:lineno].should be_a_kind_of(Fixnum)
810
- if frame[:method]
811
- frame[:method].should be_a_kind_of(String)
812
- end
813
- end
814
-
815
- # should be NameError, but can be NoMethodError sometimes on rubinius 1.8
816
- # http://yehudakatz.com/2010/01/02/the-craziest-fing-bug-ive-ever-seen/
817
- trace[:exception][:class].should match(/^(NameError|NoMethodError)$/)
818
- trace[:exception][:message].should match(/^(undefined local variable or method `bar'|undefined method `bar' on an instance of)/)
819
- end
820
-
821
- it 'should build exception data with a description' do
822
- body = notifier.send(:build_payload_body_exception, 'exception description', exception, nil)
823
-
824
- trace = body[:trace]
825
-
826
- trace[:exception][:message].should match(/^(undefined local variable or method `bar'|undefined method `bar' on an instance of)/)
827
- trace[:exception][:description].should == 'exception description'
828
- end
829
-
830
- it 'should build exception data with a description and extra data' do
831
- extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
832
- body = notifier.send(:build_payload_body_exception, 'exception description', exception, extra_data)
833
-
834
- trace = body[:trace]
835
-
836
- trace[:exception][:message].should match(/^(undefined local variable or method `bar'|undefined method `bar' on an instance of)/)
837
- trace[:exception][:description].should == 'exception description'
838
- trace[:extra][:key].should == 'value'
839
- trace[:extra][:hash].should == {:inner_key => 'inner_value'}
840
- end
841
-
842
- it 'should build exception data with a extra data' do
843
- extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
844
- body = notifier.send(:build_payload_body_exception, nil, exception, extra_data)
845
-
846
- trace = body[:trace]
847
-
848
- trace[:exception][:message].should match(/^(undefined local variable or method `bar'|undefined method `bar' on an instance of)/)
849
- trace[:extra][:key].should == 'value'
850
- trace[:extra][:hash].should == {:inner_key => 'inner_value'}
851
- end
852
-
853
- context 'with nested exceptions' do
854
- let(:crashing_code) do
855
- proc do
856
- begin
857
- begin
858
- fail CauseException.new('the cause')
859
- rescue
860
- fail StandardError.new('the error')
861
- end
862
- rescue => e
863
- e
864
- end
865
- end
866
- end
867
-
868
- let(:rescued_exception) { crashing_code.call }
869
- let(:message) { 'message' }
870
- let(:extra) { {} }
871
-
872
- context 'using ruby >= 2.1' do
873
- next unless Exception.instance_methods.include?(:cause)
874
-
875
- it 'sends the two exceptions in the trace_chain attribute' do
876
- body = notifier.send(:build_payload_body_exception, message, rescued_exception, extra)
877
-
878
- body[:trace].should be_nil
879
- body[:trace_chain].should be_kind_of(Array)
880
-
881
- chain = body[:trace_chain]
882
- chain[0][:exception][:class].should match(/StandardError/)
883
- chain[0][:exception][:message].should match(/the error/)
884
-
885
- chain[1][:exception][:class].should match(/CauseException/)
886
- chain[1][:exception][:message].should match(/the cause/)
887
- end
888
-
889
- it 'ignores the cause when it is not an Exception' do
890
- exception_with_custom_cause = Exception.new('custom cause')
891
- allow(exception_with_custom_cause).to receive(:cause) { "Foo" }
892
- body = notifier.send(:build_payload_body_exception, message, exception_with_custom_cause, extra)
893
- body[:trace].should_not be_nil
894
- end
895
-
896
- context 'with cyclic nested exceptions' do
897
- let(:exception1) { Exception.new('exception1') }
898
- let(:exception2) { Exception.new('exception2') }
899
-
900
- before do
901
- allow(exception1).to receive(:cause).and_return(exception2)
902
- allow(exception2).to receive(:cause).and_return(exception1)
903
- end
904
-
905
- it 'doesnt loop for ever' do
906
- body = notifier.send(:build_payload_body_exception, message, exception1, extra)
907
- chain = body[:trace_chain]
908
-
909
- expect(chain[0][:exception][:message]).to be_eql('exception1')
910
- expect(chain[1][:exception][:message]).to be_eql('exception2')
911
- end
912
- end
913
- end
914
-
915
- context 'using ruby <= 2.1' do
916
- next if Exception.instance_methods.include?(:cause)
917
-
918
- it 'sends only the last exception in the trace attribute' do
919
- body = notifier.send(:build_payload_body_exception, message, rescued_exception, extra)
920
-
921
- body[:trace].should be_kind_of(Hash)
922
- body[:trace_chain].should be_nil
923
-
924
- body[:trace][:exception][:class].should match(/StandardError/)
925
- body[:trace][:exception][:message].should match(/the error/)
926
- end
927
- end
928
- end
929
- end
930
-
931
- context 'build_payload_body_message' do
932
- it 'should build a message' do
933
- body = notifier.send(:build_payload_body_message, 'message', nil)
934
- body[:message][:body].should == 'message'
935
- body[:trace].should be_nil
936
- end
937
-
938
- it 'should build a message with extra data' do
939
- extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
940
- body = notifier.send(:build_payload_body_message, 'message', extra_data)
941
- body[:message][:body].should == 'message'
942
- body[:message][:extra][:key].should == 'value'
943
- body[:message][:extra][:hash].should == {:inner_key => 'inner_value'}
944
- end
945
-
946
- it 'should build an empty message with extra data' do
947
- extra_data = {:key => 'value', :hash => {:inner_key => 'inner_value'}}
948
- body = notifier.send(:build_payload_body_message, nil, extra_data)
949
- body[:message][:body].should == 'Empty message'
950
- body[:message][:extra][:key].should == 'value'
951
- body[:message][:extra][:hash].should == {:inner_key => 'inner_value'}
952
- end
953
- end
954
- end
955
-
956
- context 'reporting' do
957
- let(:exception) do
958
- begin
959
- foo = bar
960
- rescue => e
961
- e
962
- end
963
- end
964
-
965
- let(:logger_mock) { double("Rails.logger").as_null_object }
966
- let(:user) { User.create(:email => 'email@example.com', :encrypted_password => '', :created_at => Time.now, :updated_at => Time.now) }
967
-
968
- before(:each) do
969
- configure
970
- Rollbar.configure do |config|
971
- config.logger = logger_mock
972
- end
973
- end
974
-
975
- after(:each) do
976
- Rollbar.unconfigure
977
- configure
978
- end
979
-
980
- it 'should report exceptions without person or request data' do
981
- logger_mock.should_receive(:info).with('[Rollbar] Success')
982
- Rollbar.error(exception)
983
- end
984
-
985
- it 'should not report anything when disabled' do
986
- logger_mock.should_not_receive(:info).with('[Rollbar] Success')
987
-
988
- Rollbar.configure do |config|
989
- config.enabled = false
990
- end
991
-
992
- Rollbar.error(exception).should == 'disabled'
993
- end
994
-
995
- it 'should report exceptions without person or request data' do
996
- logger_mock.should_receive(:info).with('[Rollbar] Success')
997
- Rollbar.error(exception)
998
- end
999
-
1000
- it 'should be enabled when freshly configured' do
1001
- Rollbar.configuration.enabled.should == true
1002
- end
1003
-
1004
- it 'should not be enabled when not configured' do
1005
- Rollbar.unconfigure
1006
-
1007
- Rollbar.configuration.enabled.should be_nil
1008
- Rollbar.error(exception).should == 'disabled'
1009
- end
1010
-
1011
- it 'should stay disabled if configure is called again' do
1012
- Rollbar.unconfigure
1013
-
1014
- # configure once, setting enabled to false.
1015
- Rollbar.configure do |config|
1016
- config.enabled = false
1017
- end
1018
-
1019
- # now configure again (perhaps to change some other values)
1020
- Rollbar.configure do |config| end
1021
-
1022
- Rollbar.configuration.enabled.should == false
1023
- Rollbar.error(exception).should == 'disabled'
1024
- end
1025
-
1026
- context 'using :use_exception_level_filters option as true' do
1027
- it 'sends the correct filtered level' do
1028
- Rollbar.configure do |config|
1029
- config.exception_level_filters = { 'NameError' => 'warning' }
1030
- end
1031
-
1032
- Rollbar.error(exception, :use_exception_level_filters => true)
1033
- expect(Rollbar.last_report[:level]).to be_eql('warning')
1034
- end
1035
-
1036
- it 'ignore ignored exception classes' do
1037
- Rollbar.configure do |config|
1038
- config.exception_level_filters = { 'NameError' => 'ignore' }
1039
- end
1040
-
1041
- logger_mock.should_not_receive(:info)
1042
- logger_mock.should_not_receive(:warn)
1043
- logger_mock.should_not_receive(:error)
1044
-
1045
- Rollbar.error(exception, :use_exception_level_filters => true)
1046
- end
1047
- end
1048
-
1049
- context 'if not using :use_exception_level_filters option' do
1050
- it 'sends the level defined by the used method' do
1051
- Rollbar.configure do |config|
1052
- config.exception_level_filters = { 'NameError' => 'warning' }
1053
- end
1054
-
1055
- Rollbar.error(exception)
1056
- expect(Rollbar.last_report[:level]).to be_eql('error')
1057
- end
1058
-
1059
- it 'ignore ignored exception classes' do
1060
- Rollbar.configure do |config|
1061
- config.exception_level_filters = { 'NameError' => 'ignore' }
1062
- end
1063
-
1064
- Rollbar.error(exception)
1065
-
1066
- expect(Rollbar.last_report[:level]).to be_eql('error')
1067
- end
1068
- end
1069
-
1070
- # Skip jruby 1.9+ (https://github.com/jruby/jruby/issues/2373)
1071
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' && (not RUBY_VERSION =~ /^1\.9/)
1072
- it "should work with an IO object as rack.errors" do
1073
- logger_mock.should_receive(:info).with('[Rollbar] Success')
1074
-
1075
- Rollbar.error(exception, :env => { :"rack.errors" => IO.new(2, File::WRONLY) })
1076
- end
1077
- end
1078
-
1079
- it 'should ignore ignored persons' do
1080
- person_data = {
1081
- :id => 1,
1082
- :username => "test",
1083
- :email => "test@example.com"
1084
- }
1085
-
1086
- Rollbar.configure do |config|
1087
- config.payload_options = {:person => person_data}
1088
- config.ignored_person_ids += [1]
1089
- end
1090
-
1091
- logger_mock.should_not_receive(:info)
1092
- logger_mock.should_not_receive(:warn)
1093
- logger_mock.should_not_receive(:error)
1094
-
1095
- Rollbar.error(exception)
1096
- end
1097
-
1098
- it 'should not ignore non-ignored persons' do
1099
- person_data = {
1100
- :id => 1,
1101
- :username => "test",
1102
- :email => "test@example.com"
1103
- }
1104
- Rollbar.configure do |config|
1105
- config.payload_options = { :person => person_data }
1106
- config.ignored_person_ids += [1]
1107
- end
1108
-
1109
- Rollbar.last_report = nil
1110
-
1111
- Rollbar.error(exception)
1112
- Rollbar.last_report.should be_nil
1113
-
1114
- person_data = {
1115
- :id => 2,
1116
- :username => "test2",
1117
- :email => "test2@example.com"
1118
- }
1119
-
1120
- new_options = {
1121
- :person => person_data
1122
- }
1123
-
1124
- Rollbar.scoped(new_options) do
1125
- Rollbar.error(exception)
1126
- end
1127
-
1128
- Rollbar.last_report.should_not be_nil
1129
- end
1130
-
1131
- it 'should allow callables to set exception filtered level' do
1132
- callable_mock = double
1133
- saved_filters = Rollbar.configuration.exception_level_filters
1134
-
1135
- Rollbar.configure do |config|
1136
- config.exception_level_filters = { 'NameError' => callable_mock }
1137
- end
1138
-
1139
- callable_mock.should_receive(:call).with(exception).at_least(:once).and_return("info")
1140
- logger_mock.should_receive(:info)
1141
- logger_mock.should_not_receive(:warn)
1142
- logger_mock.should_not_receive(:error)
1143
-
1144
- Rollbar.error(exception, :use_exception_level_filters => true)
1145
- end
1146
-
1147
- it 'should not report exceptions when silenced' do
1148
- expect_any_instance_of(Rollbar::Notifier).to_not receive(:schedule_payload)
1149
-
1150
- begin
1151
- test_var = 1
1152
- Rollbar.silenced do
1153
- test_var = 2
1154
- raise
1155
- end
1156
- rescue => e
1157
- Rollbar.error(e)
1158
- end
1159
-
1160
- test_var.should == 2
1161
- end
1162
-
1163
- it 'should report exception objects with no backtrace' do
1164
- payload = nil
1165
-
1166
- notifier.stub(:schedule_payload) do |*args|
1167
- payload = args[0]
1168
- end
1169
-
1170
- Rollbar.error(StandardError.new("oops"))
1171
-
1172
- payload["data"][:body][:trace][:frames].should == []
1173
- payload["data"][:body][:trace][:exception][:class].should == "StandardError"
1174
- payload["data"][:body][:trace][:exception][:message].should == "oops"
1175
- end
1176
-
1177
- it 'gets the backtrace from the caller' do
1178
- Rollbar.configure do |config|
1179
- config.populate_empty_backtraces = true
1180
- end
1181
-
1182
- exception = Exception.new
1183
-
1184
- Rollbar.error(exception)
1185
-
1186
- gem_dir = Gem::Specification.find_by_name('rollbar').gem_dir
1187
- gem_lib_dir = gem_dir + '/lib'
1188
- last_report = Rollbar.last_report
1189
-
1190
- filepaths = last_report[:body][:trace][:frames].map {|frame| frame[:filename] }.reverse
1191
-
1192
- expect(filepaths[0]).not_to include(gem_lib_dir)
1193
- expect(filepaths.any? {|filepath| filepath.include?(gem_dir) }).to eq true
1194
- end
1195
-
1196
- it 'should return the exception data with a uuid, on platforms with SecureRandom' do
1197
- if defined?(SecureRandom) and SecureRandom.respond_to?(:uuid)
1198
- exception_data = Rollbar.error(StandardError.new("oops"))
1199
- exception_data[:uuid].should_not be_nil
1200
- end
1201
- end
1202
-
1203
- it 'should report exception objects with nonstandard backtraces' do
1204
- payload = nil
1205
-
1206
- notifier.stub(:schedule_payload) do |*args|
1207
- payload = args[0]
1208
- end
1209
-
1210
- class CustomException < StandardError
1211
- def backtrace
1212
- ["custom backtrace line"]
1213
- end
1214
- end
1215
-
1216
- exception = CustomException.new("oops")
1217
-
1218
- notifier.error(exception)
1219
-
1220
- payload["data"][:body][:trace][:frames][0][:method].should == "custom backtrace line"
1221
- end
1222
-
1223
- it 'should report exceptions with a custom level' do
1224
- payload = nil
1225
-
1226
- notifier.stub(:schedule_payload) do |*args|
1227
- payload = args[0]
1228
- end
1229
-
1230
- Rollbar.error(exception)
1231
-
1232
- payload['data'][:level].should == 'error'
1233
-
1234
- Rollbar.log('debug', exception)
1235
-
1236
- payload['data'][:level].should == 'debug'
1237
- end
1238
-
1239
- context 'with invalid utf8 encoding' do
1240
- let(:extra) do
1241
- { :extra => force_to_ascii("bad value 1\255") }
1242
- end
1243
-
1244
- it 'removes te invalid characteres' do
1245
- Rollbar.info('removing invalid chars', extra)
1246
-
1247
- extra_value = Rollbar.last_report[:body][:message][:extra][:extra]
1248
- expect(extra_value).to be_eql('bad value 1')
1249
- end
1250
- end
1251
- end
1252
-
1253
- # Backwards
1254
- context 'report_message' do
1255
- before(:each) do
1256
- configure
1257
- Rollbar.configure do |config|
1258
- config.logger = logger_mock
1259
- end
1260
- end
1261
-
1262
- let(:logger_mock) { double("Rails.logger").as_null_object }
1263
- let(:user) { User.create(:email => 'email@example.com', :encrypted_password => '', :created_at => Time.now, :updated_at => Time.now) }
1264
-
1265
- it 'should report simple messages' do
1266
- logger_mock.should_receive(:info).with('[Rollbar] Scheduling payload')
1267
- logger_mock.should_receive(:info).with('[Rollbar] Success')
1268
- Rollbar.error('Test message')
1269
- end
1270
-
1271
- it 'should not report anything when disabled' do
1272
- logger_mock.should_not_receive(:info).with('[Rollbar] Success')
1273
- Rollbar.configure do |config|
1274
- config.enabled = false
1275
- end
1276
-
1277
- Rollbar.error('Test message that should be ignored')
1278
-
1279
- Rollbar.configure do |config|
1280
- config.enabled = true
1281
- end
1282
- end
1283
-
1284
- it 'should report messages with extra data' do
1285
- logger_mock.should_receive(:info).with('[Rollbar] Success')
1286
- Rollbar.debug('Test message with extra data', 'debug', :foo => "bar",
1287
- :hash => { :a => 123, :b => "xyz" })
1288
- end
1289
-
1290
- # END Backwards
1291
-
1292
- it 'should not crash with circular extra_data' do
1293
- a = { :foo => "bar" }
1294
- b = { :a => a }
1295
- c = { :b => b }
1296
- a[:c] = c
1297
-
1298
- logger_mock.should_receive(:error).with(/\[Rollbar\] Reporting internal error encountered while sending data to Rollbar./)
1299
-
1300
- Rollbar.error("Test message with circular extra data", a)
1301
- end
1302
-
1303
- it 'should be able to report form validation errors when they are present' do
1304
- logger_mock.should_receive(:info).with('[Rollbar] Success')
1305
- user.errors.add(:example, "error")
1306
- user.report_validation_errors_to_rollbar
1307
- end
1308
-
1309
- it 'should not report form validation errors when they are not present' do
1310
- logger_mock.should_not_receive(:info).with('[Rollbar] Success')
1311
- user.errors.clear
1312
- user.report_validation_errors_to_rollbar
1313
- end
1314
-
1315
- it 'should report messages with extra data' do
1316
- logger_mock.should_receive(:info).with('[Rollbar] Success')
1317
- Rollbar.info("Test message with extra data", :foo => "bar",
1318
- :hash => { :a => 123, :b => "xyz" })
1319
- end
1320
-
1321
- it 'should report messages with request, person data and extra data' do
1322
- logger_mock.should_receive(:info).with('[Rollbar] Scheduling payload')
1323
- logger_mock.should_receive(:info).with('[Rollbar] Success')
1324
-
1325
- request_data = {
1326
- :params => {:foo => 'bar'}
1327
- }
1328
-
1329
- person_data = {
1330
- :id => 123,
1331
- :username => 'username'
1332
- }
1333
-
1334
- extra_data = {
1335
- :extra_foo => 'extra_bar'
1336
- }
1337
-
1338
- Rollbar.configure do |config|
1339
- config.payload_options = {
1340
- :request => request_data,
1341
- :person => person_data
1342
- }
1343
- end
1344
-
1345
- Rollbar.info("Test message", extra_data)
1346
-
1347
- Rollbar.last_report[:request].should == request_data
1348
- Rollbar.last_report[:person].should == person_data
1349
- Rollbar.last_report[:body][:message][:extra][:extra_foo].should == 'extra_bar'
1350
- end
1351
- end
1352
-
1353
- context 'payload_destination' do
1354
- before(:each) do
1355
- configure
1356
- Rollbar.configure do |config|
1357
- config.logger = logger_mock
1358
- config.filepath = 'test.rollbar'
1359
- end
1360
- end
1361
-
1362
- after(:each) do
1363
- Rollbar.unconfigure
1364
- configure
1365
- end
1366
-
1367
- let(:exception) do
1368
- begin
1369
- foo = bar
1370
- rescue => e
1371
- e
1372
- end
1373
- end
1374
-
1375
- let(:logger_mock) { double("Rails.logger").as_null_object }
1376
-
1377
- it 'should send the payload over the network by default' do
1378
- logger_mock.should_not_receive(:info).with('[Rollbar] Writing payload to file')
1379
- logger_mock.should_receive(:info).with('[Rollbar] Sending payload').once
1380
- logger_mock.should_receive(:info).with('[Rollbar] Success').once
1381
- Rollbar.error(exception)
1382
- end
1383
-
1384
- it 'should save the payload to a file if set' do
1385
- logger_mock.should_not_receive(:info).with('[Rollbar] Sending payload')
1386
- logger_mock.should_receive(:info).with('[Rollbar] Writing payload to file').once
1387
- logger_mock.should_receive(:info).with('[Rollbar] Success').once
1388
-
1389
- filepath = ''
1390
-
1391
- Rollbar.configure do |config|
1392
- config.write_to_file = true
1393
- filepath = config.filepath
1394
- end
1395
-
1396
- Rollbar.error(exception)
1397
-
1398
- File.exist?(filepath).should == true
1399
- File.read(filepath).should include test_access_token
1400
- File.delete(filepath)
1401
-
1402
- Rollbar.configure do |config|
1403
- config.write_to_file = false
1404
- end
1405
- end
1406
- end
1407
-
1408
- context 'asynchronous_handling' do
1409
- before(:each) do
1410
- configure
1411
- Rollbar.configure do |config|
1412
- config.logger = logger_mock
1413
- end
1414
- end
1415
-
1416
- after(:each) do
1417
- Rollbar.unconfigure
1418
- configure
1419
- end
1420
-
1421
- let(:exception) do
1422
- begin
1423
- foo = bar
1424
- rescue => e
1425
- e
1426
- end
1427
- end
1428
-
1429
- let(:logger_mock) { double("Rails.logger").as_null_object }
1430
-
1431
- it 'should send the payload using the default asynchronous handler girl_friday' do
1432
- logger_mock.should_receive(:info).with('[Rollbar] Scheduling payload')
1433
- logger_mock.should_receive(:info).with('[Rollbar] Sending payload')
1434
- logger_mock.should_receive(:info).with('[Rollbar] Success')
1435
-
1436
- Rollbar.configure do |config|
1437
- config.use_async = true
1438
- GirlFriday::WorkQueue.immediate!
1439
- end
1440
-
1441
- Rollbar.error(exception)
1442
-
1443
- Rollbar.configure do |config|
1444
- config.use_async = false
1445
- GirlFriday::WorkQueue.queue!
1446
- end
1447
- end
1448
-
1449
- it 'should send the payload using a user-supplied asynchronous handler' do
1450
- logger_mock.should_receive(:info).with('Custom async handler called')
1451
- logger_mock.should_receive(:info).with('[Rollbar] Sending payload')
1452
- logger_mock.should_receive(:info).with('[Rollbar] Success')
1453
-
1454
- Rollbar.configure do |config|
1455
- config.use_async = true
1456
- config.async_handler = Proc.new { |payload|
1457
- logger_mock.info 'Custom async handler called'
1458
- Rollbar.process_payload(payload)
1459
- }
1460
- end
1461
-
1462
- Rollbar.error(exception)
1463
- end
1464
-
1465
- # We should be able to send String payloads, generated
1466
- # by a previous version of the gem. This can happend just
1467
- # after a deploy with an gem upgrade.
1468
- context 'with a payload generated as String' do
1469
- let(:async_handler) do
1470
- proc do |payload|
1471
- # simulate previous gem version
1472
- string_payload = Rollbar::JSON.dump(payload)
1473
-
1474
- Rollbar.process_payload(string_payload)
1475
- end
1476
- end
1477
-
1478
- before do
1479
- Rollbar.configuration.stub(:use_async).and_return(true)
1480
- Rollbar.configuration.stub(:async_handler).and_return(async_handler)
1481
- end
1482
-
1483
- it 'sends a payload generated as String, not as a Hash' do
1484
- logger_mock.should_receive(:info).with('[Rollbar] Success')
1485
-
1486
- Rollbar.error(exception)
1487
- end
1488
-
1489
- context 'with async failover handlers' do
1490
- before do
1491
- Rollbar.reconfigure do |config|
1492
- config.use_async = true
1493
- config.async_handler = async_handler
1494
- config.failover_handlers = handlers
1495
- config.logger = logger_mock
1496
- end
1497
- end
1498
-
1499
- let(:exception) { StandardError.new('the error') }
1500
-
1501
- context 'if the async handler doesnt fail' do
1502
- let(:async_handler) { proc { |_| 'success' } }
1503
- let(:handler) { proc { |_| 'success' } }
1504
- let(:handlers) { [handler] }
1505
-
1506
- it 'doesnt call any failover handler' do
1507
- expect(handler).not_to receive(:call)
1508
-
1509
- Rollbar.error(exception)
1510
- end
1511
- end
1512
-
1513
- context 'if the async handler fails' do
1514
- let(:async_handler) { proc { |_| fail 'this handler will crash' } }
1515
-
1516
- context 'if any failover handlers is configured' do
1517
- let(:handlers) { [] }
1518
- let(:log_message) do
1519
- '[Rollbar] Async handler failed, and there are no failover handlers configured. See the docs for "failover_handlers"'
1520
- end
1521
-
1522
- it 'logs the error but doesnt try to report an internal error' do
1523
- expect(logger_mock).to receive(:error).with(log_message)
1524
-
1525
- Rollbar.error(exception)
1526
- end
1527
- end
1528
-
1529
- context 'if the first failover handler success' do
1530
- let(:handler) { proc { |_| 'success' } }
1531
- let(:handlers) { [handler] }
1532
-
1533
- it 'calls the failover handler and doesnt report internal error' do
1534
- expect(Rollbar).not_to receive(:report_internal_error)
1535
- expect(handler).to receive(:call)
1536
-
1537
- Rollbar.error(exception)
1538
- end
1539
- end
1540
-
1541
- context 'with two handlers, the first failing' do
1542
- let(:handler1) { proc { |_| fail 'this handler fails' } }
1543
- let(:handler2) { proc { |_| 'success' } }
1544
- let(:handlers) { [handler1, handler2] }
1545
-
1546
- it 'calls the second handler and doesnt report internal error' do
1547
- expect(handler2).to receive(:call)
1548
-
1549
- Rollbar.error(exception)
1550
- end
1551
- end
1552
-
1553
- context 'with two handlers, both failing' do
1554
- let(:handler1) { proc { |_| fail 'this handler fails' } }
1555
- let(:handler2) { proc { |_| fail 'this will also fail' } }
1556
- let(:handlers) { [handler1, handler2] }
1557
-
1558
- it 'reports internal error' do
1559
- expect(logger_mock).to receive(:error)
1560
-
1561
- Rollbar.error(exception)
1562
- end
1563
- end
1564
- end
1565
- end
1566
- end
1567
-
1568
- describe "#use_sucker_punch", :if => defined?(SuckerPunch) do
1569
- it "should send the payload to sucker_punch delayer" do
1570
- logger_mock.should_receive(:info).with('[Rollbar] Scheduling payload')
1571
- logger_mock.should_receive(:info).with('[Rollbar] Sending payload')
1572
- logger_mock.should_receive(:info).with('[Rollbar] Success')
1573
-
1574
- Rollbar.configure do |config|
1575
- config.use_sucker_punch
1576
- end
1577
-
1578
- Rollbar.error(exception)
1579
- end
1580
- end
1581
-
1582
- describe "#use_sidekiq", :if => defined?(Sidekiq) do
1583
- it "should instanciate sidekiq delayer with custom values" do
1584
- Rollbar::Delay::Sidekiq.should_receive(:new).with('queue' => 'test_queue')
1585
- config = Rollbar::Configuration.new
1586
- config.use_sidekiq 'queue' => 'test_queue'
1587
- end
1588
-
1589
- it "should send the payload to sidekiq delayer" do
1590
- handler = double('sidekiq_handler_mock')
1591
- handler.should_receive(:call)
1592
-
1593
- Rollbar.configure do |config|
1594
- config.use_sidekiq
1595
- config.async_handler = handler
1596
- end
1597
-
1598
- Rollbar.error(exception)
1599
- end
1600
- end
1601
- end
1602
-
1603
- context 'logger' do
1604
- before(:each) do
1605
- reset_configuration
1606
- end
1607
-
1608
- it 'should have use the Rails logger when configured to do so' do
1609
- configure
1610
- expect(Rollbar.send(:logger)).to be_kind_of(Rollbar::LoggerProxy)
1611
- expect(Rollbar.send(:logger).object).to eq ::Rails.logger
1612
- end
1613
-
1614
- it 'should use the default_logger when no logger is set' do
1615
- logger = Logger.new(STDERR)
1616
-
1617
- Rollbar.configure do |config|
1618
- config.default_logger = lambda { logger }
1619
- end
1620
-
1621
- Rollbar.send(:logger).object.should == logger
1622
- end
1623
-
1624
- it 'should have a default default_logger' do
1625
- Rollbar.send(:logger).should_not be_nil
1626
- end
1627
-
1628
- after(:each) do
1629
- reset_configuration
1630
- end
1631
- end
1632
-
1633
- context 'enforce_valid_utf8' do
1634
- # TODO(jon): all these tests should be removed since they are in
1635
- # in spec/rollbar/encoding/encoder.rb.
1636
- #
1637
- # This should just check that in payload with simple values and
1638
- # nested values are each one passed through Rollbar::Encoding.encode
1639
- context 'with utf8 string and ruby > 1.8' do
1640
- next unless String.instance_methods.include?(:force_encoding)
1641
-
1642
- let(:payload) { { :foo => 'Изменение' } }
1643
-
1644
- it 'just returns the same string' do
1645
- payload_copy = payload.clone
1646
- notifier.send(:enforce_valid_utf8, payload_copy)
1647
-
1648
- expect(payload_copy[:foo]).to be_eql('Изменение')
1649
- end
1650
- end
1651
-
1652
- it 'should replace invalid utf8 values' do
1653
- bad_key = force_to_ascii("inner \x92bad key")
1654
-
1655
- payload = {
1656
- :bad_value => force_to_ascii("bad value 1\255"),
1657
- :bad_value_2 => force_to_ascii("bad\255 value 2"),
1658
- force_to_ascii("bad\255 key") => "good value",
1659
- :hash => {
1660
- :inner_bad_value => force_to_ascii("\255\255bad value 3"),
1661
- bad_key.to_sym => 'inner good value',
1662
- force_to_ascii("bad array key\255") => [
1663
- 'good array value 1',
1664
- force_to_ascii("bad\255 array value 1\255"),
1665
- {
1666
- :inner_inner_bad => force_to_ascii("bad inner \255inner value")
1667
- }
1668
- ]
1669
- }
1670
- }
1671
-
1672
-
1673
- payload_copy = payload.clone
1674
- notifier.send(:enforce_valid_utf8, payload_copy)
1675
-
1676
- payload_copy[:bad_value].should == "bad value 1"
1677
- payload_copy[:bad_value_2].should == "bad value 2"
1678
- payload_copy["bad key"].should == "good value"
1679
- payload_copy.keys.should_not include("bad\456 key")
1680
- payload_copy[:hash][:inner_bad_value].should == "bad value 3"
1681
- payload_copy[:hash][:"inner bad key"].should == 'inner good value'
1682
- payload_copy[:hash]["bad array key"].should == [
1683
- 'good array value 1',
1684
- 'bad array value 1',
1685
- {
1686
- :inner_inner_bad => 'bad inner inner value'
1687
- }
1688
- ]
1689
- end
1690
- end
1691
-
1692
- context 'truncate_payload' do
1693
- it 'should truncate all nested strings in the payload' do
1694
- payload = {
1695
- :truncated => '1234567',
1696
- :not_truncated => '123456',
1697
- :hash => {
1698
- :inner_truncated => '123456789',
1699
- :inner_not_truncated => '567',
1700
- :array => ['12345678', '12', {:inner_inner => '123456789'}]
1701
- }
1702
- }
1703
-
1704
- payload_copy = payload.clone
1705
- notifier.send(:truncate_payload, payload_copy, 6)
1706
-
1707
- payload_copy[:truncated].should == '123...'
1708
- payload_copy[:not_truncated].should == '123456'
1709
- payload_copy[:hash][:inner_truncated].should == '123...'
1710
- payload_copy[:hash][:inner_not_truncated].should == '567'
1711
- payload_copy[:hash][:array].should == ['123...', '12', {:inner_inner => '123...'}]
1712
- end
1713
-
1714
- it 'should truncate utf8 strings properly' do
1715
- payload = {
1716
- :truncated => 'Ŝǻмρļẻ śţяịņģ',
1717
- :not_truncated => '123456',
1718
- }
1719
-
1720
- payload_copy = payload.clone
1721
- notifier.send(:truncate_payload, payload_copy, 6)
1722
-
1723
- payload_copy[:truncated].should == "Ŝǻм..."
1724
- payload_copy[:not_truncated].should == '123456'
1725
- end
1726
- end
1727
-
1728
- context 'server_data' do
1729
- it 'should have the right hostname' do
1730
- notifier.send(:server_data)[:host] == Socket.gethostname
1731
- end
1732
-
1733
- it 'should have root and branch set when configured' do
1734
- configure
1735
- Rollbar.configure do |config|
1736
- config.root = '/path/to/root'
1737
- config.branch = 'master'
1738
- end
1739
-
1740
- data = notifier.send(:server_data)
1741
- data[:root].should == '/path/to/root'
1742
- data[:branch].should == 'master'
1743
- end
1744
- end
1745
-
1746
- context "project_gems" do
1747
- it "should include gem paths for specified project gems in the payload" do
1748
- gems = ['rack', 'rspec-rails']
1749
- gem_paths = []
1750
-
1751
- Rollbar.configure do |config|
1752
- config.project_gems = gems
1753
- end
1754
-
1755
- gems.each {|gem|
1756
- gem_paths.push(Gem::Specification.find_by_name(gem).gem_dir)
1757
- }
1758
-
1759
- data = notifier.send(:build_payload, 'info', 'test', nil, {})['data']
1760
- data[:project_package_paths].kind_of?(Array).should == true
1761
- data[:project_package_paths].length.should == gem_paths.length
1762
-
1763
- data[:project_package_paths].each_with_index{|path, index|
1764
- path.should == gem_paths[index]
1765
- }
1766
- end
1767
-
1768
- it "should handle regex gem patterns" do
1769
- gems = ["rack", /rspec/, /roll/]
1770
- gem_paths = []
1771
-
1772
- Rollbar.configure do |config|
1773
- config.project_gems = gems
1774
- end
1775
-
1776
- gem_paths = gems.map{|gem| Gem::Specification.find_all_by_name(gem).map(&:gem_dir) }.flatten.compact.uniq
1777
- gem_paths.length.should > 1
1778
-
1779
- gem_paths.any?{|path| path.include? 'rollbar-gem'}.should == true
1780
- gem_paths.any?{|path| path.include? 'rspec-rails'}.should == true
1781
-
1782
- data = notifier.send(:build_payload, 'info', 'test', nil, {})['data']
1783
- data[:project_package_paths].kind_of?(Array).should == true
1784
- data[:project_package_paths].length.should == gem_paths.length
1785
- (data[:project_package_paths] - gem_paths).length.should == 0
1786
- end
1787
-
1788
- it "should not break on non-existent gems" do
1789
- gems = ["this_gem_does_not_exist", "rack"]
1790
-
1791
- Rollbar.configure do |config|
1792
- config.project_gems = gems
1793
- end
1794
-
1795
- data = notifier.send(:build_payload, 'info', 'test', nil, {})['data']
1796
- data[:project_package_paths].kind_of?(Array).should == true
1797
- data[:project_package_paths].length.should == 1
1798
- end
1799
- end
1800
-
1801
- context 'report_internal_error', :reconfigure_notifier => true do
1802
- it "should not crash when given an exception object" do
1803
- begin
1804
- 1 / 0
1805
- rescue => e
1806
- notifier.send(:report_internal_error, e)
1807
- end
1808
- end
1809
- end
1810
-
1811
- context "send_failsafe" do
1812
- let(:exception) { StandardError.new }
1813
-
1814
- it "doesn't crash when given a message and exception" do
1815
- sent_payload = notifier.send(:send_failsafe, "test failsafe", exception)
1816
-
1817
- expected_message = 'Failsafe from rollbar-gem. StandardError: test failsafe'
1818
- expect(sent_payload['data'][:body][:message][:body]).to be_eql(expected_message)
1819
- end
1820
-
1821
- it "doesn't crash when given all nils" do
1822
- notifier.send(:send_failsafe, nil, nil)
1823
- end
1824
-
1825
- context 'with a non default exception message' do
1826
- let(:exception) { StandardError.new 'Something is wrong' }
1827
-
1828
- it 'adds it to exception info' do
1829
- sent_payload = notifier.send(:send_failsafe, "test failsafe", exception)
1830
-
1831
- expected_message = 'Failsafe from rollbar-gem. StandardError: "Something is wrong": test failsafe'
1832
- expect(sent_payload['data'][:body][:message][:body]).to be_eql(expected_message)
1833
- end
1834
- end
1835
-
1836
- context 'without exception object' do
1837
- it 'just sends the given message' do
1838
- sent_payload = notifier.send(:send_failsafe, "test failsafe", nil)
1839
-
1840
- expected_message = 'Failsafe from rollbar-gem. test failsafe'
1841
- expect(sent_payload['data'][:body][:message][:body]).to be_eql(expected_message)
1842
- end
1843
- end
1844
-
1845
- context 'if the exception has a backtrace' do
1846
- let(:backtrace) { ['func3', 'func2', 'func1'] }
1847
- let(:failsafe_reason) { 'StandardError in func3: test failsafe' }
1848
- let(:expected_body) { "Failsafe from rollbar-gem. #{failsafe_reason}" }
1849
- let(:expected_log_message) do
1850
- "[Rollbar] Sending failsafe response due to #{failsafe_reason}"
1851
- end
1852
-
1853
- before { exception.set_backtrace(backtrace) }
1854
-
1855
- it 'adds the nearest frame to the message' do
1856
- expect(notifier).to receive(:log_error).with(expected_log_message)
1857
-
1858
- sent_payload = notifier.send(:send_failsafe, "test failsafe", exception)
1859
-
1860
- expect(sent_payload['data'][:body][:message][:body]).to be_eql(expected_body)
1861
- end
1862
- end
1863
- end
1864
-
1865
- context 'when reporting internal error with nil context' do
1866
- let(:context_proc) { proc {} }
1867
- let(:scoped_notifier) { notifier.scope(:context => context_proc) }
1868
- let(:exception) { Exception.new }
1869
- let(:logger_mock) { double("Rails.logger").as_null_object }
1870
-
1871
- it 'reports successfully' do
1872
- configure
1873
-
1874
- Rollbar.configure do |config|
1875
- config.logger = logger_mock
1876
- end
1877
-
1878
- logger_mock.should_receive(:info).with('[Rollbar] Sending payload').once
1879
- logger_mock.should_receive(:info).with('[Rollbar] Success').once
1880
- scoped_notifier.send(:report_internal_error, exception)
1881
- end
1882
- end
1883
-
1884
- context "request_data_extractor" do
1885
- before(:each) do
1886
- class DummyClass
1887
- end
1888
- @dummy_class = DummyClass.new
1889
- @dummy_class.extend(Rollbar::RequestDataExtractor)
1890
- end
1891
-
1892
- context "rollbar_headers" do
1893
- it "should not include cookies" do
1894
- env = {"HTTP_USER_AGENT" => "test", "HTTP_COOKIE" => "cookie"}
1895
- headers = @dummy_class.send(:rollbar_headers, env)
1896
- headers.should have_key "User-Agent"
1897
- headers.should_not have_key "Cookie"
1898
- end
1899
- end
1900
- end
1901
-
1902
- describe '.scoped' do
1903
- let(:scope_options) do
1904
- { :foo => 'bar' }
1905
- end
1906
-
1907
- it 'changes data in scope_object inside the block' do
1908
- Rollbar.reset_notifier!
1909
- configure
1910
-
1911
- current_notifier_id = Rollbar.notifier.object_id
1912
-
1913
- Rollbar.scoped(scope_options) do
1914
- scope_object = Rollbar.notifier.scope_object
1915
-
1916
- expect(Rollbar.notifier.object_id).not_to be_eql(current_notifier_id)
1917
- expect(scope_object).to be_eql(scope_options)
1918
- end
1919
-
1920
- expect(Rollbar.notifier.object_id).to be_eql(current_notifier_id)
1921
- end
1922
-
1923
- context 'if the block fails' do
1924
- let(:crashing_block) { proc { fail } }
1925
-
1926
- it 'restores the old notifier' do
1927
- notifier = Rollbar.notifier
1928
-
1929
- expect { Rollbar.scoped(&crashing_block) }.to raise_error
1930
- expect(notifier).to be_eql(Rollbar.notifier)
1931
- end
1932
- end
1933
-
1934
- context 'if the block creates a new thread' do
1935
- let(:block) do
1936
- proc do
1937
- Thread.new do
1938
- scope = Rollbar.notifier.scope_object
1939
- Thread.main[:inner_scope] = scope
1940
- end.join
1941
- end
1942
- end
1943
-
1944
- let(:scope) do
1945
- { :foo => 'bar' }
1946
- end
1947
-
1948
- it 'maintains the parent thread notifier scope' do
1949
- Rollbar.scoped(scope, &block)
1950
-
1951
- expect(Thread.main[:inner_scope]).to be_eql(scope)
1952
- end
1953
- end
1954
- end
1955
-
1956
- describe '.scope!' do
1957
- let(:new_scope) do
1958
- { :person => { :id => 1 } }
1959
- end
1960
-
1961
- before { reconfigure_notifier }
1962
-
1963
- it 'adds the new scope to the payload options' do
1964
- scope_object = Rollbar.notifier.scope_object
1965
- Rollbar.scope!(new_scope)
1966
-
1967
- expect(scope_object).to be_eql(new_scope)
1968
- end
1969
- end
1970
-
1971
- describe '.reset_notifier' do
1972
- it 'resets the notifier' do
1973
- notifier1_id = Rollbar.notifier.object_id
1974
-
1975
- Rollbar.reset_notifier!
1976
- expect(Rollbar.notifier.object_id).not_to be_eql(notifier1_id)
1977
- end
1978
- end
1979
-
1980
- describe '.process_payload' do
1981
- context 'if there is an exception sending the payload' do
1982
- let(:exception) { StandardError.new('error message') }
1983
- let(:payload) { { :foo => :bar } }
1984
-
1985
- it 'logs the error and the payload' do
1986
- allow(Rollbar.notifier).to receive(:send_payload).and_raise(exception)
1987
- expect(Rollbar.notifier).to receive(:log_error)
1988
-
1989
- expect { Rollbar.notifier.process_payload(payload) }.to raise_error(exception)
1990
- end
1991
- end
1992
- end
1993
-
1994
- describe '.process_from_async_handler' do
1995
- context 'with errors' do
1996
- let(:exception) { StandardError.new('the error') }
1997
-
1998
- it 'raises anything and sends internal error' do
1999
- allow(Rollbar.notifier).to receive(:process_payload).and_raise(exception)
2000
- expect(Rollbar.notifier).to receive(:report_internal_error).with(exception)
2001
-
2002
- expect do
2003
- Rollbar.notifier.process_from_async_handler({})
2004
- end.to raise_error(exception)
2005
-
2006
- rollbar_do_not_report = exception.instance_variable_get(:@_rollbar_do_not_report)
2007
- expect(rollbar_do_not_report).to be_eql(true)
2008
- end
2009
- end
2010
- end
2011
-
2012
- describe '#custom_data' do
2013
- before do
2014
- Rollbar.configure do |config|
2015
- config.custom_data_method = proc { raise 'this-will-raise' }
2016
- end
2017
-
2018
- expect_any_instance_of(Rollbar::Notifier).to receive(:error).and_return(report_data)
2019
- end
2020
-
2021
- context 'with uuid in reported data' do
2022
- next unless defined?(SecureRandom) and SecureRandom.respond_to?(:uuid)
2023
-
2024
- let(:report_data) { { :uuid => SecureRandom.uuid } }
2025
- let(:expected_url) { "https://rollbar.com/instance/uuid?uuid=#{report_data[:uuid]}" }
2026
-
2027
- it 'returns the uuid in :_error_in_custom_data_method' do
2028
- expect(notifier.custom_data).to be_eql(:_error_in_custom_data_method => expected_url)
2029
- end
2030
- end
2031
-
2032
- context 'without uuid in reported data' do
2033
- let(:report_data) { { :some => 'other-data' } }
2034
-
2035
- it 'returns the uuid in :_error_in_custom_data_method' do
2036
- expect(notifier.custom_data).to be_eql({})
2037
- end
2038
- end
2039
- end
2040
-
2041
- describe '.preconfigure'do
2042
- before do
2043
- Rollbar.unconfigure
2044
- Rollbar.reset_notifier!
2045
- end
2046
-
2047
- it 'resets the notifier' do
2048
- Rollbar.configure do |config|
2049
- config.access_token = 'foo'
2050
- end
2051
-
2052
- Thread.new {}
2053
-
2054
- Rollbar.preconfigure do |config|
2055
- config.root = 'bar'
2056
- end
2057
-
2058
- notifier_config = Rollbar.notifier.configuration
2059
- expect(notifier_config.root).to be_eql('bar')
2060
- end
2061
- end
2062
-
2063
- # configure with some basic params
2064
- def configure
2065
- reconfigure_notifier
2066
- end
2067
- end