octocore 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +117 -0
- data/README.md +50 -0
- data/Rakefile +138 -0
- data/bin/fakestream +258 -0
- data/lib/octocore.rb +141 -0
- data/lib/octocore/baseline.rb +131 -0
- data/lib/octocore/callbacks.rb +78 -0
- data/lib/octocore/config.rb +37 -0
- data/lib/octocore/config/config.yml +1 -0
- data/lib/octocore/config/search/index/user.yml +42 -0
- data/lib/octocore/counter.rb +265 -0
- data/lib/octocore/counter/helpers.rb +168 -0
- data/lib/octocore/helpers.rb +6 -0
- data/lib/octocore/helpers/api_consumer_helper.rb +371 -0
- data/lib/octocore/helpers/api_helper.rb +53 -0
- data/lib/octocore/helpers/api_logger.rb +14 -0
- data/lib/octocore/helpers/client_helper.rb +104 -0
- data/lib/octocore/helpers/kong_helper.rb +156 -0
- data/lib/octocore/helpers/sinatra_helper.rb +22 -0
- data/lib/octocore/kafka_bridge.rb +60 -0
- data/lib/octocore/kldivergence.rb +14 -0
- data/lib/octocore/models.rb +260 -0
- data/lib/octocore/models/contactus.rb +17 -0
- data/lib/octocore/models/enterprise.rb +76 -0
- data/lib/octocore/models/enterprise/api_event.rb +14 -0
- data/lib/octocore/models/enterprise/api_hit.rb +20 -0
- data/lib/octocore/models/enterprise/api_track.rb +13 -0
- data/lib/octocore/models/enterprise/app_init.rb +13 -0
- data/lib/octocore/models/enterprise/app_login.rb +12 -0
- data/lib/octocore/models/enterprise/app_logout.rb +12 -0
- data/lib/octocore/models/enterprise/authorization.rb +61 -0
- data/lib/octocore/models/enterprise/category.rb +14 -0
- data/lib/octocore/models/enterprise/category_baseline.rb +19 -0
- data/lib/octocore/models/enterprise/category_hit.rb +26 -0
- data/lib/octocore/models/enterprise/category_trend.rb +19 -0
- data/lib/octocore/models/enterprise/conversions.rb +69 -0
- data/lib/octocore/models/enterprise/ctr.rb +54 -0
- data/lib/octocore/models/enterprise/dimension_choice.rb +21 -0
- data/lib/octocore/models/enterprise/engagement_time.rb +43 -0
- data/lib/octocore/models/enterprise/funnel_data.rb +20 -0
- data/lib/octocore/models/enterprise/funnels.rb +126 -0
- data/lib/octocore/models/enterprise/gcm.rb +21 -0
- data/lib/octocore/models/enterprise/newsfeed_hit.rb +52 -0
- data/lib/octocore/models/enterprise/notification_hit.rb +42 -0
- data/lib/octocore/models/enterprise/page.rb +15 -0
- data/lib/octocore/models/enterprise/page_view.rb +14 -0
- data/lib/octocore/models/enterprise/pageload_time.rb +43 -0
- data/lib/octocore/models/enterprise/product.rb +22 -0
- data/lib/octocore/models/enterprise/product_baseline.rb +20 -0
- data/lib/octocore/models/enterprise/product_hit.rb +26 -0
- data/lib/octocore/models/enterprise/product_page_view.rb +13 -0
- data/lib/octocore/models/enterprise/product_trend.rb +18 -0
- data/lib/octocore/models/enterprise/push_key.rb +15 -0
- data/lib/octocore/models/enterprise/rules.rb +45 -0
- data/lib/octocore/models/enterprise/segment.rb +65 -0
- data/lib/octocore/models/enterprise/segment_data.rb +22 -0
- data/lib/octocore/models/enterprise/tag.rb +14 -0
- data/lib/octocore/models/enterprise/tag_baseline.rb +19 -0
- data/lib/octocore/models/enterprise/tag_hit.rb +26 -0
- data/lib/octocore/models/enterprise/tag_trend.rb +19 -0
- data/lib/octocore/models/enterprise/template.rb +18 -0
- data/lib/octocore/models/plans.rb +17 -0
- data/lib/octocore/models/subscribe.rb +12 -0
- data/lib/octocore/models/user.rb +22 -0
- data/lib/octocore/models/user/push_token.rb +15 -0
- data/lib/octocore/models/user/user_browser_details.rb +16 -0
- data/lib/octocore/models/user/user_location_history.rb +15 -0
- data/lib/octocore/models/user/user_persona.rb +101 -0
- data/lib/octocore/models/user/user_phone_details.rb +17 -0
- data/lib/octocore/models/user/user_profile.rb +20 -0
- data/lib/octocore/models/user/user_timeline.rb +111 -0
- data/lib/octocore/record.rb +20 -0
- data/lib/octocore/schedeuleable.rb +20 -0
- data/lib/octocore/scheduler.rb +59 -0
- data/lib/octocore/search.rb +5 -0
- data/lib/octocore/search/client.rb +33 -0
- data/lib/octocore/search/indexer.rb +0 -0
- data/lib/octocore/search/searchable.rb +18 -0
- data/lib/octocore/search/setup.rb +71 -0
- data/lib/octocore/segment.rb +285 -0
- data/lib/octocore/stats.rb +33 -0
- data/lib/octocore/trendable.rb +88 -0
- data/lib/octocore/trends.rb +158 -0
- data/lib/octocore/utils.rb +90 -0
- data/lib/octocore/version.rb +4 -0
- data/spec/lib/stats_spec.rb +20 -0
- data/spec/spec_helper.rb +103 -0
- metadata +436 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'cequel'
|
2
|
+
require 'octocore/record'
|
3
|
+
|
4
|
+
module Octo
|
5
|
+
|
6
|
+
# Choices for dimensions
|
7
|
+
class DimensionChoice
|
8
|
+
|
9
|
+
include Cequel::Record
|
10
|
+
include Octo::Record
|
11
|
+
|
12
|
+
belongs_to :enterprise, class_name: 'Octo::Enterprise'
|
13
|
+
|
14
|
+
key :dimension, :int
|
15
|
+
column :choice, :text
|
16
|
+
|
17
|
+
timestamps
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'cequel/record'
|
2
|
+
|
3
|
+
module Octo
|
4
|
+
|
5
|
+
class EngagementTime
|
6
|
+
include Cequel::Record
|
7
|
+
|
8
|
+
# Types of Engagement
|
9
|
+
NEWSFEED = 0
|
10
|
+
|
11
|
+
belongs_to :enterprise, class_name: 'Octo::Enterprise'
|
12
|
+
key :engagement_type, :int
|
13
|
+
key :counter_type, :int
|
14
|
+
key :ts, :timestamp
|
15
|
+
|
16
|
+
column :time, :int
|
17
|
+
|
18
|
+
timestamps
|
19
|
+
|
20
|
+
def self.fakedata(args)
|
21
|
+
res = self.where(args)
|
22
|
+
enterprise = Octo::Enterprise.find_by_id(args[:enterprise_id])
|
23
|
+
if res.count == 0 and enterprise.fakedata?
|
24
|
+
res = []
|
25
|
+
ts = args.fetch(ts, 7.days.ago..Time.now.floor)
|
26
|
+
if ts.class == Range
|
27
|
+
start_time = ts.begin.beginning_of_day
|
28
|
+
end_time = ts.end.end_of_day
|
29
|
+
start_time.to(end_time, 1.day).each do |_ts|
|
30
|
+
_args = args.merge({ ts: _ts, time: (rand(5.0..7.0)*60).to_i })
|
31
|
+
res << self.new(_args).save!
|
32
|
+
end
|
33
|
+
elsif ts.class == Time
|
34
|
+
_args = args.merge({ time: (rand(5.0..7.0)).to_i })
|
35
|
+
res << self.new(args).save!
|
36
|
+
end
|
37
|
+
end
|
38
|
+
res
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'cequel'
|
2
|
+
require 'octocore/record'
|
3
|
+
|
4
|
+
module Octo
|
5
|
+
|
6
|
+
# Stores the data for funnels
|
7
|
+
class FunnelData
|
8
|
+
include Cequel::Record
|
9
|
+
include Octo::Record
|
10
|
+
|
11
|
+
belongs_to :enterprise, class_name: 'Octo::Enterprise'
|
12
|
+
|
13
|
+
key :funnel_slug, :text
|
14
|
+
|
15
|
+
key :ts, :timestamp
|
16
|
+
list :value, :float
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'cequel'
|
2
|
+
require 'octocore/record'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Octo
|
6
|
+
|
7
|
+
# Stores the funnel for the enterprise
|
8
|
+
class Funnel
|
9
|
+
include Cequel::Record
|
10
|
+
include Octo::Record
|
11
|
+
|
12
|
+
belongs_to :enterprise, class_name: 'Octo::Enterprise'
|
13
|
+
|
14
|
+
key :name_slug, :text
|
15
|
+
list :funnel, :text
|
16
|
+
|
17
|
+
column :name, :text
|
18
|
+
column :active, :boolean
|
19
|
+
|
20
|
+
timestamps
|
21
|
+
|
22
|
+
before_create :create_name_slug, :activate_funnel
|
23
|
+
|
24
|
+
after_create :populate_with_fake_data
|
25
|
+
|
26
|
+
# Creates name slug
|
27
|
+
def create_name_slug
|
28
|
+
self.name_slug = self.name.to_slug
|
29
|
+
end
|
30
|
+
|
31
|
+
# Activates a funnel
|
32
|
+
def activate_funnel
|
33
|
+
self.active = true
|
34
|
+
end
|
35
|
+
|
36
|
+
# Generates a new funnel from the pages provided
|
37
|
+
# @param [Array] pages The pages array. This array could contain instances
|
38
|
+
# of either String, Octo::Product or Octo::Page.
|
39
|
+
# If string, it will be assumed that these are routeurls for pages or
|
40
|
+
# products.
|
41
|
+
# If the class is explicitly specified, it will be used.
|
42
|
+
# @param [Hash] opts The options for creating funnel
|
43
|
+
# @option opts [String] :name The name of the funnel
|
44
|
+
# @option opts [String] :enterprise_id The enterprise ID for whom funnel is
|
45
|
+
# being created
|
46
|
+
# @return [Octo::Funnel] The funnel created
|
47
|
+
def self.from_pages(pages, opts = {})
|
48
|
+
funnel_length = pages.count
|
49
|
+
return nil if funnel_length.zero?
|
50
|
+
|
51
|
+
funnel = Array.new
|
52
|
+
enterprise_id = opts.fetch(:enterprise_id, nil)
|
53
|
+
|
54
|
+
# Check if they are Octo::Product or Octo::Page instantces and handle
|
55
|
+
if ::Set.new([Octo::Product, Octo::Page]).include?(pages[0].class)
|
56
|
+
funnel = pages.collect { |p| p.routeurl }
|
57
|
+
enterprise_id = pages[0].enterprise_id
|
58
|
+
elsif pages[0].class == String
|
59
|
+
funnel = pages
|
60
|
+
end
|
61
|
+
|
62
|
+
# Create a new funnel
|
63
|
+
self.new(
|
64
|
+
enterprise_id: enterprise_id,
|
65
|
+
name: opts.fetch(:name),
|
66
|
+
funnel: funnel
|
67
|
+
).save!
|
68
|
+
end
|
69
|
+
|
70
|
+
# Populates a newly created funnel with some fake data
|
71
|
+
# @param [Fixnum] days The number of days for which data to be faked
|
72
|
+
def populate_with_fake_data(interval_days = 7)
|
73
|
+
if self.enterprise.fakedata?
|
74
|
+
today = Time.now.beginning_of_day
|
75
|
+
(today - interval_days.days).to(today, 24.hour).each do |ts|
|
76
|
+
Octo::FunnelData.new(
|
77
|
+
enterprise_id: self.enterprise_id,
|
78
|
+
funnel_slug: self.name_slug,
|
79
|
+
ts: ts,
|
80
|
+
value: fake_data(self.funnel.count)
|
81
|
+
).save!
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns data for a funnel
|
87
|
+
# @return [Octo::FunnelData] The Octo funnel data
|
88
|
+
def data(ts = Time.now.floor)
|
89
|
+
args = {
|
90
|
+
enterprise_id: self.enterprise.id,
|
91
|
+
funnel_slug: self.name_slug,
|
92
|
+
ts: ts
|
93
|
+
}
|
94
|
+
res = Octo::FunnelData.where(args)
|
95
|
+
if res.count > 0
|
96
|
+
res.first
|
97
|
+
elsif self.enterprise.fakedata?
|
98
|
+
args.merge!({ value: fake_data(self.funnel.count) })
|
99
|
+
Octo::FunnelData.new(args).save!
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
# Generates fake data for funnel
|
106
|
+
# @param [Fixnum] n The length of funnel
|
107
|
+
# @return [Array] An array containing the funnel value
|
108
|
+
def fake_data(n)
|
109
|
+
fun = Array.new(n)
|
110
|
+
max_dropoff = 100/n
|
111
|
+
n.times do |i|
|
112
|
+
if i == 0
|
113
|
+
fun[i] = 100.0
|
114
|
+
else
|
115
|
+
fun[i] = fun[i-1] - rand(1..max_dropoff)
|
116
|
+
if fun[i] < 0
|
117
|
+
fun[i] = rand(0...fun[i].abs)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
fun
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'cequel'
|
2
|
+
|
3
|
+
module Octo
|
4
|
+
|
5
|
+
# Storage for Notifications
|
6
|
+
class GcmNotification
|
7
|
+
include Cequel::Record
|
8
|
+
|
9
|
+
belongs_to :enterprise, class_name: 'Octo::Enterprise'
|
10
|
+
|
11
|
+
key :gcmid, :varchar
|
12
|
+
key :userid, :bigint
|
13
|
+
|
14
|
+
column :score, :float
|
15
|
+
column :ack, :boolean
|
16
|
+
column :sent_at, :timestamp
|
17
|
+
column :recieved_at, :timestamp
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'cequel'
|
2
|
+
|
3
|
+
require 'octocore/counter'
|
4
|
+
require 'octocore/schedeuleable'
|
5
|
+
|
6
|
+
module Octo
|
7
|
+
|
8
|
+
class NewsfeedHit
|
9
|
+
include Cequel::Record
|
10
|
+
extend Octo::Counter
|
11
|
+
|
12
|
+
extend Octo::Scheduleable
|
13
|
+
|
14
|
+
COUNTERS = 20
|
15
|
+
|
16
|
+
# Specify that we do not want any granularity more than
|
17
|
+
# TYPE_DAY
|
18
|
+
max_type Octo::Counter::TYPE_DAY
|
19
|
+
|
20
|
+
belongs_to :enterprise, class_name: 'Octo::Enterprise'
|
21
|
+
|
22
|
+
countables
|
23
|
+
|
24
|
+
def self.fakedata(args)
|
25
|
+
res = self.where(args)
|
26
|
+
|
27
|
+
enterprise = Octo::Enterprise.find_by_id(args[:enterprise_id])
|
28
|
+
if res.count == 0 and enterprise.fakedata?
|
29
|
+
unless args.has_key?(:uid)
|
30
|
+
args[:uid] = 'newsfeed'
|
31
|
+
end
|
32
|
+
res = []
|
33
|
+
ts = args.fetch(:ts, 7.days.ago..Time.now)
|
34
|
+
if ts.class == Range
|
35
|
+
start_ts = ts.begin.beginning_of_day
|
36
|
+
end_ts = ts.end.end_of_day
|
37
|
+
start_ts.to(end_ts, 1.day).each do |_ts|
|
38
|
+
_args = args.merge({ ts: _ts, count: rand(400..700) })
|
39
|
+
res << self.new(_args).save!
|
40
|
+
end
|
41
|
+
elsif ts.class == Time
|
42
|
+
_args = args.merge({ count: rand(400..800) })
|
43
|
+
res << self.new(_args).save!
|
44
|
+
end
|
45
|
+
end
|
46
|
+
res
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'cequel'
|
2
|
+
|
3
|
+
require 'octocore/counter'
|
4
|
+
require 'octocore/schedeuleable'
|
5
|
+
|
6
|
+
module Octo
|
7
|
+
|
8
|
+
# Counters for notifications sent
|
9
|
+
class NotificationHit
|
10
|
+
|
11
|
+
include Cequel::Record
|
12
|
+
extend Octo::Counter
|
13
|
+
extend Octo::Scheduleable
|
14
|
+
|
15
|
+
max_type Octo::Counter::TYPE_DAY
|
16
|
+
|
17
|
+
belongs_to :enterprise, class_name: 'Octo::Enterprise'
|
18
|
+
|
19
|
+
countables
|
20
|
+
|
21
|
+
def self.time_slots
|
22
|
+
Array.new(6) { |i| "s_#{ i }" }
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.fakedata(args)
|
26
|
+
opts = {
|
27
|
+
bod: false,
|
28
|
+
step: 1.day
|
29
|
+
}
|
30
|
+
self.time_slots.concat([:ios, :android]).inject([]) do |res, uid|
|
31
|
+
values = {
|
32
|
+
count: rand(500..900),
|
33
|
+
}
|
34
|
+
_args = args.merge(uid: uid)
|
35
|
+
res << self.fake_data_with(_args, values, opts)
|
36
|
+
res.flatten
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'cequel/record'
|
2
|
+
|
3
|
+
module Octo
|
4
|
+
|
5
|
+
class PageloadTime
|
6
|
+
include Cequel::Record
|
7
|
+
|
8
|
+
# Types of pageloads
|
9
|
+
NEWSFEED = 0
|
10
|
+
|
11
|
+
belongs_to :enterprise, class_name: 'Octo::Enterprise'
|
12
|
+
key :pageload_type, :int
|
13
|
+
key :counter_type, :int
|
14
|
+
key :ts, :timestamp
|
15
|
+
|
16
|
+
column :time, :int
|
17
|
+
|
18
|
+
timestamps
|
19
|
+
|
20
|
+
def self.fakedata(args)
|
21
|
+
res = self.where(args)
|
22
|
+
enterprise = Octo::Enterprise.find_by_id(args[:enterprise_id])
|
23
|
+
if res.count == 0 and enterprise.fakedata?
|
24
|
+
res = []
|
25
|
+
ts = args.fetch(ts, 7.days.ago..Time.now.floor)
|
26
|
+
if ts.class == Range
|
27
|
+
start_time = ts.begin.beginning_of_day
|
28
|
+
end_time = ts.end.end_of_day
|
29
|
+
start_time.to(end_time, 1.day).each do |_ts|
|
30
|
+
_args = args.merge({ ts: _ts, time: (rand(5.0..7.0)*60).to_i })
|
31
|
+
res << self.new(_args).save!
|
32
|
+
end
|
33
|
+
elsif ts.class == Time
|
34
|
+
_args = args.merge({ time: (rand(5.0..7.0)).to_i })
|
35
|
+
res << self.new(args).save!
|
36
|
+
end
|
37
|
+
end
|
38
|
+
res
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'cequel'
|
2
|
+
require 'octocore/record'
|
3
|
+
|
4
|
+
module Octo
|
5
|
+
class Product
|
6
|
+
include Cequel::Record
|
7
|
+
include Octo::Record
|
8
|
+
|
9
|
+
belongs_to :enterprise, class_name: 'Octo::Enterprise'
|
10
|
+
|
11
|
+
key :id, :bigint
|
12
|
+
|
13
|
+
column :price, :float
|
14
|
+
column :name, :text
|
15
|
+
column :routeurl, :text
|
16
|
+
|
17
|
+
set :categories, :text
|
18
|
+
set :tags, :text
|
19
|
+
|
20
|
+
timestamps
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'cequel'
|
2
|
+
|
3
|
+
require 'octocore/baseline'
|
4
|
+
require 'octocore/schedeuleable'
|
5
|
+
|
6
|
+
module Octo
|
7
|
+
class ProductBaseline
|
8
|
+
include Cequel::Record
|
9
|
+
extend Octo::Baseline
|
10
|
+
extend Octo::Scheduleable
|
11
|
+
|
12
|
+
belongs_to :enterprise, class_name: 'Octo::Enterprise'
|
13
|
+
|
14
|
+
baselineable
|
15
|
+
|
16
|
+
# Specify the type of counter
|
17
|
+
baseline_for 'Octo::ProductHit'
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|