ratchetio 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -10,6 +10,7 @@ coverage
10
10
  doc/
11
11
  log/
12
12
  lib/bundler/man
13
+ vendor/bundle
13
14
  pkg
14
15
  rdoc
15
16
  spec/reports
data/.travis.yml CHANGED
@@ -13,3 +13,4 @@ rvm:
13
13
  matrix:
14
14
  allow_failures:
15
15
  - rvm: ruby-head
16
+ - rvm: rbx-18mode
data/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Change Log
2
2
 
3
+ **0.5.3**
4
+ - Add `Ratchetio.silenced`; which allows disabling reporting for a given block. See README for usage.
5
+
3
6
  **0.5.2**
4
7
  - Fix compat issue with delayed_job below version 3. Exceptions raised by delayed_job below version 3 will not be automatically caught; upgrade to v3 or catch and report by hand.
5
8
 
data/README.md CHANGED
@@ -94,6 +94,16 @@ By default, all exceptions reported through `Ratchetio.report_exception()` are r
94
94
  If you'd like to customize this list, see the example code in `config/initializers/ratchetio.rb`. Supported levels: "critical", "error", "warning", "info", "debug", "ignore". Set to "ignore" to cause the exception not to be reported at all.
95
95
 
96
96
 
97
+ ## Silencing exceptions at runtime
98
+
99
+ If you just want to disable exception reporting for a single block, use `Ratchetio.silenced`:
100
+
101
+ ```ruby
102
+ Ratchetio.silenced {
103
+ foo = bar # will not be reported
104
+ }
105
+ ```
106
+
97
107
 
98
108
  ## Asynchronous reporting
99
109
 
data/THANKS CHANGED
@@ -1,5 +1,6 @@
1
1
  Huge thanks to the following contributors (by github username). For the most up-to-date list, see https://github.com/ratchetio/ratchetio-gem/graphs/contributors
2
2
 
3
+ arr-ee
3
4
  kavu
4
5
  mipearson
5
6
  trisweb
@@ -1,3 +1,3 @@
1
1
  module Ratchetio
2
- VERSION = "0.5.2"
2
+ VERSION = "0.5.3"
3
3
  end
data/lib/ratchetio.rb CHANGED
@@ -15,9 +15,9 @@ require 'ratchetio/version'
15
15
  module Ratchetio
16
16
  class << self
17
17
  attr_writer :configuration
18
-
18
+
19
19
  # Configures the gem.
20
- #
20
+ #
21
21
  # Call on app startup to set the `access_token` (required) and other config params.
22
22
  # In a Rails app, this is called by `config/initializers/ratchetio.rb` which is generated
23
23
  # with `rails generate ratchetio access-token-here`
@@ -29,7 +29,7 @@ module Ratchetio
29
29
  def configure
30
30
  yield(configuration)
31
31
  end
32
-
32
+
33
33
  def reconfigure
34
34
  @configuration = Configuration.new
35
35
  yield(configuration)
@@ -52,7 +52,7 @@ module Ratchetio
52
52
  # end
53
53
  #
54
54
  # @param exception [Exception] The exception object to report
55
- # @param request_data [Hash] Data describing the request. Should be the result of calling
55
+ # @param request_data [Hash] Data describing the request. Should be the result of calling
56
56
  # `ratchetio_request_data`.
57
57
  # @param person_data [Hash] Data describing the affected person. Should be the result of calling
58
58
  # `ratchetio_person_data`
@@ -61,13 +61,11 @@ module Ratchetio
61
61
  return
62
62
  end
63
63
 
64
- filtered_level = configuration.exception_level_filters[exception.class.name]
65
- if filtered_level == 'ignore'
66
- # ignored - do nothing
64
+ if ignored?(exception)
67
65
  return
68
66
  end
69
67
 
70
- data = exception_data(exception, filtered_level)
68
+ data = exception_data(exception, filtered_level(exception))
71
69
  data[:request] = request_data if request_data
72
70
  data[:person] = person_data if person_data
73
71
 
@@ -84,17 +82,17 @@ module Ratchetio
84
82
  # @example
85
83
  # Ratchetio.report_message("User login failed", 'info', :user_id => 123)
86
84
  #
