ahoy_matey 1.1.1 → 1.2.0

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.
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: