ahoy_matey 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/Gemfile +1 -1
  4. data/README.md +43 -7
  5. data/Rakefile +1 -1
  6. data/ahoy_matey.gemspec +4 -4
  7. data/app/controllers/ahoy/base_controller.rb +0 -1
  8. data/app/controllers/ahoy/events_controller.rb +0 -2
  9. data/app/controllers/ahoy/visits_controller.rb +0 -2
  10. data/lib/ahoy.rb +9 -0
  11. data/lib/ahoy/controller.rb +0 -2
  12. data/lib/ahoy/deckhands/location_deckhand.rb +13 -3
  13. data/lib/ahoy/deckhands/request_deckhand.rb +0 -1
  14. data/lib/ahoy/deckhands/technology_deckhand.rb +0 -2
  15. data/lib/ahoy/deckhands/traffic_source_deckhand.rb +0 -2
  16. data/lib/ahoy/deckhands/utm_parameter_deckhand.rb +1 -3
  17. data/lib/ahoy/engine.rb +6 -11
  18. data/lib/ahoy/geocode_job.rb +0 -1
  19. data/lib/ahoy/logger_silencer.rb +73 -0
  20. data/lib/ahoy/model.rb +1 -4
  21. data/lib/ahoy/stores/active_record_store.rb +1 -3
  22. data/lib/ahoy/stores/active_record_token_store.rb +10 -14
  23. data/lib/ahoy/stores/base_store.rb +1 -3
  24. data/lib/ahoy/stores/fluentd_store.rb +17 -0
  25. data/lib/ahoy/stores/log_store.rb +11 -5
  26. data/lib/ahoy/stores/mongoid_store.rb +0 -2
  27. data/lib/ahoy/subscribers/active_record.rb +0 -2
  28. data/lib/ahoy/tracker.rb +14 -5
  29. data/lib/ahoy/version.rb +1 -1
  30. data/lib/ahoy/visit_properties.rb +2 -4
  31. data/lib/ahoy/warden.rb +1 -1
  32. data/lib/generators/ahoy/stores/active_record_events_generator.rb +1 -2
  33. data/lib/generators/ahoy/stores/active_record_generator.rb +0 -1
  34. data/lib/generators/ahoy/stores/active_record_visits_generator.rb +1 -2
  35. data/lib/generators/ahoy/stores/custom_generator.rb +0 -1
  36. data/lib/generators/ahoy/stores/fluentd_generator.rb +15 -0
  37. data/lib/generators/ahoy/stores/log_generator.rb +0 -1
  38. data/lib/generators/ahoy/stores/mongoid_events_generator.rb +0 -1
  39. data/lib/generators/ahoy/stores/mongoid_generator.rb +0 -2
  40. data/lib/generators/ahoy/stores/mongoid_visits_generator.rb +0 -1
  41. data/lib/generators/ahoy/stores/templates/active_record_event_model.rb +1 -1
  42. data/lib/generators/ahoy/stores/templates/active_record_events_migration.rb +3 -3
  43. data/lib/generators/ahoy/stores/templates/active_record_visits_migration.rb +5 -2
  44. data/lib/generators/ahoy/stores/templates/custom_initializer.rb +0 -2
  45. data/lib/generators/ahoy/stores/templates/fluentd_initializer.rb +3 -0
  46. metadata +8 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 40291bf283651d14352010eda0c253cebed87db6
4
- data.tar.gz: 0ecfe15d70e6be8c3d4078b7148049edad546401
3
+ metadata.gz: cb1cce9c5947f97e0a19216e9427447c769c580d
4
+ data.tar.gz: 736da048bedafb0038ae932c1f76993941d6e95a
5
5
  SHA512:
6
- metadata.gz: bdc0d68f6ef24f2da215fa89a1b0a0a1dcb44b2a85e09eea078c2dc95d2705b776e0dda75e962563261bd7029a1ed28587128ea63129865045ba21fa53929fe9
7
- data.tar.gz: ecd7f16f4c533da8970adc20dae85fdcebb661be1d87872b269ddc7b53ad453ff3b5f72a1f82bc1888f29f77ed390d4e27a21715545f17d7e15c3d51d256ff71
6
+ metadata.gz: c05c1549e95925259447087b65a03351f29b82d99a47790e799f075bfceddafb49d5c20b5f4f20f0f5ac2469739749c56aec74dfa96b7a1f3a5d887a2091a79c
7
+ data.tar.gz: 62ee3cb9f38fdf312b7992bbb41df8ca5341f43743e308973ac71f57ad97a91d5c9225ee0364b165d6886da28613cce2125fc25a46014564e341ac5d41e3e70f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 1.2.0
2
+
3
+ - Added support for PostgreSQL `jsonb` column type
4
+ - Added Fluentd store
5
+ - Added latitude, longitude, and postal_code to visits
6
+ - Log exclusions
7
+
1
8
  ## 1.1.1
2
9
 
3
10
  - Better support for Authlogic
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in ahoy.gemspec
4
4
  gemspec
