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 CHANGED
@@ -17,20 +17,47 @@ In your Gemfile:
17
17
 
18
18
  gem 'whenauser'
19
19
 
20
+ You also need
20
21
 
21
- For Ruby on Rails
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
- You'll need to 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.
25
+ until girl_friday ~> 0.9.7 and connection_pool ~> 0.9.2 are released.
24
26
 
25
- token "CHANNEL_TOKEN"
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 "ERROR_CHANNEL_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
 
@@ -36,8 +36,7 @@ module WhenAUser
36
36
 
37
37
  private
38
38
  def send_event_now(event, token)
39
- event[:_timestamp] = Time.now.to_f unless event[:_timestamp] || event['_timestamp']
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("\n"),
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
@@ -0,0 +1,11 @@
1
+ require 'girl_friday'
2
+
3
+ module WhenAUser
4
+ class MemoryQueue
5
+
6
+ def self.push(hash)
7
+ WhenAUser.post_payload_to_token hash[:payload], WhenAUser.token
8
+ end
9
+
10
+ end
11
+ end
@@ -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 'Rack::Lock', 'WhenAUser::Rack',
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
@@ -1,3 +1,3 @@
1
1
  module WhenAUser
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.2'
3
3
  end
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 'faraday'
6
- require 'faraday_middleware'
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, :token
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
- event[:_timestamp] = Time.now.to_f unless event[:_timestamp] || event['_timestamp']
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.queue).empty?
23
- WhenAUser.queue = []
24
- endpoint.post WhenAUser.token, events.to_json
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.queue = []
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.endpoint = Faraday::Connection.new options[:webhook_url] do |builder|
35
- builder.request :json
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.queue = []
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 'faraday', '~> 0.8.0'
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.3.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-07-27 00:00:00.000000000 Z
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: faraday
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.8.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.8.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