87
- # @param message [String] The message body. This will be used to identify the message within
88
- # Ratchet. For best results, avoid putting variables in the message body; pass them as
89
- # `extra_data` instead.
85
+ # @param message [String] The message body. This will be used to identify the message within
86
+ # Ratchet. For best results, avoid putting variables in the message body; pass them as
87
+ # `extra_data` instead.
90
88
  # @param level [String] The level. One of: 'critical', 'error', 'warning', 'info', 'debug'
91
- # @param extra_data [Hash] Additional data to include alongside the body. Don't use 'body' as
89
+ # @param extra_data [Hash] Additional data to include alongside the body. Don't use 'body' as
92
90
  # it is reserved.
93
91
  def report_message(message, level = 'info', extra_data = {})
94
92
  unless configuration.enabled
95
93
  return
96
94
  end
97
-
95
+
98
96
  data = message_data(message, level, extra_data)
99
97
  payload = build_payload(data)
100
98
  schedule_payload(payload)
@@ -102,6 +100,21 @@ module Ratchetio
102
100
  logger.error "[Ratchet.io] Error reporting message to Ratchet.io: #{e}"
103
101
  end
104
102
 
103
+ # Turns off reporting for the given block.
104
+ #
105
+ # @example
106
+ # Ratchetio.silenced { raise }
107
+ #
108
+ # @yield Block which exceptions won't be reported.
109
+ def silenced
110
+ begin
111
+ yield
112
+ rescue => e
113
+ e.instance_variable_set(:@_ratchet_do_not_report, true)
114
+ raise
115
+ end
116
+ end
117
+
105
118
  def process_payload(payload)
106
119
  begin
107
120
  if configuration.write_to_file
@@ -116,9 +129,25 @@ module Ratchetio
116
129
 
117
130
  private
118
131
 
132
+ def ignored?(exception)
133
+ if filtered_level(exception) == 'ignore'
134
+ return true
135
+ end
136
+
137
+ if exception.instance_variable_get(:@_ratchet_do_not_report)
138
+ return true
139
+ end
140
+
141
+ false
142
+ end
143
+
144
+ def filtered_level(exception)
145
+ configuration.exception_level_filters[exception.class.name]
146
+ end
147
+
119
148
  def message_data(message, level, extra_data)
120
149
  data = base_data(level)
121
-
150
+
122
151
  data[:body] = {
123
152
  :message => {
124
153
  :body => message.to_s
@@ -126,13 +155,13 @@ module Ratchetio
126
155
  }
127
156
  data[:body][:message].merge!(extra_data)
128
157
  data[:server] = server_data
129
-
158
+
130
159
  data
131
160
  end
132
161
 
133
162
  def exception_data(exception, force_level = nil)
134
163
  data = base_data
135
-
164
+
136
165
  data[:level] = force_level if force_level
137
166
 
138
167
  # parse backtrace
@@ -159,7 +188,7 @@ module Ratchetio
159
188
  }
160
189
 
161
190
  data[:server] = server_data
162
-
191
+
163
192
  data
164
193
  end
165
194
 
@@ -170,7 +199,7 @@ module Ratchetio
170
199
  end
171
200
  configuration.logger
172
201
  end
173
-
202
+
174
203
  def write_payload(payload)
175
204
  if configuration.use_async
