whenauser 0.3.0 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +44 -8
- data/lib/whenauser/exceptions.rb +2 -4
- data/lib/whenauser/girl_friday_queue.rb +23 -0
- data/lib/whenauser/memory_queue.rb +11 -0
- data/lib/whenauser/railtie.rb +16 -5
- data/lib/whenauser/version.rb +1 -1
- data/lib/whenauser.rb +31 -15
- data/whenauser.gemspec +1 -2
- metadata +9 -23
data/README.md
CHANGED
@@ -17,20 +17,47 @@ In your Gemfile:
|
|
17
17
|
|
18
18
|
gem 'whenauser'
|
19
19
|
|
20
|
+
You also need
|
20
21
|
|
21
|
-
|
22
|
+
gem 'girl_friday', :git => 'git://github.com/mperham/girl_friday.git'
|
23
|
+
gem 'connection_pool', :git => 'git://github.com/mperham/connection_pool.git'
|
22
24
|
|
23
|
-
|
25
|
+
until girl_friday ~> 0.9.7 and connection_pool ~> 0.9.2 are released.
|
24
26
|
|
25
|
-
|
27
|
+
###For Ruby on Rails
|
28
|
+
|
29
|
+
You should create two incoming channels in WhenAUser, and configure their tokens in `config/whenauser.rb` (the available options are explained below). You may want to create additional channels to use in other environments, eg for staging.
|
30
|
+
|
31
|
+
token 'CHANNEL_TOKEN' # default channel (for user-centric events)
|
26
32
|
|
27
33
|
middleware :errors do
|
28
|
-
token
|
34
|
+
token 'ERROR_CHANNEL_TOKEN' # channel for error-centric events
|
29
35
|
end
|
36
|
+
|
37
|
+
###As general-purpose Rack middleware, without Rails
|
38
|
+
|
39
|
+
config.middleware.use 'WhenAUser::Rack', :token => 'CHANNEL_TOKEN_'
|
40
|
+
config.middleware.use 'WhenAUser::Exceptions', :token => 'ERROR_CHANNEL_TOKEN'
|
41
|
+
|
42
|
+
Using girl_friday for asynchronous communication and persistence
|
43
|
+
-----------------
|
44
|
+
|
45
|
+
By default this gem sends a batch of events to the WhenAUser service synchronously, at the end of each request to your application. This means that each request to your app will be slowed down by the time it takes to do that communication. In general, this is not going to be acceptable. To avoid this delay, WhenAUser supports the use of the [girl_friday](https://github.com/mperham/girl_friday) gem, which you can enable in your whenauser.rb file:
|
46
|
+
|
47
|
+
queue WhenAUser::GirlFridayQueue
|
48
|
+
|
49
|
+
You can also pass options to girl_friday. To avoid losing events when your app server instances restart, you can tell girl_friday to use Redis:
|
50
|
+
|
51
|
+
queue WhenAUser::GirlFridayQueue,
|
52
|
+
:store => GirlFriday::Store::Redis, :store_config => { :host => 'hostname', :port => 12345 }
|
53
|
+
|
54
|
+
If you already have a Redis connection pool, you can tell girl_friday to use it:
|
55
|
+
|
56
|
+
queue WhenAUser::GirlFridayQueue,
|
57
|
+
:store => GirlFriday::Store::Redis, :store_config => { :pool => $redis }
|
58
|
+
|
59
|
+
See the [girl_friday wiki](https://github.com/mperham/girl_friday/wiki) for more information on how to use girl_friday.
|
30
60
|
|
31
|
-
middleware :pageviews do
|
32
|
-
ignore_if lambda { |env| env['action_controller.instance'].is_a? SillyController }
|
33
|
-
end
|
34
61
|
|
35
62
|
Options
|
36
63
|
-------
|
@@ -40,13 +67,14 @@ WhenAUser::Rack accepts these options:
|
|
40
67
|
* `token` -- the token for a WhenAUser channel
|
41
68
|
* `webhook_url` -- defaults to 'http://whenauser.com/events'
|
42
69
|
* `middleware` -- takes the symbol for a middleware and a block, configuring it
|
70
|
+
* `queue` -- takes the class used for queuing (default: WhenAUser::MemoryQueue), and an optional hash
|
43
71
|
|
44
72
|
The `exceptions` middleware accepts these options:
|
45
73
|
|
74
|
+
* `token` -- the token for a WhenAUser error channel
|
46
75
|
* `ignore_exceptions` -- an array of exception class names, defaults to ['ActiveRecord::RecordNotFound', 'AbstractController::ActionNotFound', 'ActionController::RoutingError']
|
47
76
|
* `ignore_crawlers` -- an array of strings to match against the user agent, includes a number of webcrawlers by default
|
48
77
|
* `ignore_if` -- this proc is passed env and an exception; if it returns true, the exception is not reported to WhenAUser
|
49
|
-
* `token` -- the token for a WhenAUser channel
|
50
78
|
* `custom_data` -- this proc is passed env, and should return a hash to be merged into each event
|
51
79
|
|
52
80
|
The `pageviews` middleware accepts these options:
|
@@ -55,6 +83,14 @@ The `pageviews` middleware accepts these options:
|
|
55
83
|
* `ignore_if` -- this proc is passed env; if it returns true, the pageview is not reported to WhenAUser
|
56
84
|
* `custom_data` -- this proc is passed env, and should return a hash to be merged into each event
|
57
85
|
|
86
|
+
The WhenAUser::Pageviews middleware uses the same token as WhenAUser::Rack.
|
87
|
+
|
88
|
+
Here's an example of how to skip sending any pageview events for all requests to the SillyController:
|
89
|
+
|
90
|
+
middleware :pageviews do
|
91
|
+
ignore_if lambda { |env| env['action_controller.instance'].is_a? SillyController }
|
92
|
+
end
|
93
|
+
|
58
94
|
Sending other events
|
59
95
|
--------------------
|
60
96
|
|
data/lib/whenauser/exceptions.rb
CHANGED
@@ -36,8 +36,7 @@ module WhenAUser
|
|
36
36
|
|
37
37
|
private
|
38
38
|
def send_event_now(event, token)
|
39
|
-
|
40
|
-
WhenAUser.endpoint.post token, event.to_json
|
39
|
+
WhenAUser.post_payload_to_token WhenAUser.prepare_event(event), token
|
41
40
|
end
|
42
41
|
|
43
42
|
def should_be_ignored(env, exception)
|
@@ -73,7 +72,7 @@ module WhenAUser
|
|
73
72
|
:_domain => 'exception',
|
74
73
|
:_name => exception.class.to_s,
|
75
74
|
:message => exception.to_s,
|
76
|
-
:backtrace => backtrace.join("
|
75
|
+
:backtrace => backtrace.join("; "),
|
77
76
|
:request_url => request.url,
|
78
77
|
:request_method => request.request_method,
|
79
78
|
:params => request.params.except(*WhenAUser.filter_parameters),
|
@@ -82,7 +81,6 @@ module WhenAUser
|
|
82
81
|
user = current_user(env)
|
83
82
|
event.merge!(:current_user => user) if user
|
84
83
|
event.merge!(:referer_url => request.referer) if request.referer
|
85
|
-
event.merge!(:rails_env => Rails.env) if defined?(Rails)
|
86
84
|
event.merge!(@options[:custom_data].call(env))
|
87
85
|
event
|
88
86
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'girl_friday'
|
2
|
+
|
3
|
+
module WhenAUser
|
4
|
+
class GirlFridayQueue < GirlFriday::WorkQueue
|
5
|
+
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super(:whenauser, {:size => 1}.merge(WhenAUser.queue_options)) do |msg|
|
10
|
+
WhenAUser.post_payload_to_token msg[:payload], WhenAUser.token
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.push *args
|
15
|
+
instance.push *args
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.status
|
19
|
+
instance.status
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/lib/whenauser/railtie.rb
CHANGED
@@ -4,9 +4,9 @@ require 'action_controller/log_subscriber'
|
|
4
4
|
|
5
5
|
module Whenauser
|
6
6
|
class RailsConfigurator
|
7
|
-
attr_accessor :token, :webhook_url, :middlewares
|
7
|
+
attr_accessor :token, :webhook_url, :middlewares, :queue, :queue_options
|
8
8
|
def initialize
|
9
|
-
@webhook_url = 'http://whenauser.com/events/'
|
9
|
+
@webhook_url = 'http://www.whenauser.com/events/'
|
10
10
|
@middlewares = {}
|
11
11
|
end
|
12
12
|
|
@@ -21,6 +21,15 @@ module Whenauser
|
|
21
21
|
def middleware(middleware, &block)
|
22
22
|
@middlewares[middleware] = MiddlewareConfigurator.apply(&block)
|
23
23
|
end
|
24
|
+
|
25
|
+
def queue(queue, options)
|
26
|
+
@queue = queue
|
27
|
+
@queue_options = options
|
28
|
+
end
|
29
|
+
|
30
|
+
def girl_friday_options(options)
|
31
|
+
@girl_friday_options = options
|
32
|
+
end
|
24
33
|
end
|
25
34
|
|
26
35
|
class MiddlewareConfigurator
|
@@ -61,11 +70,13 @@ module Whenauser
|
|
61
70
|
Whenauser::RailsConfigurator.new.instance_eval do
|
62
71
|
eval IO.read(filename), binding, filename.to_s, 1
|
63
72
|
if defined?(::Rails.configuration) && ::Rails.configuration.respond_to?(:middleware)
|
64
|
-
::Rails.configuration.middleware.insert_after '
|
73
|
+
::Rails.configuration.middleware.insert_after 'ActionDispatch::Static', 'WhenAUser::Rack',
|
65
74
|
:webhook_url => @webhook_url,
|
66
|
-
:token => @token
|
75
|
+
:token => @token,
|
76
|
+
:queue => @queue,
|
77
|
+
:queue_options => @queue_options
|
67
78
|
::Rails.configuration.middleware.use('WhenAUser::Exceptions', @middlewares[:exceptions].configuration) if @middlewares.has_key?(:exceptions)
|
68
|
-
puts "configuration with: #{@middlewares[:pageviews].configuration}"
|
79
|
+
# puts "configuration with: #{@middlewares[:pageviews].configuration}"
|
69
80
|
::Rails.configuration.middleware.insert_after('WhenAUser::Rack', 'WhenAUser::Pageviews', @middlewares[:pageviews].configuration) if @middlewares.has_key?(:pageviews)
|
70
81
|
end
|
71
82
|
end
|
data/lib/whenauser/version.rb
CHANGED
data/lib/whenauser.rb
CHANGED
@@ -2,43 +2,59 @@ require 'whenauser/version'
|
|
2
2
|
require 'whenauser/helpers'
|
3
3
|
require 'whenauser/exceptions'
|
4
4
|
require 'whenauser/pageviews'
|
5
|
-
require '
|
6
|
-
require '
|
5
|
+
require 'whenauser/girl_friday_queue'
|
6
|
+
require 'whenauser/memory_queue'
|
7
|
+
require 'net/http'
|
8
|
+
require 'uri'
|
7
9
|
require 'active_support/core_ext/module/attribute_accessors'
|
8
10
|
|
9
11
|
module WhenAUser
|
10
|
-
mattr_accessor :endpoint, :filter_parameters, :queue, :
|
12
|
+
mattr_accessor :endpoint, :filter_parameters, :buffer, :token, :webhook_url, :queue, :queue_options
|
11
13
|
|
12
14
|
def self.default_ignored_crawlers
|
13
15
|
%w(Baidu Gigabot Googlebot libwww-perl lwp-trivial msnbot SiteUptime Slurp WordPress ZIBB ZyBorg Yandex Jyxobot Huaweisymantecspider ApptusBot)
|
14
16
|
end
|
15
17
|
|
16
18
|
def self.send_event(event)
|
17
|
-
|
18
|
-
WhenAUser.queue << event
|
19
|
+
WhenAUser.buffer << WhenAUser.prepare_event(event)
|
19
20
|
end
|
20
21
|
|
21
22
|
def self.flush
|
22
|
-
return if (events = WhenAUser.
|
23
|
-
WhenAUser.
|
24
|
-
|
23
|
+
return if (events = WhenAUser.buffer).empty?
|
24
|
+
WhenAUser.buffer = []
|
25
|
+
WhenAUser.queue.push(:payload => events)
|
26
|
+
# WhenAUser.post_payload_to_token events.to_json, WhenAUser.token
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.post_payload_to_token(payload, token)
|
30
|
+
uri = URI(WhenAUser.webhook_url + token)
|
31
|
+
req = Net::HTTP::Post.new(uri.path)
|
32
|
+
req.body = payload.to_json
|
33
|
+
req.content_type = 'application/json'
|
34
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
35
|
+
http.request(req)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.prepare_event(event)
|
40
|
+
event[:_timestamp] = Time.now.to_f unless event[:_timestamp] || event['_timestamp']
|
41
|
+
event[:rails_env] = Rails.env if defined?(Rails)
|
42
|
+
event
|
25
43
|
end
|
26
44
|
|
27
45
|
class Rack
|
28
46
|
def initialize(app, options={})
|
29
|
-
options[:webhook_url] ||= 'http://whenauser.com/events/'
|
30
47
|
@app = app
|
31
|
-
WhenAUser.
|
48
|
+
WhenAUser.webhook_url = options[:webhook_url] || 'http://www.whenauser.com/events/'
|
49
|
+
WhenAUser.buffer = []
|
32
50
|
WhenAUser.filter_parameters = defined?(Rails) ? Rails.application.config.filter_parameters : []
|
33
51
|
WhenAUser.token = options[:token]
|
34
|
-
WhenAUser.
|
35
|
-
|
36
|
-
builder.adapter Faraday.default_adapter
|
37
|
-
end
|
52
|
+
WhenAUser.queue = options[:queue] || WhenAUser::MemoryQueue
|
53
|
+
WhenAUser.queue_options = options[:queue_options] || {}
|
38
54
|
end
|
39
55
|
|
40
56
|
def call(env)
|
41
|
-
WhenAUser.
|
57
|
+
WhenAUser.buffer = []
|
42
58
|
@app.call(env)
|
43
59
|
ensure
|
44
60
|
WhenAUser.flush
|
data/whenauser.gemspec
CHANGED
@@ -18,6 +18,5 @@ Gem::Specification.new do |s|
|
|
18
18
|
|
19
19
|
s.add_runtime_dependency 'activesupport'
|
20
20
|
s.add_runtime_dependency 'actionpack'
|
21
|
-
s.add_runtime_dependency '
|
22
|
-
s.add_runtime_dependency 'faraday_middleware'
|
21
|
+
s.add_runtime_dependency 'girl_friday', '0.9.7'
|
23
22
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: whenauser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-08-01 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -45,37 +45,21 @@ dependencies:
|
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '0'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
48
|
+
name: girl_friday
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
54
|
+
version: 0.9.7
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
57
|
version_requirements: !ruby/object:Gem::Requirement
|
58
58
|
none: false
|
59
59
|
requirements:
|
60
|
-
- -
|
60
|
+
- - '='
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: 0.
|
63
|
-
- !ruby/object:Gem::Dependency
|
64
|
-
name: faraday_middleware
|
65
|
-
requirement: !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
|
-
requirements:
|
68
|
-
- - ! '>='
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
version: '0'
|
71
|
-
type: :runtime
|
72
|
-
prerelease: false
|
73
|
-
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
|
-
requirements:
|
76
|
-
- - ! '>='
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
version: '0'
|
62
|
+
version: 0.9.7
|
79
63
|
description: Rack middleware for connecting to WhenAUser
|
80
64
|
email:
|
81
65
|
- david@alpinegizmo.com
|
@@ -89,7 +73,9 @@ files:
|
|
89
73
|
- Rakefile
|
90
74
|
- lib/whenauser.rb
|
91
75
|
- lib/whenauser/exceptions.rb
|
76
|
+
- lib/whenauser/girl_friday_queue.rb
|
92
77
|
- lib/whenauser/helpers.rb
|
78
|
+
- lib/whenauser/memory_queue.rb
|
93
79
|
- lib/whenauser/pageviews.rb
|
94
80
|
- lib/whenauser/railtie.rb
|
95
81
|
- lib/whenauser/version.rb
|