ratchetio 0.4.7 → 0.4.8
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.
- data/CHANGELOG.md +4 -0
- data/Gemfile +1 -0
- data/README.md +36 -1
- data/lib/generators/ratchetio/templates/initializer.rb +8 -0
- data/lib/ratchetio/configuration.rb +7 -0
- data/lib/ratchetio/railtie.rb +1 -0
- data/lib/ratchetio/version.rb +1 -1
- data/lib/ratchetio.rb +79 -5
- data/ratchetio.gemspec +1 -0
- data/spec/ratchetio_spec.rb +101 -0
- metadata +18 -2
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
**0.4.8**
|
4
|
+
- Add ability to send reports asynchronously, using girl_friday or Threading by default.
|
5
|
+
- Add ability to save reports to a file (for use with ratchet-agent) instead of sending across to Ratchet servers.
|
6
|
+
|
3
7
|
**0.4.7**
|
4
8
|
- Sensitive params now scrubbed out of requests. Param name list is customizable via the `scrub_fields` config option.
|
5
9
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -85,7 +85,7 @@ If the methods to extract the `id`, `username`, and `email` from the object retu
|
|
85
85
|
|
86
86
|
## Exception level filters
|
87
87
|
|
88
|
-
By default, all exceptions reported through `Ratchetio.report_exception()` are
|
88
|
+
By default, all exceptions reported through `Ratchetio.report_exception()` are reported at the "error" level, except for the following, which are reported at "warning" level:
|
89
89
|
|
90
90
|
- ActiveRecord::RecordNotFound
|
91
91
|
- AbstractController::ActionNotFound
|
@@ -94,6 +94,41 @@ 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
|
+
|
98
|
+
## Asynchronous reporting
|
99
|
+
|
100
|
+
By default, all messages are reported synchronously. You can enable asynchronous reporting by adding the following in `config/initializers/ratchetio.rb`:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
config.use_async = true
|
104
|
+
```
|
105
|
+
|
106
|
+
Ratchet uses [girl_friday](https://github.com/mperham/girl_friday) to handle asynchronous reporting when installed, and falls back to Threading if girl_friday is not installed.
|
107
|
+
|
108
|
+
You can supply your own handler using `config.async_handler`. The handler should schedule the payload for later processing (i.e. with a delayed_job, in a resque queue, etc.) and should itself return immediately. For example:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
config.async_handler = Proc.new { |payload|
|
112
|
+
Thread.new { Ratchetio.process_payload(payload) }
|
113
|
+
}
|
114
|
+
```
|
115
|
+
|
116
|
+
Make sure you pass `payload` to `Ratchetio.process_payload` in your own implementation.
|
117
|
+
|
118
|
+
|
119
|
+
## Using with ratchet-agent
|
120
|
+
|
121
|
+
For even more asynchrony, you can configure the gem to write to a file instead of sending the payload to Ratchet servers directly. [ratchet-agent](https://github.com/ratchetio/ratchet-agent) can then be hooked up to this file to actually send the payload across. To enable, add the following in `config/initializers/ratchetio.rb`:
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
config.write_to_file = true
|
125
|
+
# optional, defaults to "#{AppName}.ratchet"
|
126
|
+
config.filepath = '/path/to/file.ratchet' #should end in '.ratchet' for use with ratchet-agent
|
127
|
+
```
|
128
|
+
|
129
|
+
For this to work, you'll also need to set up ratchet-agent--see its docs for details.
|
130
|
+
|
131
|
+
|
97
132
|
## Help / Support
|
98
133
|
|
99
134
|
If you run into any issues, please email us at `support@ratchet.io`
|
@@ -17,4 +17,12 @@ Ratchetio.configure do |config|
|
|
17
17
|
# Valid levels: 'critical', 'error', 'warning', 'info', 'debug', 'ignore'
|
18
18
|
# 'ignore' will cause the exception to not be reported at all.
|
19
19
|
# config.exception_level_filters.merge!('MyCriticalException' => 'critical')
|
20
|
+
|
21
|
+
# Enable asynchronous reporting (uses girl_friday or Threading if girl_friday
|
22
|
+
# is not installed)
|
23
|
+
# config.use_async = true
|
24
|
+
# Supply your own async handler:
|
25
|
+
# config.async_handler = Proc.new { |payload|
|
26
|
+
# Thread.new { Ratchetio.process_payload(payload) }
|
27
|
+
# }
|
20
28
|
end
|
@@ -8,6 +8,8 @@ module Ratchetio
|
|
8
8
|
attr_accessor :default_logger
|
9
9
|
attr_accessor :enabled
|
10
10
|
attr_accessor :endpoint
|
11
|
+
attr_accessor :write_to_file
|
12
|
+
attr_accessor :filepath
|
11
13
|
attr_accessor :environment
|
12
14
|
attr_accessor :exception_level_filters
|
13
15
|
attr_accessor :framework
|
@@ -18,6 +20,8 @@ module Ratchetio
|
|
18
20
|
attr_accessor :person_email_method
|
19
21
|
attr_accessor :root
|
20
22
|
attr_accessor :scrub_fields
|
23
|
+
attr_accessor :use_async
|
24
|
+
attr_accessor :async_handler
|
21
25
|
|
22
26
|
DEFAULT_ENDPOINT = 'https://submit.ratchet.io/api/1/item/'
|
23
27
|
|
@@ -25,6 +29,7 @@ module Ratchetio
|
|
25
29
|
@default_logger = lambda { Logger.new(STDERR) }
|
26
30
|
@enabled = true
|
27
31
|
@endpoint = DEFAULT_ENDPOINT
|
32
|
+
@write_to_file = false
|
28
33
|
@framework = 'Plain'
|
29
34
|
@exception_level_filters = {
|
30
35
|
'ActiveRecord::RecordNotFound' => 'warning',
|
@@ -36,6 +41,8 @@ module Ratchetio
|
|
36
41
|
@person_username_method = 'username'
|
37
42
|
@person_email_method = 'email'
|
38
43
|
@scrub_fields = [:passwd, :password, :secret]
|
44
|
+
@use_async = false
|
45
|
+
@async_handler = nil
|
39
46
|
end
|
40
47
|
|
41
48
|
# allow params to be read like a hash
|
data/lib/ratchetio/railtie.rb
CHANGED
@@ -13,6 +13,7 @@ module Ratchetio
|
|
13
13
|
config.environment ||= ::Rails.env
|
14
14
|
config.root ||= ::Rails.root
|
15
15
|
config.framework = "Rails: #{::Rails::VERSION::STRING}"
|
16
|
+
config.filepath ||= ::Rails.application.class.parent_name + '.ratchet'
|
16
17
|
end
|
17
18
|
|
18
19
|
ActiveSupport.on_load(:action_controller) do
|
data/lib/ratchetio/version.rb
CHANGED
data/lib/ratchetio.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
require 'net/https'
|
2
2
|
require 'socket'
|
3
|
+
require 'thread'
|
3
4
|
require 'uri'
|
4
5
|
|
5
6
|
require 'ratchetio/version'
|
6
7
|
require 'ratchetio/configuration'
|
7
8
|
require 'ratchetio/railtie' if defined?(Rails)
|
8
9
|
require 'ratchetio/goalie' if defined?(Goalie)
|
10
|
+
require "girl_friday" if defined?(GirlFriday)
|
9
11
|
|
10
12
|
module Ratchetio
|
11
13
|
class << self
|
@@ -67,7 +69,7 @@ module Ratchetio
|
|
67
69
|
data[:person] = person_data if person_data
|
68
70
|
|
69
71
|
payload = build_payload(data)
|
70
|
-
|
72
|
+
schedule_payload(payload)
|
71
73
|
rescue => e
|
72
74
|
logger.error "[Ratchet.io] Error reporting exception to Ratchet.io: #{e}"
|
73
75
|
end
|
@@ -90,11 +92,23 @@ module Ratchetio
|
|
90
92
|
|
91
93
|
data = message_data(message, level, extra_data)
|
92
94
|
payload = build_payload(data)
|
93
|
-
|
95
|
+
schedule_payload(payload)
|
94
96
|
rescue => e
|
95
97
|
logger.error "[Ratchet.io] Error reporting message to Ratchet.io: #{e}"
|
96
98
|
end
|
97
99
|
|
100
|
+
def process_payload(payload)
|
101
|
+
begin
|
102
|
+
if configuration.write_to_file
|
103
|
+
write_payload(payload)
|
104
|
+
else
|
105
|
+
send_payload(payload)
|
106
|
+
end
|
107
|
+
rescue => e
|
108
|
+
logger.error "[Ratchet.io] Error reporting message to Ratchet.io: #{e}"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
98
112
|
private
|
99
113
|
|
100
114
|
def message_data(message, level, extra_data)
|
@@ -147,10 +161,36 @@ module Ratchetio
|
|
147
161
|
end
|
148
162
|
configuration.logger
|
149
163
|
end
|
150
|
-
|
164
|
+
|
165
|
+
def write_payload(payload)
|
166
|
+
if configuration.use_async
|
167
|
+
@file_semaphore.synchronize {
|
168
|
+
do_write_payload(payload)
|
169
|
+
}
|
170
|
+
else
|
171
|
+
do_write_payload(payload)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def do_write_payload(payload)
|
176
|
+
logger.info '[Ratchet.io] Writing payload to file'
|
177
|
+
|
178
|
+
begin
|
179
|
+
unless @file
|
180
|
+
@file = File.open(configuration.filepath, "a")
|
181
|
+
end
|
182
|
+
|
183
|
+
@file.puts payload
|
184
|
+
@file.flush
|
185
|
+
logger.info "[Ratchet.io] Success"
|
186
|
+
rescue IOError => e
|
187
|
+
logger.error "[Ratchet.io] Error opening/writing to file: #{e}"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
151
191
|
def send_payload(payload)
|
152
192
|
logger.info '[Ratchet.io] Sending payload'
|
153
|
-
|
193
|
+
|
154
194
|
uri = URI.parse(configuration.endpoint)
|
155
195
|
http = Net::HTTP.new(uri.host, uri.port)
|
156
196
|
|
@@ -170,6 +210,26 @@ module Ratchetio
|
|
170
210
|
logger.info "[Ratchet.io] Response: #{response.body}"
|
171
211
|
end
|
172
212
|
end
|
213
|
+
|
214
|
+
def schedule_payload(payload)
|
215
|
+
logger.info '[Ratchet.io] Scheduling payload'
|
216
|
+
|
217
|
+
if configuration.use_async
|
218
|
+
unless configuration.async_handler
|
219
|
+
configuration.async_handler = method(:default_async_handler)
|
220
|
+
end
|
221
|
+
|
222
|
+
if configuration.write_to_file
|
223
|
+
unless @file_semaphore
|
224
|
+
@file_semaphore = Mutex.new
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
configuration.async_handler.call(payload)
|
229
|
+
else
|
230
|
+
process_payload(payload)
|
231
|
+
end
|
232
|
+
end
|
173
233
|
|
174
234
|
def build_payload(data)
|
175
235
|
payload = {
|
@@ -205,6 +265,20 @@ module Ratchetio
|
|
205
265
|
|
206
266
|
data
|
207
267
|
end
|
208
|
-
|
268
|
+
|
269
|
+
def default_async_handler(payload)
|
270
|
+
if defined?(GirlFriday)
|
271
|
+
unless @queue
|
272
|
+
@queue = GirlFriday::WorkQueue.new(nil, :size => 5) do |payload|
|
273
|
+
process_payload(payload)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
@queue.push(payload)
|
278
|
+
else
|
279
|
+
logger.warn '[Ratchet.io] girl_friday not found to handle async call, falling back to Thread'
|
280
|
+
Thread.new { process_payload(payload) }
|
281
|
+
end
|
282
|
+
end
|
209
283
|
end
|
210
284
|
end
|
data/ratchetio.gemspec
CHANGED
@@ -18,4 +18,5 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.add_development_dependency 'devise', '>= 2.1.2'
|
19
19
|
gem.add_development_dependency 'rspec-rails', '~> 2.12.0'
|
20
20
|
gem.add_development_dependency 'database_cleaner', '>= 0.9.1'
|
21
|
+
gem.add_development_dependency 'girl_friday', '>= 0.11.1'
|
21
22
|
end
|
data/spec/ratchetio_spec.rb
CHANGED
@@ -125,6 +125,107 @@ describe Ratchetio do
|
|
125
125
|
end
|
126
126
|
end
|
127
127
|
end
|
128
|
+
|
129
|
+
context 'payload_destination' do
|
130
|
+
before(:each) do
|
131
|
+
configure
|
132
|
+
Ratchetio.configure do |config|
|
133
|
+
config.logger = logger_mock
|
134
|
+
config.filepath = 'test.ratchet'
|
135
|
+
end
|
136
|
+
|
137
|
+
begin
|
138
|
+
foo = bar
|
139
|
+
rescue => e
|
140
|
+
@exception = e
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
let(:logger_mock) { double("Rails.logger").as_null_object }
|
145
|
+
|
146
|
+
it 'should send the payload over the network by default' do
|
147
|
+
logger_mock.should_not_receive(:info).with('[Ratchet.io] Writing payload to file')
|
148
|
+
logger_mock.should_receive(:info).with('[Ratchet.io] Sending payload')
|
149
|
+
logger_mock.should_receive(:info).with('[Ratchet.io] Success')
|
150
|
+
Ratchetio.report_exception(@exception)
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'should save the payload to a file if set' do
|
154
|
+
logger_mock.should_not_receive(:info).with('[Ratchet.io] Sending payload')
|
155
|
+
logger_mock.should_receive(:info).with('[Ratchet.io] Writing payload to file')
|
156
|
+
logger_mock.should_receive(:info).with('[Ratchet.io] Success')
|
157
|
+
|
158
|
+
filepath = ''
|
159
|
+
|
160
|
+
Ratchetio.configure do |config|
|
161
|
+
config.write_to_file = true
|
162
|
+
filepath = config.filepath
|
163
|
+
end
|
164
|
+
|
165
|
+
Ratchetio.report_exception(@exception)
|
166
|
+
|
167
|
+
File.exist?(filepath).should == true
|
168
|
+
File.read(filepath).should include test_access_token
|
169
|
+
File.delete(filepath)
|
170
|
+
|
171
|
+
Ratchetio.configure do |config|
|
172
|
+
config.write_to_file = false
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context 'asynchronous_handling' do
|
178
|
+
before(:each) do
|
179
|
+
configure
|
180
|
+
Ratchetio.configure do |config|
|
181
|
+
config.logger = logger_mock
|
182
|
+
end
|
183
|
+
|
184
|
+
begin
|
185
|
+
foo = bar
|
186
|
+
rescue => e
|
187
|
+
@exception = e
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
let(:logger_mock) { double("Rails.logger").as_null_object }
|
192
|
+
|
193
|
+
it 'should send the payload using the default asynchronous handler girl_friday' do
|
194
|
+
logger_mock.should_receive(:info).with('[Ratchet.io] Success')
|
195
|
+
|
196
|
+
Ratchetio.configure do |config|
|
197
|
+
config.use_async = true
|
198
|
+
GirlFriday::WorkQueue::immediate!
|
199
|
+
end
|
200
|
+
|
201
|
+
Ratchetio.report_exception(@exception)
|
202
|
+
|
203
|
+
Ratchetio.configure do |config|
|
204
|
+
config.use_async = false
|
205
|
+
GirlFriday::WorkQueue::queue!
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'should send the payload using a user-supplied asynchronous handler' do
|
210
|
+
logger_mock.should_receive(:info).with('Custom async handler called')
|
211
|
+
logger_mock.should_receive(:info).with('[Ratchet.io] Success')
|
212
|
+
|
213
|
+
Ratchetio.configure do |config|
|
214
|
+
config.use_async = true
|
215
|
+
config.async_handler = Proc.new { |payload|
|
216
|
+
logger_mock.info 'Custom async handler called'
|
217
|
+
Ratchetio.process_payload(payload)
|
218
|
+
}
|
219
|
+
end
|
220
|
+
|
221
|
+
Ratchetio.report_exception(@exception)
|
222
|
+
|
223
|
+
Ratchetio.configure do |config|
|
224
|
+
config.use_async = false
|
225
|
+
config.async_handler = Ratchetio.method(:default_async_handler)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
128
229
|
|
129
230
|
context 'message_data' do
|
130
231
|
before(:each) do
|
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.4.
|
4
|
+
version: 0.4.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -75,6 +75,22 @@ dependencies:
|
|
75
75
|
- - ! '>='
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: 0.9.1
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: girl_friday
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 0.11.1
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.11.1
|
78
94
|
description: Rails plugin to catch and send exceptions to Ratchet.io
|
79
95
|
email:
|
80
96
|
- brian@ratchet.io
|