176
205
  @file_semaphore.synchronize {
@@ -180,15 +209,15 @@ module Ratchetio
180
209
  do_write_payload(payload)
181
210
  end
182
211
  end
183
-
212
+
184
213
  def do_write_payload(payload)
185
214
  logger.info '[Ratchet.io] Writing payload to file'
186
-
215
+
187
216
  begin
188
217
  unless @file
189
218
  @file = File.open(configuration.filepath, "a")
190
219
  end
191
-
220
+
192
221
  @file.puts payload
193
222
  @file.flush
194
223
  logger.info "[Ratchet.io] Success"
@@ -196,13 +225,13 @@ module Ratchetio
196
225
  logger.error "[Ratchet.io] Error opening/writing to file: #{e}"
197
226
  end
198
227
  end
199
-
228
+
200
229
  def send_payload(payload)
201
230
  logger.info '[Ratchet.io] Sending payload'
202
-
231
+
203
232
  uri = URI.parse(configuration.endpoint)
204
233
  http = Net::HTTP.new(uri.host, uri.port)
205
-
234
+
206
235
  if uri.scheme == 'https'
207
236
  http.use_ssl = true
208
237
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
@@ -219,21 +248,21 @@ module Ratchetio
219
248
  logger.info "[Ratchet.io] Response: #{response.body}"
220
249
  end
221
250
  end
222
-
251
+
223
252
  def schedule_payload(payload)
224
253
  logger.info '[Ratchet.io] Scheduling payload'
225
-
254
+
226
255
  if configuration.use_async
227
256
  unless configuration.async_handler
228
257
  configuration.async_handler = method(:default_async_handler)
229
258
  end
230
-
259
+
231
260
  if configuration.write_to_file
232
261
  unless @file_semaphore
233
262
  @file_semaphore = Mutex.new
234
263
  end
235
264
  end
236
-
265
+
237
266
  configuration.async_handler.call(payload)
238
267
  else
239
268
  process_payload(payload)
@@ -261,26 +290,26 @@ module Ratchetio
261
290
  :version => VERSION
262
291
  }
263
292
  }
264
-
293
+
265
294
  if defined?(SecureRandom) and SecureRandom.respond_to?(:uuid)
266
295
  data[:uuid] = SecureRandom.uuid
267
296
  end
268
-
297
+
269
298
  data
270
299
  end
271
300
 
272
301
  def server_data
273
302
  config = configuration
274
-
303
+
275
304
  data = {
276
305
  :host => Socket.gethostname
277
306
  }
278
307
  data[:root] = config.root.to_s if config.root
279
308
  data[:branch] = config.branch if config.branch
280
-
309
+
281
310
  data
282
311
  end
283
-
312
+
284
313
  def default_async_handler(payload)
285
314
  if defined?(GirlFriday)
286
315
  unless @queue
@@ -288,7 +317,7 @@ module Ratchetio
288
317
  process_payload(payload)
289
318
  end
290
319
  end
291
-
320
+
292
321
  @queue.push(payload)
293
322
  else
294
323
  logger.warn '[Ratchet.io] girl_friday not found to handle async call, falling back to Thread'
@@ -3,7 +3,7 @@ class HomeController < ApplicationController
3
3
  @users = User.all
4
4
 
5
5
  Ratchetio.report_message("Test message from controller with no data", "debug")