data/README.md CHANGED
@@ -1,12 +1,14 @@
1
1
  # Ahoy
2
2
 
3
+ :fire: Never build an analytics platform from scratch again.
4
+
3
5
  Ahoy provides a solid foundation to track visits and events in Ruby, JavaScript, and native apps.
4
6
 
5
- :fire: Works with any data store so you can easily scale.
7
+ Works with any data store so you can easily scale.
6
8
 
7
- :postbox: To track emails, check out [Ahoy Email](https://github.com/ankane/ahoy_email).
9
+ :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
8
10
 
9
- Never build an analytics platform from scratch again.
11
+ :postbox: To track emails, check out [Ahoy Email](https://github.com/ankane/ahoy_email).
10
12
 
11
13
  See [upgrade instructions](#upgrading) on how to move to 1.0.
12
14
 
@@ -27,9 +29,26 @@ And add the javascript file in `app/assets/javascripts/application.js` after jQu
27
29
 
28
30
  ## Choose a Data Store
29
31
 
32
+ Ahoy supports a number of data stores out of the box. You can start with one of them and customize as needed, or create your own store from scratch.
33
+
34
+ - [PostgreSQL](#PostgreSQL)
35
+ - [MySQL](#MySQL-or-SQLite)
36
+ - [SQLite](#MySQL-or-SQLite)
37
+ - [MongoDB](#MongoDB)
38
+ - [Fluentd](#Fluentd)
39
+ - [Logs](#Logs)
40
+ - [Custom](#Custom)
41
+
30
42
  ### PostgreSQL
31
43
 
32
- For Rails 4 and PostgreSQL 9.2 or greater, use:
44
+ For Rails 4 and PostgreSQL 9.4 or greater, use:
45
+
46
+ ```sh
47
+ rails generate ahoy:stores:active_record -d postgresql-jsonb
48
+ rake db:migrate
49
+ ```
50
+
51
+ For Rails 4 and PostgreSQL 9.2 and 9.3, use:
33
52
 
34
53
  ```sh
35
54
  rails generate ahoy:stores:active_record -d postgresql
@@ -60,12 +79,28 @@ rails generate ahoy:stores:active_record_visits
60
79
  rake db:migrate
61
80
  ```
62
81
 
63
- ### Mongoid
82
+ ### MongoDB
64
83
 
65
84
  ```sh
66
85
  rails generate ahoy:stores:mongoid
67
86
  ```
68
87
 
88
+ ### Fluentd
89
+
90
+ Add [fluent-logger](https://github.com/fluent/fluent-logger-ruby) to your Gemfile.
91
+
92
+ ```ruby
93
+ gem 'fluent-logger'
94
+ ```
95
+
96
+ And run:
97
+
98
+ ```sh
99
+ rails generate ahoy:stores:fluentd
100
+ ```
101
+
102
+ Use `ENV["FLUENTD_HOST"]` and `ENV["FLUENTD_PORT"]` to configure.
103
+
69
104
  ### Logs
70
105
 
71
106
  ```sh
@@ -297,7 +332,7 @@ Ahoy.visit_duration = 30.minutes
297
332
 
298
333
  ### ActiveRecord
299
334
 
300
- Let’s associate orders with visits.
335
+ Let’s associate orders with visits. Add a `visit_id` column on orders and do:
301
336
 
302
337
  ```ruby
303
338
  class Order < ActiveRecord::Base
@@ -584,7 +619,8 @@ end
584
619
 
585
620
  ## TODO
586
621
 
587
- - simple dashboard
622
+ - real-time dashboard of visits and events
623
+ - more events for append only stores
588
624
  - turn off modules
589
625
 
590
626
  ## No Ruby?
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
3
 
4
- task :default => :test
4
+ task default: :test
5
5
  Rake::TestTask.new do |t|
6
6
  t.libs << "test"
7
7
  t.pattern = "test/**/*_test.rb"
data/ahoy_matey.gemspec CHANGED
@@ -1,15 +1,15 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
2
+ lib = File.expand_path("../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'ahoy/version'
4
+ require "ahoy/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "ahoy_matey"
8
8
  spec.version = Ahoy::VERSION
9
9
  spec.authors = ["Andrew Kane"]
10
10
  spec.email = ["andrew@chartkick.com"]
11
- spec.summary = %q{Simple, powerful visit tracking for Rails}
12
- spec.description = %q{Simple, powerful visit tracking for Rails}
11
+ spec.summary = "Simple, powerful visit tracking for Rails"
12
+ spec.description = "Simple, powerful visit tracking for Rails"
13
13
  spec.homepage = "https://github.com/ankane/ahoy"
14
14
  spec.license = "MIT"
15
15
 
@@ -6,6 +6,5 @@ module Ahoy
6
6
  def ahoy
7
7
  @ahoy ||= Ahoy::Tracker.new(controller: self, api: true)
8
8
  end
9
-
10
9
  end
11
10
  end
@@ -1,6 +1,5 @@
1
1
  module Ahoy
2
2
  class EventsController < Ahoy::BaseController
3
-
4
3
  def create
5
4
  events =
6
5
  if params[:name]
@@ -29,6 +28,5 @@ module Ahoy
29
28
  end
30
29
  render json: {}
31
30
  end
32
-
33
31
  end
34
32
  end
@@ -1,10 +1,8 @@
1
1
  module Ahoy
2
2
  class VisitsController < BaseController
3
-
4
3
  def create
5
4
  ahoy.track_visit
6
5
  render json: {visit_id: ahoy.visit_id, visitor_id: ahoy.visitor_id}
7
6
  end
8
-
9
7
  end
10
8
  end
data/lib/ahoy.rb CHANGED
@@ -22,7 +22,9 @@ require "ahoy/stores/base_store"
22
22
  require "ahoy/stores/active_record_store"
23
23
  require "ahoy/stores/active_record_token_store"
24
24
  require "ahoy/stores/log_store"
25
+ require "ahoy/stores/fluentd_store"
25
26
  require "ahoy/stores/mongoid_store"
27
+ require "ahoy/logger_silencer"
26
28
  require "ahoy/engine"
27
29
  require "ahoy/warden" if defined?(Warden)
28
30
 
@@ -82,3 +84,10 @@ end
82
84
 
83
85
  ActionController::Base.send :include, Ahoy::Controller
84
86
  ActiveRecord::Base.send(:extend, Ahoy::Model) if defined?(ActiveRecord)
87
+
88
+ Logger.send :include, Ahoy::LoggerSilencer
89
+
90
+ begin
91
+ require "syslog/logger"
92
+ Syslog::Logger.send :include, Ahoy::LoggerSilencer
93
+ rescue LoadError; end
@@ -2,7 +2,6 @@ require "request_store"
2
2
 
3
3
  module Ahoy
4
4
  module Controller
5
-
6
5
  def self.included(base)
7
6
  base.helper_method :current_visit
8
7
  base.helper_method :ahoy
@@ -31,6 +30,5 @@ module Ahoy
31
30
  ahoy.track_visit(defer: !Ahoy.track_visits_immediately)
32
31
  end
33
32
  end
34
-
35
33
  end
36
34
  end
@@ -1,7 +1,6 @@
1
1
  module Ahoy
2
2
  module Deckhands
3
3
  class LocationDeckhand
4
-
5
4
  def initialize(ip)
6
5
  @ip = ip
7
6
  end
@@ -14,14 +13,26 @@ module Ahoy
14
13
  location.try(:state).presence
15
14
  end
16
15
 
16
+ def postal_code
17
+ location.try(:postal_code).presence
18
+ end
19
+
17
20
  def city
18
21
  location.try(:city).presence
19
22
  end
20
23
 
24
+ def latitude
25
+ location.try(:latitude).presence
26
+ end
27
+
28
+ def longitude
29
+ location.try(:longitude).presence
30
+ end
31
+
21
32
  protected
22
33
 
23
34
  def location
24
- if !@checked
35
+ unless @checked
25
36
  @location =
26
37
  begin
27
38
  Geocoder.search(@ip).first
@@ -33,7 +44,6 @@ module Ahoy
33
44
  end
34
45
  @location
35
46
  end
36
-
37
47
  end
38
48
  end
39
49
  end
@@ -43,7 +43,6 @@ module Ahoy
43
43
  def screen_width
44
44
  request.params["screen_width"]
45
45
  end
46
-
47
46
  end
48
47
  end
49
48
  end
@@ -1,7 +1,6 @@
1
1
  module Ahoy
2
2
  module Deckhands
3
3
  class TechnologyDeckhand
4
-
5
4
  def initialize(user_agent)
6
5
  @user_agent = user_agent
7
6
  end
@@ -43,7 +42,6 @@ module Ahoy
43
42
  def self.user_agent_parser
44
43
  @user_agent_parser ||= UserAgentParser::Parser.new
45
44
  end
46
-
47
45
  end
48
46
  end
49
47
  end
@@ -1,7 +1,6 @@
1
1
  module Ahoy
2
2
  module Deckhands
3
3
  class TrafficSourceDeckhand
4
-
5
4
  def initialize(referrer)
6
5
  @referrer = referrer
7
6
  end
@@ -18,7 +17,6 @@ module Ahoy
18
17
  def self.referrer_parser
19
18
  @referrer_parser ||= RefererParser::Parser.new
20
19
  end
21
-
22
20
  end
23
21
  end
24
22
  end
@@ -1,7 +1,6 @@
1
1
  module Ahoy
2
2
  module Deckhands
3
3
  class UtmParameterDeckhand
4
-
5
4
  def initialize(landing_page)
6
5
  @landing_page = landing_page
7
6
  end
@@ -13,12 +12,11 @@ module Ahoy
13
12
  end
14
13
  end
15
14
 
16
- %w[utm_source utm_medium utm_term utm_content utm_campaign].each do |name|
15
+ %w(utm_source utm_medium utm_term utm_content utm_campaign).each do |name|
17
16
  define_method name do
18
17
  landing_params[name]
19
18
  end
20
19
  end
21
-
22
20
  end
23
21
  end
24
22
  end
data/lib/ahoy/engine.rb CHANGED
@@ -1,30 +1,25 @@
1
1
  module Ahoy
2
2
  class Engine < ::Rails::Engine
3
-
4
3
  # from https://github.com/evrone/quiet_assets/blob/master/lib/quiet_assets.rb
5
- initializer "ahoy.middleware", after: "sprockets.environment" do |app|
4
+ initializer "ahoy.middleware", after: "sprockets.environment" do
6
5
  next unless Ahoy.quiet
7
6
 
8
7
  # Parse PATH_INFO by assets prefix
9
- AHOY_PREFIX = "/ahoy/"
10
- KEY = "ahoy.old_level"
8
+ AHOY_PREFIX = "/ahoy/".freeze
11
9
 
12
10
  # Just create an alias for call in middleware
13
11
  Rails::Rack::Logger.class_eval do
14
12
  def call_with_quiet_ahoy(env)
15
- begin
16
- if env["PATH_INFO"].start_with?(AHOY_PREFIX)
17
- env[KEY] = Rails.logger.level
18
- Rails.logger.level = Logger::ERROR
13
+ if env["PATH_INFO"].start_with?(AHOY_PREFIX) && logger.respond_to?(:silence_logger)
14
+ logger.silence_logger do
15
+ call_without_quiet_ahoy(env)
19
16
  end
17
+ else
20
18
  call_without_quiet_ahoy(env)
21
- ensure
22
- Rails.logger.level = env[KEY] if env[KEY]
23
19
  end
24
20
  end
25
21
  alias_method_chain :call, :quiet_ahoy
26
22
  end
27
23
  end
28
-
29
24
  end
30
25
  end
@@ -9,6 +9,5 @@ module Ahoy
9
9
  end
10
10
  visit.save!
11
11
  end
12
-
13
12
  end
14
13
  end
@@ -0,0 +1,73 @@
1
+ # from https://github.com/rails/activerecord-session_store/blob/master/lib/active_record/session_store/extension/logger_silencer.rb
2
+ require "thread"
3
+ require "active_support/core_ext/class/attribute_accessors"
4
+ require "active_support/core_ext/module/aliasing"
5
+ require "active_support/core_ext/module/attribute_accessors"
6
+ require "active_support/concern"
7
+
8
+ module Ahoy
9
+ module LoggerSilencer
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ cattr_accessor :silencer
14
+ self.silencer = true
15
+ alias_method_chain :level, :threadsafety
16
+ alias_method_chain :add, :threadsafety
17
+ end
18
+
19
+ def thread_level
20
+ Thread.current[thread_hash_level_key]
21
+ end
22
+
23
+ def thread_level=(level)
24
+ Thread.current[thread_hash_level_key] = level
25
+ end
26
+
27
+ def level_with_threadsafety
28
+ thread_level || level_without_threadsafety
29
+ end
30
+
31
+ def add_with_threadsafety(severity, message = nil, progname = nil, &block)
32
+ if !defined?(@logdev) || @logdev.nil? || (severity || UNKNOWN) < level
33
+ true
34
+ else
35
+ add_without_threadsafety(severity, message, progname, &block)
36
+ end
37
+ end
38
+
39
+ # Silences the logger for the duration of the block.
40
+ def silence_logger(temporary_level = Logger::ERROR)
41
+ if silencer
42
+ begin
43
+ self.thread_level = temporary_level
44
+ yield self
45
+ ensure
46
+ self.thread_level = nil
47
+ end
48
+ else
49
+ yield self
50
+ end
51
+ end
52
+
53
+ for severity in Logger::Severity.constants
54
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
55
+ def #{severity.downcase}? # def debug?
56
+ Logger::#{severity} >= level # DEBUG >= level
57
+ end # end
58
+ EOT
59
+ end
60
+
61
+ private
62
+
63
+ def thread_hash_level_key
64
+ @thread_hash_level_key ||= :"ThreadSafeLogger##{object_id}@level"
65
+ end
66
+ end
67
+ end
68
+
69
+ class NilLogger
70
+ def self.silence_logger
71
+ yield
72
+ end
73
+ end
data/lib/ahoy/model.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  module Ahoy
2
2
  module Model
3
-
4
3
  def visitable(name = nil, options = {})
5
4
  if name.is_a?(Hash)
6
5
  name = nil
@@ -11,7 +10,7 @@ module Ahoy
11
10
  belongs_to name, options
12
11
  before_create :set_visit
13
12
  end
14
- class_eval %Q{
13
+ class_eval %{
15
14
  def set_visit
16
15
  self.#{name} ||= RequestStore.store[:ahoy].try(:visit)
17
16
  end
@@ -32,9 +31,7 @@ module Ahoy
32
31
  Deckhands::UtmParameterDeckhand.new(landing_page).landing_params
33
32
  end
34
33
  end
35
-
36
34
  end
37
35
  end
38
-
39
36
  end
40
37
  end
@@ -1,7 +1,6 @@
1
1
  module Ahoy
2
2
  module Stores
3
3
  class ActiveRecordStore < BaseStore
4
-
5
4
  def track_visit(options, &block)
6
5
  visit =
7
6
  visit_model.new do |v|
@@ -28,7 +27,7 @@ module Ahoy
28
27
  event_model.new do |e|
29
28
  e.id = options[:id]
30
29
  e.visit_id = ahoy.visit_id
31
- e.user = user
30
+ e.user = user if e.respond_to?(:user=)
32
31
  e.name = name
33
32
  e.properties = properties
34
33
  e.time = options[:time]
@@ -56,7 +55,6 @@ module Ahoy
56
55
  def event_model
57
56
  ::Ahoy::Event
58
57
  end
59
-
60
58
  end
61
59
  end
62
60
  end
@@ -1,7 +1,6 @@
1
1
  module Ahoy
2
2
  module Stores
3
3
  class ActiveRecordTokenStore < BaseStore
4
-
5
4
  def track_visit(options, &block)
6
5
  visit =
7
6
  visit_model.new do |v|
@@ -61,18 +60,18 @@ module Ahoy
61
60
 
62
61
  def exclude?
63
62
  (!Ahoy.track_bots && bot?) ||
64
- (
65
- if Ahoy.exclude_method
66
- warn "[DEPRECATION] Ahoy.exclude_method is deprecated - use exclude? instead"
67
- if Ahoy.exclude_method.arity == 1
68
- Ahoy.exclude_method.call(controller)
63
+ (
64
+ if Ahoy.exclude_method
65
+ warn "[DEPRECATION] Ahoy.exclude_method is deprecated - use exclude? instead"
66
+ if Ahoy.exclude_method.arity == 1
67
+ Ahoy.exclude_method.call(controller)
68
+ else
69
+ Ahoy.exclude_method.call(controller, request)
70
+ end
69
71
  else
70
- Ahoy.exclude_method.call(controller, request)
72
+ false
71
73
  end
72
- else
73
- false
74
- end
75
- )
74
+ )
76
75
  end
77
76
 
78
77
  def user
@@ -89,7 +88,6 @@ module Ahoy
89
88
  end
90
89
 
91
90
  class << self
92
-
93
91
  def uses_deprecated_subscribers
94
92
  warn "[DEPRECATION] Ahoy subscribers are deprecated"
95
93
  @uses_deprecated_subscribers = true
@@ -98,7 +96,6 @@ module Ahoy
98
96
  def uses_deprecated_subscribers?
99
97
  @uses_deprecated_subscribers || false
100
98
  end
101
-
102
99
  end
103
100
 
104
101
  protected
@@ -110,7 +107,6 @@ module Ahoy
110
107
  def event_model
111
108
  ::Ahoy::Event
112
109
  end
113
-
114
110
  end
115
111
  end
116
112
  end
@@ -1,7 +1,6 @@
1
1
  module Ahoy
2
2
  module Stores
3
3
  class BaseStore
4
-
5
4
  def initialize(options)
6
5
  @options = options
7
6
  end
@@ -17,7 +16,7 @@ module Ahoy
17
16
 
18
17
  def authenticate(user)
19
18
  @user = user
20
- if visit and visit.respond_to?(:user) and !visit.user
19
+ if visit && visit.respond_to?(:user) && !visit.user
21
20
  begin
22
21
  visit.user = user
23
22
  visit.save!
@@ -84,7 +83,6 @@ module Ahoy
84
83
  classes << PG::UniqueViolation if defined?(PG::UniqueViolation)
85
84
  classes
86
85
  end
87
-
88
86
  end
89
87
  end
90
88
  end
@@ -0,0 +1,17 @@
1
+ module Ahoy
2
+ module Stores
3
+ class FluentdStore < LogStore
4
+ def log_visit(data)
5
+ logger.post("visit", data)
6
+ end
7
+
8
+ def log_event(data)
9
+ logger.post("event", data)
10
+ end
11
+
12
+ def logger
13
+ @logger ||= Fluent::Logger::FluentLogger.new("ahoy", host: ENV["FLUENTD_HOST"] || "localhost", port: ENV["FLUENTD_PORT"] || 24224)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,18 +1,17 @@
1
1
  module Ahoy
2
2
  module Stores
3
3
  class LogStore < BaseStore
4
-
5
4
  def track_visit(options, &block)
6
5
  data = {
7
6
  id: ahoy.visit_id,
8
- visitor_id: ahoy.visitor_id,
7
+ visitor_id: ahoy.visitor_id
9
8
  }.merge(visit_properties.to_hash)
10
9
  data[:user_id] = user.id if user
11
10
  data[:started_at] = options[:started_at]
12
11
 
13
12
  yield(data) if block_given?
14
13
 
15
- visit_logger.info data.to_json
14
+ log_visit(data)
16
15
  end
17
16
 
18
17
  def track_event(name, properties, options, &block)
@@ -28,11 +27,19 @@ module Ahoy
28
27
 
29
28
  yield(data) if block_given?
30
29
 
31
- event_logger.info data.to_json
30
+ log_event(data)
32
31
  end
33
32
 
34
33
  protected
35
34
 
35
+ def log_visit(data)
36
+ visit_logger.info data.to_json
37
+ end
38
+
39
+ def log_event(data)
40
+ event_logger.info data.to_json
41
+ end
42
+
36
43
  # TODO disable header
37
44
  def visit_logger
38
45
  @visit_logger ||= ActiveSupport::Logger.new(Rails.root.join("log/visits.log"))
@@ -41,7 +48,6 @@ module Ahoy
41
48
  def event_logger
42
49
  @event_logger ||= ActiveSupport::Logger.new(Rails.root.join("log/events.log"))
43
50
  end
44
-
45
51
  end
46
52
  end
47
53
  end
@@ -1,7 +1,6 @@
1
1
  module Ahoy
2
2
  module Stores
3
3
  class MongoidStore < BaseStore
4
-
5
4
  def track_visit(options, &block)
6
5
  visit =
7
6
  visit_model.new do |v|
@@ -59,7 +58,6 @@ module Ahoy
59
58
  token
60
59
  end
61
60
  end
62
-
63
61
  end
64
62
  end
65
63
  end
@@ -1,7 +1,6 @@
1
1
  module Ahoy
2
2
  module Subscribers
3
3
  class ActiveRecord
4
-
5
4
  def initialize(options = {})
6
5
  @model = options[:model] || Ahoy::Event
7
6
  end
@@ -15,7 +14,6 @@ module Ahoy
15
14
  e.time = options[:time]
16
15
  end
17
16
  end
18
-
19
17
  end
20
18
  end
21
19
  end
data/lib/ahoy/tracker.rb CHANGED
@@ -10,7 +10,9 @@ module Ahoy
10
10
  end
11
11
 
12
12
  def track(name, properties = {}, options = {})
13
- unless exclude?
13
+ if exclude?
14
+ debug "Event excluded"
15
+ else
14
16
  options = options.dup
15
17
 
16
18
  options[:time] = trusted_time(options[:time])
@@ -24,7 +26,9 @@ module Ahoy
24
26
  end
25
27
 
26
28
  def track_visit(options = {})
27
- unless exclude?
29
+ if exclude?
30
+ debug "Visit excluded"
31
+ else
28
32
  if options[:defer]
29
33
  set_cookie("ahoy_track", true)
30
34
  else
@@ -41,7 +45,9 @@ module Ahoy
41
45
  end
42
46
 
43
47
  def authenticate(user)
44
- unless exclude?
48
+ if exclude?
49
+ debug "Authentication excluded"
50
+ else
45
51
  @store.authenticate(user)
46
52
  end
47
53
  true
@@ -70,7 +76,7 @@ module Ahoy
70
76
  end
71
77
 
72
78
  def set_visitor_cookie
73
- if !existing_visitor_id
79
+ unless existing_visitor_id
74
80
  set_cookie("ahoy_visitor", visitor_id, Ahoy.visitor_duration)
75
81
  end
76
82
  end
@@ -107,7 +113,7 @@ module Ahoy
107
113
  end
108
114
 
109
115
  def trusted_time(time)
110
- if !time or (@options[:api] and !(1.minute.ago..Time.now).cover?(time))
116
+ if !time || (@options[:api] && !(1.minute.ago..Time.now).cover?(time))
111
117
  Time.zone.now
112
118
  else
113
119
  time
@@ -146,5 +152,8 @@ module Ahoy
146
152
  Ahoy.ensure_uuid(id)
147
153
  end
148
154
 
155
+ def debug(message)
156
+ Rails.logger.debug { "[ahoy] #{message}" }
157
+ end
149
158
  end
150
159
  end
data/lib/ahoy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ahoy
2
- VERSION = "1.1.1"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -1,11 +1,10 @@
1
1
  module Ahoy
2
2
  class VisitProperties
3
-
4
3
  REQUEST_KEYS = [:ip, :user_agent, :referrer, :landing_page, :platform, :app_version, :os_version, :screen_height, :screen_width]
5
4
  TRAFFIC_SOURCE_KEYS = [:referring_domain, :search_keyword]
6
5
  UTM_PARAMETER_KEYS = [:utm_source, :utm_medium, :utm_term, :utm_content, :utm_campaign]
7
6
  TECHNOLOGY_KEYS = [:browser, :os, :device_type]
8
- LOCATION_KEYS = [:country, :region, :city]
7
+ LOCATION_KEYS = [:country, :region, :city, :postal_code, :latitude, :longitude]
9
8
 
10
9
  KEYS = REQUEST_KEYS + TRAFFIC_SOURCE_KEYS + UTM_PARAMETER_KEYS + TECHNOLOGY_KEYS + LOCATION_KEYS
11
10
 
@@ -33,7 +32,7 @@ module Ahoy
33
32
  end
34
33
 
35
34
  def to_hash
36
- keys.inject({}){|memo, key| memo[key] = send(key); memo }
35
+ keys.inject({}) { |memo, key| memo[key] = send(key); memo }
37
36
  end
38
37
 
39
38
  protected
@@ -57,6 +56,5 @@ module Ahoy
57
56
  def location_deckhand
58
57
  @location_deckhand ||= Deckhands::LocationDeckhand.new(request_deckhand.ip)
59
58
  end
60
-
61
59
  end
62
60
  end
data/lib/ahoy/warden.rb CHANGED
@@ -1,4 +1,4 @@
1
- Warden::Manager.after_set_user except: :fetch do |user, auth, opts|
1
+ Warden::Manager.after_set_user except: :fetch do |user, auth, _|
2
2
  request = ActionDispatch::Request.new(auth.env)
3
3
  ahoy = Ahoy::Tracker.new(request: request)
4
4
  ahoy.authenticate(user)
@@ -24,7 +24,7 @@ module Ahoy
24
24
  end
25
25
 
26
26
  def copy_migration
27
- unless options["database"].in?([nil, "postgresql"])
27
+ unless options["database"].in?([nil, "postgresql", "postgresql-jsonb"])
28
28
  raise Thor::Error, "Unknown database option"
29
29
  end
30
30
  migration_template "active_record_events_migration.rb", "db/migrate/create_ahoy_events.rb"
@@ -37,7 +37,6 @@ module Ahoy
37
37
  def create_initializer
38
38
  template "active_record_initializer.rb", "config/initializers/ahoy.rb"
39
39
  end
40
-
41
40
  end
42
41
  end
43
42
  end
@@ -10,7 +10,6 @@ module Ahoy
10
10
  invoke "ahoy:stores:active_record_visits", nil, options
11
11
  invoke "ahoy:stores:active_record_events", nil, options
12
12
  end
13
-
14
13
  end
15
14
  end
16
15
  end
@@ -24,7 +24,7 @@ module Ahoy
24
24
  end
25
25
 
26
26
  def copy_migration
27
- unless options["database"].in?([nil, "postgresql"])
27
+ unless options["database"].in?([nil, "postgresql", "postgresql-jsonb"])
28
28
  raise Thor::Error, "Unknown database option"
29
29
  end
30
30
  migration_template "active_record_visits_migration.rb", "db/migrate/create_visits.rb"
@@ -37,7 +37,6 @@ module Ahoy
37
37
  def create_initializer
38
38
  template "active_record_initializer.rb", "config/initializers/ahoy.rb"
39
39
  end
40
-
41
40
  end
42
41
  end
43
42
  end
@@ -9,7 +9,6 @@ module Ahoy
9
9
  def create_initializer
10
10
  template "custom_initializer.rb", "config/initializers/ahoy.rb"
11
11
  end
12
-
13
12
  end
14
13
  end
15
14
  end
@@ -0,0 +1,15 @@
1
+ require "rails/generators"
2
+
3
+ module Ahoy
4
+ module Stores
5
+ module Generators
6
+ class FluentdGenerator < Rails::Generators::Base
7
+ source_root File.expand_path("../templates", __FILE__)
8
+
9
+ def create_initializer
10
+ template "fluentd_initializer.rb", "config/initializers/ahoy.rb"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -9,7 +9,6 @@ module Ahoy
9
9
  def create_initializer
10
10
  template "log_initializer.rb", "config/initializers/ahoy.rb"
11
11
  end
12
-
13
12
  end
14
13
  end
15
14
  end
@@ -13,7 +13,6 @@ module Ahoy
13
13
  def create_initializer
14
14
  template "mongoid_initializer.rb", "config/initializers/ahoy.rb"
15
15
  end
16
-
17
16
  end
18
17
  end
19
18
  end
@@ -4,12 +4,10 @@ module Ahoy
4
4
  module Stores
5
5
  module Generators
6
6
  class MongoidGenerator < Rails::Generators::Base
7
-
8
7
  def boom
9
8
  invoke "ahoy:stores:mongoid_visits"
10
9
  invoke "ahoy:stores:mongoid_events"
11
10
  end
12
-
13
11
  end
14
12
  end
15
13
  end
@@ -21,7 +21,6 @@ module Ahoy
21
21
  def create_initializer
22
22
  template "mongoid_initializer.rb", "config/initializers/ahoy.rb"
23
23
  end
24
-
25
24
  end
26
25
  end
27
26
  end
@@ -3,7 +3,7 @@ module Ahoy
3
3
  self.table_name = "ahoy_events"
4
4
 
5
5
  belongs_to :visit
6
- belongs_to :user<% if options["database"] != "postgresql" %>
6
+ belongs_to :user<% if options["database"].blank? %>
7
7
 
8
8
  serialize :properties, JSON<% end %>
9
9
  end
@@ -1,15 +1,15 @@
1
1
  class <%= migration_class_name %> < ActiveRecord::Migration
2
2
  def change
3
3
  create_table :ahoy_events, id: false do |t|
4
- t.uuid :id, primary_key: true
5
- t.uuid :visit_id
4
+ t.uuid :id, default: nil, primary_key: true
5
+ t.uuid :visit_id, default: nil
6
6
 
7
7
  # user
8
8
  t.integer :user_id
9
9
  # add t.string :user_type if polymorphic
10
10
 
11
11
  t.string :name
12
- t.<% if options["database"] == "postgresql" %>json<% else %>text<% end %> :properties
12
+ t.<% case options["database"] when "postgresql" %>json<% when "postgresql-jsonb" %>jsonb<% else %>text<% end %> :properties
13
13
  t.timestamp :time
14
14
  end
15
15
 
@@ -1,8 +1,8 @@
1
1
  class <%= migration_class_name %> < ActiveRecord::Migration
2
2
  def change
3
3
  create_table :visits, id: false do |t|
4
- t.uuid :id, primary_key: true
5
- t.uuid :visitor_id
4
+ t.uuid :id, default: nil, primary_key: true
5
+ t.uuid :visitor_id, default: nil
6
6
 
7
7
  # the rest are recommended but optional
8
8
  # simply remove the columns you don't want
@@ -32,6 +32,9 @@ class <%= migration_class_name %> < ActiveRecord::Migration
32
32
  t.string :country
33
33
  t.string :region
34
34
  t.string :city
35
+ t.string :postal_code
36
+ t.decimal :latitude
37
+ t.decimal :longitude
35
38
 
36
39
  # utm parameters
37
40
  t.string :utm_source
@@ -1,5 +1,4 @@
1
1
  class Ahoy::Store < Ahoy::Stores::BaseStore
2
-
3
2
  def track_visit(options)
4
3
  end
5
4
 
@@ -8,5 +7,4 @@ class Ahoy::Store < Ahoy::Stores::BaseStore
8
7
 
9
8
  def current_visit
10
9
  end
11
-
12
10
  end
@@ -0,0 +1,3 @@
1
+ class Ahoy::Store < Ahoy::Stores::FluentdStore
2
+ # customize here
3
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ahoy_matey
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-06 00:00:00.000000000 Z
11
+ date: 2015-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -205,10 +205,12 @@ files:
205
205
  - lib/ahoy/deckhands/utm_parameter_deckhand.rb
206
206
  - lib/ahoy/engine.rb
207
207
  - lib/ahoy/geocode_job.rb
208
+ - lib/ahoy/logger_silencer.rb
208
209
  - lib/ahoy/model.rb
209
210
  - lib/ahoy/stores/active_record_store.rb
210
211
  - lib/ahoy/stores/active_record_token_store.rb
211
212
  - lib/ahoy/stores/base_store.rb
213
+ - lib/ahoy/stores/fluentd_store.rb
212
214
  - lib/ahoy/stores/log_store.rb
213
215
  - lib/ahoy/stores/mongoid_store.rb
214
216
  - lib/ahoy/subscribers/active_record.rb
@@ -221,6 +223,7 @@ files:
221
223
  - lib/generators/ahoy/stores/active_record_generator.rb
222
224
  - lib/generators/ahoy/stores/active_record_visits_generator.rb
223
225
  - lib/generators/ahoy/stores/custom_generator.rb
226
+ - lib/generators/ahoy/stores/fluentd_generator.rb
224
227
  - lib/generators/ahoy/stores/log_generator.rb
225
228
  - lib/generators/ahoy/stores/mongoid_events_generator.rb
226
229
  - lib/generators/ahoy/stores/mongoid_generator.rb
@@ -231,6 +234,7 @@ files:
231
234
  - lib/generators/ahoy/stores/templates/active_record_visit_model.rb
232
235
  - lib/generators/ahoy/stores/templates/active_record_visits_migration.rb
233
236
  - lib/generators/ahoy/stores/templates/custom_initializer.rb
237
+ - lib/generators/ahoy/stores/templates/fluentd_initializer.rb
234
238
  - lib/generators/ahoy/stores/templates/log_initializer.rb
235
239
  - lib/generators/ahoy/stores/templates/mongoid_event_model.rb
236
240
  - lib/generators/ahoy/stores/templates/mongoid_initializer.rb
@@ -258,10 +262,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
258
262
  version: '0'
259
263
  requirements: []
260
264
  rubyforge_project:
261
- rubygems_version: 2.2.2
265
+ rubygems_version: 2.4.5
262
266
  signing_key:
263
267
  specification_version: 4
264
268
  summary: Simple, powerful visit tracking for Rails
265
269
  test_files:
266
270
  - test/test_helper.rb
267
271
  - test/visit_properties_test.rb
272
+ has_rdoc: