whenauser 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,27 +1,36 @@
1
1
  WhenAUser
2
2
  =========
3
3
 
4
- [WhenAUser.com](http://whenauser.com) is a rules engine as a service that uses events from your application to trigger calls to 3rd party SaaS APIs. This lets you lift out the rapidly evolving parts of the business logic from your application, and use the WhenAUser web UI instead. This gem contains Rack middleware for connecting to WhenAUser. It generates two event streams, one for exceptions and the other for pageviews.
4
+ [WhenAUser.com](http://whenauser.com) is a rules engine that reacts to things users do or experience in your software, and makes things happen in 3rd party SaaS APIs -- without your having to write any code. Rather than implementing the most rapidly evolving parts of your application's business logic in code, your team can use the WhenAUser web app to specify "when", "how", and "who", with rules like these:
5
5
 
6
- Usage Example
7
- -------------
6
+ * when a user gets a validation error twice for the same form, send an email to Frank
7
+ * when a premium customer hasn't logged in for a month, flag them in Highrise
8
+ * when a user gets a 500 response, create a ticket in Zendesk
9
+ * when a user invites ten friends, add them to the "well-connected" segment in MailChimp
8
10
 
9
- config.middleware.use 'WhenAUser::Rack',
10
- :token => CHANNEL_TOKEN
11
- config.middleware.use 'WhenAUser::Exceptions',
12
- :token => ERROR_CHANNEL_TOKEN
13
- config.middleware.use 'WhenAUser::Pageviews',
14
- :ignore_if => lambda { |env| env['action_controller.instance'].is_a? SillyController }
11
+ This gem contains Rack middleware that automatically generates two event streams, one for exceptions and the other for pageviews, that can be used to trigger rules in WhenAUser. You can (and probably should) also send more specific events manually.
15
12
 
16
- This gem will automatically send events for all exceptions and all pageviews (except those that filtered out by the options). You can also manually send additional events. For example:
13
+ Setup
14
+ -----
17
15
 
18
- WhenAUser.send_event(
19
- :_actor => current_user.unique_id,
20
- :_timestamp => Time.now.to_f,
21
- :_domain => 'account',
22
- :_name => 'upgrade',
23
- :user_email => current_user.email,
24
- :plan => plan.name )
16
+ In your Gemfile:
17
+
18
+ gem 'whenauser'
19
+
20
+
21
+ For Ruby on Rails
22
+
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.
24
+
25
+ token "CHANNEL_TOKEN"
26
+
27
+ middleware :errors do
28
+ token "ERROR_CHANNEL_TOKEN"
29
+ end
30
+
31
+ middleware :pageviews do
32
+ ignore_if lambda { |env| env['action_controller.instance'].is_a? SillyController }
33
+ end
25
34
 
26
35
  Options
27
36
  -------
@@ -30,8 +39,9 @@ WhenAUser::Rack accepts these options:
30
39
 
31
40
  * `token` -- the token for a WhenAUser channel
32
41
  * `webhook_url` -- defaults to 'http://whenauser.com/events'
42
+ * `middleware` -- takes the symbol for a middleware and a block, configuring it
33
43
 
34
- WhenAUser::Exceptions accepts these options:
44
+ The `exceptions` middleware accepts these options:
35
45
 
36
46
  * `ignore_exceptions` -- an array of exception class names, defaults to ['ActiveRecord::RecordNotFound', 'AbstractController::ActionNotFound', 'ActionController::RoutingError']
37
47
  * `ignore_crawlers` -- an array of strings to match against the user agent, includes a number of webcrawlers by default
@@ -39,12 +49,25 @@ WhenAUser::Exceptions accepts these options:
39
49
  * `token` -- the token for a WhenAUser channel
40
50
  * `custom_data` -- this proc is passed env, and should return a hash to be merged into each event
41
51
 
42
- WhenAUser::Pageviews accepts these options:
52
+ The `pageviews` middleware accepts these options:
43
53
 
44
54
  * `ignore_crawlers` -- an array of strings to match against the user agent, includes a number of webcrawlers by default
45
55
  * `ignore_if` -- this proc is passed env; if it returns true, the pageview is not reported to WhenAUser
46
56
  * `custom_data` -- this proc is passed env, and should return a hash to be merged into each event
47
57
 
58
+ Sending other events
59
+ --------------------
60
+
61
+ To manually send an event when a user upgrades to a "premium" account:
62
+
63
+ WhenAUser.send_event(
64
+ :_actor => current_user.unique_id,
65
+ :_timestamp => Time.now.to_f,
66
+ :_domain => 'account',
67
+ :_name => 'upgrade',
68
+ :user_email => current_user.email,
69
+ :plan => 'premium' )
70
+
48
71
  Use Cases
49
72
  ---------
50
73
 
@@ -82,6 +82,7 @@ module WhenAUser
82
82
  user = current_user(env)
83
83
  event.merge!(:current_user => user) if user
84
84
  event.merge!(:referer_url => request.referer) if request.referer
85
+ event.merge!(:rails_env => Rails.env) if defined?(Rails)
85
86
  event.merge!(@options[:custom_data].call(env))
86
87
  event
87
88
  end
@@ -18,15 +18,23 @@ module WhenAUser
18
18
  def call(env)
19
19
  before = Time.now
20
20
  status, headers, response = @app.call(env)
21
+ [status, headers, response]
22
+ rescue Exception => e
23
+ status = 500
24
+ raise e
25
+ ensure
21
26
  after = Time.now
22
27
  request = ActionDispatch::Request.new(env)
23
28
  WhenAUser.send_event event(env, request, status, after - before) unless should_be_ignored(env, request)
24
- [status, headers, response]
25
29
  end
26
30
 
27
31
  private
32
+ def rails_asset_request?(env, request)
33
+ defined?(Rails) && env['action_controller.instance'].nil?
34
+ end
35
+
28
36
  def should_be_ignored(env, request)
29
- (defined?(Rails) && env['action_controller.instance'].nil?) ||
37
+ rails_asset_request?(env, request) ||
30
38
  from_crawler(@options[:ignore_crawlers], env['HTTP_USER_AGENT']) ||
31
39
  conditionally_ignored(@options[:ignore_if], env)
32
40
  end
@@ -36,7 +44,7 @@ module WhenAUser
36
44
  rescue Exception => ex
37
45
  false
38
46
  end
39
-
47
+
40
48
  def event_name(request)
41
49
  if (params = request.params)['controller']
42
50
  "#{params['controller']}##{params['action']}"
@@ -59,6 +67,7 @@ module WhenAUser
59
67
  :duration => "%.2f" % (duration * 1000)
60
68
  }
61
69
  event.merge!(:referer_url => request.referer) if request.referer
70
+ event.merge!(:rails_env => Rails.env) if defined?(Rails)
62
71
  event.merge!(@options[:custom_data].call(env))
63
72
  event
64
73
  end
@@ -0,0 +1,75 @@
1
+ require 'rails/railtie'
2
+ require 'action_view/log_subscriber'
3
+ require 'action_controller/log_subscriber'
4
+
5
+ module Whenauser
6
+ class RailsConfigurator
7
+ attr_accessor :token, :webhook_url, :middlewares
8
+ def initialize
9
+ @webhook_url = 'http://whenauser.com/events/'
10
+ @middlewares = {}
11
+ end
12
+
13
+ def token(token)
14
+ @token = token
15
+ end
16
+
17
+ def webhook_url(webhook_url)
18
+ @webhook_url = webhook_url
19
+ end
20
+
21
+ def middleware(middleware, &block)
22
+ @middlewares[middleware] = MiddlewareConfigurator.apply(&block)
23
+ end
24
+ end
25
+
26
+ class MiddlewareConfigurator
27
+ attr_accessor :configuration
28
+
29
+ def self.apply(&block)
30
+ x = new
31
+ x.configure(&block)
32
+ x
33
+ end
34
+
35
+ def initialize
36
+ @configuration = {}
37
+ end
38
+
39
+ def configure(&block)
40
+ instance_eval &block
41
+ end
42
+
43
+ def method_missing(mid, *args, &block)
44
+ mname = mid.id2name
45
+ if block_given?
46
+ @configuration[mname.to_sym] = *block
47
+ else
48
+ if args.size == 1
49
+ @configuration[mname.to_sym] = args.first
50
+ else
51
+ @configuration[mname.to_sym] = args
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ class Railtie < Rails::Railtie
58
+ initializer :whenauser do |app|
59
+ filename = Rails.root.join('config/whenauser.rb')
60
+ if File.exists?(filename)
61
+ Whenauser::RailsConfigurator.new.instance_eval do
62
+ eval IO.read(filename), binding, filename.to_s, 1
63
+ if defined?(::Rails.configuration) && ::Rails.configuration.respond_to?(:middleware)
64
+ ::Rails.configuration.middleware.insert_after 'Rack::Lock', 'WhenAUser::Rack',
65
+ :webhook_url => @webhook_url,
66
+ :token => @token
67
+ ::Rails.configuration.middleware.use('WhenAUser::Exceptions', @middlewares[:exceptions].configuration) if @middlewares.has_key?(:exceptions)
68
+ puts "configuration with: #{@middlewares[:pageviews].configuration}"
69
+ ::Rails.configuration.middleware.insert_after('WhenAUser::Rack', 'WhenAUser::Pageviews', @middlewares[:pageviews].configuration) if @middlewares.has_key?(:pageviews)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -1,3 +1,3 @@
1
1
  module WhenAUser
2
- VERSION = '0.2.3'
2
+ VERSION = '0.3.0'
3
3
  end
data/lib/whenauser.rb CHANGED
@@ -39,9 +39,11 @@ module WhenAUser
39
39
 
40
40
  def call(env)
41
41
  WhenAUser.queue = []
42
- status, headers, response = @app.call(env)
42
+ @app.call(env)
43
+ ensure
43
44
  WhenAUser.flush
44
- [status, headers, response]
45
45
  end
46
46
  end
47
47
  end
48
+
49
+ require 'whenauser/railtie' if defined?(Rails)
data/whenauser.gemspec CHANGED
@@ -5,7 +5,7 @@ require 'whenauser/version'
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'whenauser'
7
7
  s.version = WhenAUser::VERSION
8
- s.authors = ['David Anderson']
8
+ s.authors = ['David Anderson', 'Chris Weis']
9
9
  s.email = ['david@alpinegizmo.com']
10
10
  s.homepage = 'https://github.com/tractionlabs/whenauser'
11
11
  s.summary = %q{Rack middleware for connecting to WhenAUser}
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: whenauser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - David Anderson
9
+ - Chris Weis
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2012-07-20 00:00:00.000000000 Z
13
+ date: 2012-07-27 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: activesupport
@@ -90,6 +91,7 @@ files:
90
91
  - lib/whenauser/exceptions.rb
91
92
  - lib/whenauser/helpers.rb
92
93
  - lib/whenauser/pageviews.rb
94
+ - lib/whenauser/railtie.rb
93
95
  - lib/whenauser/version.rb
94
96
  - whenauser.gemspec
95
97
  homepage: https://github.com/tractionlabs/whenauser