6
- Ratchetio.report_message("Test message from controller with extra data", "debug",
6
+ Ratchetio.report_message("Test message from controller with extra data", "debug",
7
7
  :foo => "bar", :num_users => @users.length)
8
8
  end
9
9
 
@@ -10,14 +10,14 @@ describe Ratchetio do
10
10
  Ratchetio.configure do |config|
11
11
  config.logger = logger_mock
12
12
  end
13
-
13
+
14
14
  begin
15
15
  foo = bar
16
16
  rescue => e
17
17
  @exception = e
18
18
  end
19
19
  end
20
-
20
+
21
21
  let(:logger_mock) { double("Rails.logger").as_null_object }
22
22
 
23
23
  it 'should report exceptions without person or request data' do
@@ -30,9 +30,9 @@ describe Ratchetio do
30
30
  Ratchetio.configure do |config|
31
31
  config.enabled = false
32
32
  end
33
-
33
+
34
34
  Ratchetio.report_exception(@exception)
35
-
35
+
36
36
  Ratchetio.configure do |config|
37
37
  config.enabled = true
38
38
  end
@@ -66,14 +66,30 @@ describe Ratchetio do
66
66
  logger_mock.should_not_receive(:info)
67
67
  logger_mock.should_not_receive(:warn)
68
68
  logger_mock.should_not_receive(:error)
69
-
69
+
70
70
  Ratchetio.report_exception(@exception)
71
-
71
+
72
72
  Ratchetio.configure do |config|
73
73
  config.exception_level_filters = saved_filters
74
74
  end
75
75
  end
76
76
 
77
+ it 'should not report exceptions when silenced' do
78
+ Ratchetio.should_not_receive :schedule_payload
79
+
80
+ begin
81
+ test_var = 1
82
+ Ratchetio.silenced do
83
+ test_var = 2
84
+ raise
85
+ end
86
+ rescue => e
87
+ Ratchetio.report_exception(e)
88
+ end
89
+
90
+ test_var.should == 2
91
+ end
92
+
77
93
  it 'should report exception objects with no backtrace' do
78
94
  payload = nil
79
95
  Ratchetio.stub(:schedule_payload) do |*args|
@@ -93,7 +109,7 @@ describe Ratchetio do
93
109
  end
94
110
  end
95
111
  end
96
-
112
+
97
113
  context 'report_message' do
98
114
  before(:each) do
99
115
  configure
@@ -101,7 +117,7 @@ describe Ratchetio do
101
117
  config.logger = logger_mock
102
118
  end
103
119
  end
104
-
120
+
105
121
  let(:logger_mock) { double("Rails.logger").as_null_object }
106
122
 
107
123
  it 'should report simple messages' do
@@ -115,9 +131,9 @@ describe Ratchetio do
115
131
  Ratchetio.configure do |config|
116
132
  config.enabled = false
117
133
  end
118
-
134
+
119
135
  Ratchetio.report_message("Test message that should be ignored")
120
-
136
+
121
137
  Ratchetio.configure do |config|
122
138
  config.enabled = true
123
139
  end
@@ -145,7 +161,7 @@ describe Ratchetio do
145
161
  end
146
162
  end
147
163
  end
148
-
164
+
149
165
  context 'payload_destination' do
150
166
  before(:each) do
151
167
  configure
@@ -153,83 +169,84 @@ describe Ratchetio do
153
169
  config.logger = logger_mock
154
170
  config.filepath = 'test.ratchet'
155
171
  end
156
-
172
+
157
173
  begin
158
174
  foo = bar
159
175
  rescue => e
160
176
  @exception = e
161
177
  end
162
178
  end
163
-
179
+
164
180
  let(:logger_mock) { double("Rails.logger").as_null_object }
165
-
181
+
166
182
  it 'should send the payload over the network by default' do
167
183
  logger_mock.should_not_receive(:info).with('[Ratchet.io] Writing payload to file')
168
184
  logger_mock.should_receive(:info).with('[Ratchet.io] Sending payload')
169
185
  logger_mock.should_receive(:info).with('[Ratchet.io] Success')
170
186
  Ratchetio.report_exception(@exception)
171
187
  end
172
-
188
+
173
189
  it 'should save the payload to a file if set' do
174
190
  logger_mock.should_not_receive(:info).with('[Ratchet.io] Sending payload')
175
191
  logger_mock.should_receive(:info).with('[Ratchet.io] Writing payload to file')
176
192
  logger_mock.should_receive(:info).with('[Ratchet.io] Success')
177
-
193
+
178
194
  filepath = ''
179
-
195
+
180
196
  Ratchetio.configure do |config|
181
197
  config.write_to_file = true
182
198
  filepath = config.filepath
183
199
  end
184
-
200
+
185
201
  Ratchetio.report_exception(@exception)
186
-
202
+
187
203
  File.exist?(filepath).should == true
188
204
  File.read(filepath).should include test_access_token
189
205
  File.delete(filepath)
190
-
206
+
191
207
  Ratchetio.configure do |config|
192
208
  config.write_to_file = false
193
209
  end
194
210
  end
195
211
  end
196
-
212
+
197
213
  context 'asynchronous_handling' do
198
214
  before(:each) do
199
215
  configure
200
216
  Ratchetio.configure do |config|
201
217
  config.logger = logger_mock
202
218
  end
203
-
219
+
204
220
  begin
205
221
  foo = bar
206
222
  rescue => e
207
223
  @exception = e
208
224
  end
209
225
  end
210
-
226
+
211
227
  let(:logger_mock) { double("Rails.logger").as_null_object }
212
-
228
+
213
229
  it 'should send the payload using the default asynchronous handler girl_friday' do
214
230
  logger_mock.should_receive(:info).with('[Ratchet.io] Success')
215
-
231
+
216
232
  Ratchetio.configure do |config|
217
233
  config.use_async = true
218
234
  GirlFriday::WorkQueue::immediate!
219
235
  end
220
-
236
+
221
237
  Ratchetio.report_exception(@exception)
222
-
238
+
223
239
  Ratchetio.configure do |config|
224
240
  config.use_async = false
225
241
  GirlFriday::WorkQueue::queue!
226
242
  end
227
243
  end
228
-
244
+
229
245
  it 'should send the payload using a user-supplied asynchronous handler' do
230
246
  logger_mock.should_receive(:info).with('Custom async handler called')
247
+ logger_mock.should_receive(:info).with('[Ratchet.io] Sending payload')
231
248
  logger_mock.should_receive(:info).with('[Ratchet.io] Success')
232
-
249
+
233
250
  Ratchetio.configure do |config|
234
251
  config.use_async = true
235
252
  config.async_handler = Proc.new { |payload|
@@ -237,9 +254,9 @@ describe Ratchetio do
237
254
  Ratchetio.process_payload(payload)
238
255
  }
239
256
  end
240
-
257
+
241
258
  Ratchetio.report_exception(@exception)
242
-
259
+
243
260
  Ratchetio.configure do |config|
244
261
  config.use_async = false
245
262
  config.async_handler = Ratchetio.method(:default_async_handler)
@@ -264,16 +281,16 @@ describe Ratchetio do
264
281
  user_id = 123
265
282
  name = "Tester"
266
283
 
267
- data = Ratchetio.send(:message_data, @message_body, 'info',
284
+ data = Ratchetio.send(:message_data, @message_body, 'info',
268
285
  :user_id => user_id, :name => name)
269
-
286
+
270
287
  message = data[:body][:message]
271
288
  message[:body].should == @message_body
272
289
  message[:user_id].should == user_id
273
290
  message[:name].should == name
274
291
  end
275
292
  end
276
-
293
+
277
294
  context 'exception_data' do
278
295
  before(:each) do
279
296
  configure
@@ -283,7 +300,7 @@ describe Ratchetio do
283
300
  @exception = e
284
301
  end
285
302
  end
286
-
303
+
287
304
  it 'should accept force_level' do
288
305
  level = 'critical'
289
306
  data = Ratchetio.send(:exception_data, @exception, level)
@@ -292,11 +309,11 @@ describe Ratchetio do
292
309
 
293
310
  it 'should build valid exception data' do
294
311
  data = Ratchetio.send(:exception_data, @exception)
295
-
312
+
296
313
  data[:level].should_not be_nil
297
-
314
+
298
315
  trace = data[:body][:trace]
299
-
316
+
300
317
  frames = trace[:frames]
301
318
  frames.should be_a_kind_of(Array)
302
319
  frames.each do |frame|
@@ -306,14 +323,14 @@ describe Ratchetio do
306
323
  frame[:method].should be_a_kind_of(String)
307
324
  end
308
325
  end
309
-
326
+
310
327
  # should be NameError, but can be NoMethodError sometimes on rubinius 1.8
311
328
  # http://yehudakatz.com/2010/01/02/the-craziest-fing-bug-ive-ever-seen/
312
329
  trace[:exception][:class].should match(/^(NameError|NoMethodError)$/)
313
330
  trace[:exception][:message].should match(/^(undefined local variable or method `bar'|undefined method `bar' on an instance of)/)
314
331
  end
315
332
  end
316
-
333
+
317
334
  context 'logger' do
318
335
  before(:each) do
319
336
  reset_configuration
@@ -340,7 +357,7 @@ describe Ratchetio do
340
357
  reset_configuration
341
358
  end
342
359
  end
343
-
360
+
344
361
  context 'build_payload' do
345
362
  it 'should build valid json' do
346
363
  json = Ratchetio.send(:build_payload, {:foo => {:bar => "baz"}})
@@ -357,7 +374,7 @@ describe Ratchetio do
357
374
  it 'should have the correct notifier name' do
358
375
  Ratchetio.send(:base_data)[:notifier][:name].should == 'ratchetio-gem'
359
376
  end
360
-
377
+
361
378
  it 'should have the correct notifier version' do
362
379
  Ratchetio.send(:base_data)[:notifier][:version].should == Ratchetio::VERSION
363
380
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ratchetio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: