kameleoon-client-ruby 3.2.0 → 3.4.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.
- checksums.yaml +4 -4
- data/lib/kameleoon/configuration/custom_data_info.rb +16 -8
- data/lib/kameleoon/configuration/data_file.rb +40 -17
- data/lib/kameleoon/configuration/feature_flag.rb +10 -0
- data/lib/kameleoon/configuration/rule.rb +4 -0
- data/lib/kameleoon/configuration/settings.rb +13 -8
- data/lib/kameleoon/configuration/variation_exposition.rb +4 -0
- data/lib/kameleoon/data/browser.rb +4 -0
- data/lib/kameleoon/data/conversion.rb +4 -0
- data/lib/kameleoon/data/cookie.rb +4 -0
- data/lib/kameleoon/data/custom_data.rb +11 -3
- data/lib/kameleoon/data/data.rb +30 -4
- data/lib/kameleoon/data/device.rb +4 -0
- data/lib/kameleoon/data/geolocation.rb +5 -0
- data/lib/kameleoon/data/kcs_heat.rb +16 -0
- data/lib/kameleoon/data/manager/assigned_variation.rb +5 -0
- data/lib/kameleoon/data/manager/data_array_storage.rb +7 -0
- data/lib/kameleoon/data/manager/data_map_storage.rb +7 -0
- data/lib/kameleoon/data/manager/page_view_visit.rb +4 -0
- data/lib/kameleoon/data/manager/visitor.rb +198 -67
- data/lib/kameleoon/data/manager/visitor_manager.rb +54 -17
- data/lib/kameleoon/data/mapping_identifier.rb +33 -0
- data/lib/kameleoon/data/operating_system.rb +4 -0
- data/lib/kameleoon/data/page_view.rb +6 -1
- data/lib/kameleoon/data/unique_identifier.rb +11 -0
- data/lib/kameleoon/data/user_agent.rb +4 -0
- data/lib/kameleoon/data/visitor_visits.rb +12 -1
- data/lib/kameleoon/hybrid/manager.rb +13 -4
- data/lib/kameleoon/kameleoon_client.rb +348 -146
- data/lib/kameleoon/kameleoon_client_config.rb +64 -17
- data/lib/kameleoon/kameleoon_client_factory.rb +15 -2
- data/lib/kameleoon/logging/default_logger.rb +20 -0
- data/lib/kameleoon/logging/kameleoon_logger.rb +77 -0
- data/lib/kameleoon/logging/logger.rb +12 -0
- data/lib/kameleoon/managers/data/data_manager.rb +36 -0
- data/lib/kameleoon/managers/remote_data/remote_data_manager.rb +33 -18
- data/lib/kameleoon/managers/remote_data/remote_visitor_data.rb +42 -16
- data/lib/kameleoon/managers/tracking/tracking_builder.rb +149 -0
- data/lib/kameleoon/managers/tracking/tracking_manager.rb +97 -0
- data/lib/kameleoon/managers/tracking/visitor_tracking_registry.rb +94 -0
- data/lib/kameleoon/managers/warehouse/warehouse_manager.rb +22 -5
- data/lib/kameleoon/network/access_token_source.rb +46 -14
- data/lib/kameleoon/network/cookie/cookie_manager.rb +45 -7
- data/lib/kameleoon/network/net_provider.rb +2 -3
- data/lib/kameleoon/network/network_manager.rb +16 -21
- data/lib/kameleoon/network/request.rb +14 -3
- data/lib/kameleoon/network/response.rb +4 -0
- data/lib/kameleoon/network/url_provider.rb +11 -10
- data/lib/kameleoon/real_time/real_time_configuration_service.rb +10 -11
- data/lib/kameleoon/sdk_version.rb +31 -0
- data/lib/kameleoon/targeting/condition.rb +6 -2
- data/lib/kameleoon/targeting/condition_factory.rb +3 -0
- data/lib/kameleoon/targeting/conditions/browser_condition.rb +3 -3
- data/lib/kameleoon/targeting/conditions/cookie_condition.rb +10 -10
- data/lib/kameleoon/targeting/conditions/geolocation_condition.rb +0 -1
- data/lib/kameleoon/targeting/conditions/kcs_heat_range_condition.rb +37 -0
- data/lib/kameleoon/targeting/conditions/number_condition.rb +4 -4
- data/lib/kameleoon/targeting/conditions/operating_system_condition.rb +1 -2
- data/lib/kameleoon/targeting/conditions/sdk_language_condition.rb +2 -1
- data/lib/kameleoon/targeting/conditions/segment_condition.rb +3 -3
- data/lib/kameleoon/targeting/conditions/string_value_condition.rb +2 -1
- data/lib/kameleoon/targeting/conditions/target_feature_flag_condition.rb +7 -11
- data/lib/kameleoon/targeting/conditions/time_elapsed_since_visit_condition.rb +1 -2
- data/lib/kameleoon/targeting/conditions/visit_number_today_condition.rb +4 -4
- data/lib/kameleoon/targeting/conditions/visit_number_total_condition.rb +5 -3
- data/lib/kameleoon/targeting/conditions/visitor_new_return_condition.rb +7 -6
- data/lib/kameleoon/targeting/models.rb +0 -14
- data/lib/kameleoon/targeting/targeting_manager.rb +37 -7
- data/lib/kameleoon/targeting/tree_builder.rb +10 -5
- data/lib/kameleoon/types/remote_visitor_data_filter.rb +21 -3
- data/lib/kameleoon/types/variable.rb +21 -0
- data/lib/kameleoon/types/variation.rb +22 -0
- data/lib/kameleoon/utils.rb +18 -0
- data/lib/kameleoon/version.rb +1 -27
- metadata +16 -2
|
@@ -5,12 +5,15 @@ require 'kameleoon/data/browser'
|
|
|
5
5
|
require 'kameleoon/data/conversion'
|
|
6
6
|
require 'kameleoon/data/custom_data'
|
|
7
7
|
require 'kameleoon/data/device'
|
|
8
|
+
require 'kameleoon/data/kcs_heat'
|
|
8
9
|
require 'kameleoon/data/page_view'
|
|
10
|
+
require 'kameleoon/data/unique_identifier'
|
|
9
11
|
require 'kameleoon/data/user_agent'
|
|
10
12
|
require 'kameleoon/data/manager/assigned_variation'
|
|
11
13
|
require 'kameleoon/data/manager/page_view_visit'
|
|
12
14
|
require 'kameleoon/data/manager/data_map_storage'
|
|
13
15
|
require 'kameleoon/data/manager/data_array_storage'
|
|
16
|
+
require 'kameleoon/logging/kameleoon_logger'
|
|
14
17
|
|
|
15
18
|
module Kameleoon
|
|
16
19
|
module DataManager
|
|
@@ -18,129 +21,265 @@ module Kameleoon
|
|
|
18
21
|
# Visitor is a container of all data assigned to a visitor.
|
|
19
22
|
# It is thread-safe
|
|
20
23
|
class Visitor
|
|
21
|
-
attr_reader :
|
|
22
|
-
attr_accessor :legal_consent, :mapping_identifier
|
|
24
|
+
attr_reader :data, :is_unique_identifier
|
|
23
25
|
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
def to_s
|
|
27
|
+
"Visitor{}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def initialize(source = nil)
|
|
31
|
+
if source.nil?
|
|
32
|
+
@data = VisitorData.new
|
|
33
|
+
@is_unique_identifier = false
|
|
34
|
+
else
|
|
35
|
+
@data = source.data
|
|
36
|
+
@is_unique_identifier = source.is_unique_identifier
|
|
37
|
+
end
|
|
27
38
|
update_last_activity_time
|
|
28
39
|
end
|
|
29
40
|
|
|
41
|
+
def last_activity_time
|
|
42
|
+
@data.last_activity_time
|
|
43
|
+
end
|
|
44
|
+
|
|
30
45
|
def update_last_activity_time
|
|
31
|
-
@last_activity_time = Time.new.to_i
|
|
46
|
+
@data.last_activity_time = Time.new.to_i
|
|
32
47
|
end
|
|
33
48
|
|
|
34
49
|
def enumerate_sendable_data(&blk)
|
|
35
|
-
|
|
36
|
-
blk.call(@browser) unless @browser.nil?
|
|
37
|
-
blk.call(@operating_system) unless @operating_system.nil?
|
|
38
|
-
blk.call(@geolocation) unless @geolocation.nil?
|
|
39
|
-
@mutex.with_read_lock do
|
|
40
|
-
@custom_data_map&.each { |_, cd| blk.call(cd) }
|
|
41
|
-
@page_view_visits&.each { |_, pvv| blk.call(pvv.page_view) }
|
|
42
|
-
@conversions&.each { |c| blk.call(c) }
|
|
43
|
-
@variations&.each { |_, av| blk.call(av) }
|
|
44
|
-
end
|
|
50
|
+
@data.enumerate_sendable_data(&blk)
|
|
45
51
|
end
|
|
46
52
|
|
|
47
53
|
def count_sendable_data
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
count_sendable_data = @data.count_sendable_data
|
|
55
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.count_sendable_data -> (count_sendable_data: %s)', count_sendable_data)
|
|
56
|
+
count_sendable_data
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def user_agent
|
|
60
|
+
user_agent = @data.user_agent
|
|
61
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.user_agent -> (user_agent: %s)', user_agent)
|
|
62
|
+
user_agent
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def device
|
|
66
|
+
device = @data.device
|
|
67
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.device -> (device: %s)', device)
|
|
68
|
+
device
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def browser
|
|
72
|
+
browser = @data.browser
|
|
73
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.browser -> (browser: %s)', browser)
|
|
74
|
+
browser
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def geolocation
|
|
78
|
+
geolocation = @data.geolocation
|
|
79
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.geolocation -> (geolocation: %s)', geolocation)
|
|
80
|
+
geolocation
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def operating_system
|
|
84
|
+
operating_system = @data.operating_system
|
|
85
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.operating_system -> (operating_system: %s)', operating_system)
|
|
86
|
+
operating_system
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def cookie
|
|
90
|
+
cookie = @data.cookie
|
|
91
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.cookie -> (cookie: %s)', cookie)
|
|
92
|
+
cookie
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def kcs_heat
|
|
96
|
+
kcs_heat = @data.kcs_heat
|
|
97
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.kcs_heat -> (kcs_heat: %s)', kcs_heat)
|
|
98
|
+
kcs_heat
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def visitor_visits
|
|
102
|
+
visitor_visits = @data.visitor_visits
|
|
103
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.visitor_visits -> (visitor_visits: %s)', visitor_visits)
|
|
104
|
+
visitor_visits
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def legal_consent
|
|
108
|
+
legal_consent = @data.legal_consent
|
|
109
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.legal_consent -> (legal_consent: %s)', legal_consent)
|
|
110
|
+
legal_consent
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def legal_consent=(value)
|
|
114
|
+
@data.legal_consent = value
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def mapping_identifier
|
|
118
|
+
mapping_identifier = @data.mapping_identifier
|
|
119
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.mapping_identifier -> (mapping_identifier: %s)',
|
|
120
|
+
mapping_identifier)
|
|
121
|
+
mapping_identifier
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def mapping_identifier=(value)
|
|
125
|
+
@data.mapping_identifier = value
|
|
60
126
|
end
|
|
61
127
|
|
|
62
128
|
def custom_data
|
|
63
|
-
|
|
129
|
+
custom_data = @data.custom_data
|
|
130
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.custom_data -> (custom_data: %s)', custom_data)
|
|
131
|
+
custom_data
|
|
64
132
|
end
|
|
65
133
|
|
|
66
134
|
def page_view_visits
|
|
67
|
-
|
|
135
|
+
page_view_visits = @data.page_view_visits
|
|
136
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.page_view_visits -> (page_view_visits: %s)',
|
|
137
|
+
page_view_visits)
|
|
138
|
+
page_view_visits
|
|
68
139
|
end
|
|
69
140
|
|
|
70
141
|
def conversions
|
|
71
|
-
|
|
142
|
+
conversions = @data.conversions
|
|
143
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.conversions -> (conversions: %s)', conversions)
|
|
144
|
+
conversions
|
|
72
145
|
end
|
|
73
146
|
|
|
74
147
|
def variations
|
|
75
|
-
|
|
148
|
+
variations = @data.variations
|
|
149
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.variations -> (variations: %s)', variations)
|
|
150
|
+
variations
|
|
76
151
|
end
|
|
77
152
|
|
|
78
|
-
def add_data(
|
|
79
|
-
|
|
153
|
+
def add_data(*args, overwrite: true)
|
|
154
|
+
Logging::KameleoonLogger.debug('CALL: Visitor.add_data(args: %s, overwrite: %s)', args, overwrite)
|
|
155
|
+
@data.mutex.with_write_lock do
|
|
80
156
|
args.each do |data|
|
|
81
157
|
case data
|
|
82
158
|
when Kameleoon::UserAgent
|
|
83
|
-
|
|
159
|
+
@data.user_agent = data.value
|
|
84
160
|
when Kameleoon::DataManager::AssignedVariation
|
|
85
|
-
add_variation(data, overwrite)
|
|
161
|
+
@data.add_variation(data, overwrite)
|
|
86
162
|
when Kameleoon::Device
|
|
87
|
-
set_device(data, overwrite)
|
|
163
|
+
@data.set_device(data, overwrite)
|
|
88
164
|
when Kameleoon::Browser
|
|
89
|
-
set_browser(data, overwrite)
|
|
165
|
+
@data.set_browser(data, overwrite)
|
|
90
166
|
when Kameleoon::CustomData
|
|
91
|
-
add_custom_data(data, overwrite)
|
|
167
|
+
@data.add_custom_data(data, overwrite)
|
|
92
168
|
when Kameleoon::PageView
|
|
93
|
-
add_page_view(data)
|
|
169
|
+
@data.add_page_view(data)
|
|
94
170
|
when Kameleoon::DataManager::PageViewVisit
|
|
95
|
-
add_page_view_visit(data)
|
|
171
|
+
@data.add_page_view_visit(data)
|
|
96
172
|
when Kameleoon::Conversion
|
|
97
|
-
add_conversion(data)
|
|
173
|
+
@data.add_conversion(data)
|
|
98
174
|
when Kameleoon::Cookie
|
|
99
|
-
|
|
175
|
+
@data.cookie = data
|
|
100
176
|
when Kameleoon::OperatingSystem
|
|
101
|
-
set_operating_system(data, overwrite)
|
|
177
|
+
@data.set_operating_system(data, overwrite)
|
|
102
178
|
when Kameleoon::Geolocation
|
|
103
|
-
set_geolocation(data, overwrite)
|
|
179
|
+
@data.set_geolocation(data, overwrite)
|
|
180
|
+
when Kameleoon::KcsHeat
|
|
181
|
+
@data.kcs_heat = data
|
|
104
182
|
when Kameleoon::VisitorVisits
|
|
105
|
-
|
|
183
|
+
@data.visitor_visits = data
|
|
184
|
+
when Kameleoon::UniqueIdentifier
|
|
185
|
+
@is_unique_identifier = data.value
|
|
106
186
|
else
|
|
107
|
-
|
|
187
|
+
Logging::KameleoonLogger.warning("Data has unsupported type '%s'", data.class)
|
|
108
188
|
end
|
|
109
189
|
end
|
|
110
190
|
end
|
|
191
|
+
Logging::KameleoonLogger.debug('RETURN: Visitor.add_data(args: %s, overwrite: %s)', args, overwrite)
|
|
111
192
|
end
|
|
112
193
|
|
|
113
194
|
def assign_variation(variation)
|
|
114
|
-
@mutex.with_write_lock do
|
|
115
|
-
@
|
|
116
|
-
@variations[variation.experiment_id] = variation
|
|
195
|
+
@data.mutex.with_write_lock do
|
|
196
|
+
@data.add_variation(variation, true)
|
|
117
197
|
end
|
|
118
198
|
end
|
|
119
199
|
|
|
120
|
-
|
|
200
|
+
def clone
|
|
201
|
+
Visitor.new(self)
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
class VisitorData
|
|
206
|
+
attr_reader :mutex, :device, :browser, :geolocation, :operating_system
|
|
207
|
+
attr_accessor :last_activity_time, :legal_consent, :user_agent, :cookie, :kcs_heat, :visitor_visits,
|
|
208
|
+
:mapping_identifier
|
|
121
209
|
|
|
122
|
-
def
|
|
123
|
-
|
|
210
|
+
def initialize
|
|
211
|
+
Logging::KameleoonLogger.debug('CALL: VisitorData.new')
|
|
212
|
+
@mutex = Concurrent::ReadWriteLock.new
|
|
213
|
+
@legal_consent = false
|
|
214
|
+
Logging::KameleoonLogger.debug('RETURN: VisitorData.new')
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def enumerate_sendable_data(&blk)
|
|
218
|
+
blk.call(@device) unless @device.nil?
|
|
219
|
+
blk.call(@browser) unless @browser.nil?
|
|
220
|
+
blk.call(@operating_system) unless @operating_system.nil?
|
|
221
|
+
blk.call(@geolocation) unless @geolocation.nil?
|
|
222
|
+
@mutex.with_read_lock do
|
|
223
|
+
@custom_data_map&.each { |_, cd| blk.call(cd) }
|
|
224
|
+
@page_view_visits&.each { |_, pvv| blk.call(pvv.page_view) }
|
|
225
|
+
@conversions&.each { |c| blk.call(c) }
|
|
226
|
+
@variations&.each { |_, av| blk.call(av) }
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def count_sendable_data
|
|
231
|
+
Logging::KameleoonLogger.debug('CALL: Visitor.count_sendable_data')
|
|
232
|
+
count = 0
|
|
233
|
+
@mutex.with_read_lock do
|
|
234
|
+
count += 1 unless @device.nil?
|
|
235
|
+
count += 1 unless @browser.nil?
|
|
236
|
+
count += 1 unless @geolocation.nil?
|
|
237
|
+
count += 1 unless @operating_system.nil?
|
|
238
|
+
count += @custom_data_map.size unless @custom_data_map.nil?
|
|
239
|
+
count += @page_view_visits.size unless @page_view_visits.nil?
|
|
240
|
+
count += @conversions.size unless @conversions.nil?
|
|
241
|
+
count += @variations.size unless @variations.nil?
|
|
242
|
+
end
|
|
243
|
+
Logging::KameleoonLogger.debug('RETURN: VisitorData.count_sendable_data -> (count: %s)', count)
|
|
244
|
+
count
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def custom_data
|
|
248
|
+
DataMapStorage.new(@mutex, @custom_data_map)
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def page_view_visits
|
|
252
|
+
DataMapStorage.new(@mutex, @page_view_visits)
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def conversions
|
|
256
|
+
DataArrayStorage.new(@mutex, @conversions)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def variations
|
|
260
|
+
DataMapStorage.new(@mutex, @variations)
|
|
124
261
|
end
|
|
125
262
|
|
|
126
263
|
def set_device(device, overwrite)
|
|
127
|
-
@device = device if overwrite || @device
|
|
264
|
+
@device = device if overwrite || @device.nil?
|
|
128
265
|
end
|
|
129
266
|
|
|
130
267
|
def add_variation(variation, overwrite)
|
|
131
|
-
@variations = {} if @variations
|
|
268
|
+
@variations = {} if @variations.nil?
|
|
132
269
|
if overwrite || !@variations.include?(variation.experiment_id)
|
|
133
270
|
@variations[variation.experiment_id] = variation
|
|
134
271
|
end
|
|
135
272
|
end
|
|
136
273
|
|
|
137
274
|
def set_browser(browser, overwrite)
|
|
138
|
-
@browser = browser if overwrite || @browser
|
|
275
|
+
@browser = browser if overwrite || @browser.nil?
|
|
139
276
|
end
|
|
140
277
|
|
|
141
278
|
def add_custom_data(custom_data, overwrite)
|
|
142
279
|
@custom_data_map = {} if @custom_data_map.nil?
|
|
143
|
-
|
|
280
|
+
if overwrite || !@custom_data_map.include?(custom_data.id)
|
|
281
|
+
@custom_data_map[custom_data.id] = custom_data
|
|
282
|
+
end
|
|
144
283
|
end
|
|
145
284
|
|
|
146
285
|
def add_page_view(page_view)
|
|
@@ -173,19 +312,11 @@ module Kameleoon
|
|
|
173
312
|
end
|
|
174
313
|
|
|
175
314
|
def set_geolocation(geolocation, overwrite)
|
|
176
|
-
@geolocation = geolocation if overwrite || @geolocation
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
def set_cookie(cookie)
|
|
180
|
-
@cookie = cookie
|
|
315
|
+
@geolocation = geolocation if overwrite || @geolocation.nil?
|
|
181
316
|
end
|
|
182
317
|
|
|
183
318
|
def set_operating_system(operating_system, overwrite)
|
|
184
|
-
@operating_system = operating_system if overwrite || @operating_system
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
def set_visitor_visits(visitor_visits)
|
|
188
|
-
@visitor_visits = visitor_visits
|
|
319
|
+
@operating_system = operating_system if overwrite || @operating_system.nil?
|
|
189
320
|
end
|
|
190
321
|
end
|
|
191
322
|
end
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
require 'concurrent'
|
|
4
4
|
require 'rufus/scheduler'
|
|
5
|
+
require 'kameleoon/configuration/custom_data_info'
|
|
6
|
+
require 'kameleoon/data/mapping_identifier'
|
|
5
7
|
require 'kameleoon/data/manager/visitor'
|
|
8
|
+
require 'kameleoon/logging/kameleoon_logger'
|
|
6
9
|
|
|
7
10
|
module Kameleoon
|
|
8
11
|
module DataManager
|
|
@@ -11,36 +14,52 @@ module Kameleoon
|
|
|
11
14
|
# It is thread-safe except `stop` method
|
|
12
15
|
class VisitorManager
|
|
13
16
|
attr_reader :expiration_period
|
|
14
|
-
attr_accessor :custom_data_info
|
|
15
17
|
|
|
16
|
-
def initialize(expiration_period,
|
|
18
|
+
def initialize(data_manager, expiration_period, scheduler)
|
|
19
|
+
Logging::KameleoonLogger.debug(
|
|
20
|
+
'CALL: VisitorManager.new(data_manager, expiration_period: %s, scheduler)', expiration_period
|
|
21
|
+
)
|
|
22
|
+
@data_manager = data_manager
|
|
17
23
|
@expiration_period = expiration_period
|
|
24
|
+
@scheduler = scheduler
|
|
18
25
|
@visitors = Concurrent::Map.new
|
|
19
|
-
@log_func = log_func
|
|
20
26
|
start
|
|
27
|
+
Logging::KameleoonLogger.debug(
|
|
28
|
+
'RETURN: VisitorManager.new(data_manager, expiration_period: %s, scheduler)', expiration_period
|
|
29
|
+
)
|
|
21
30
|
end
|
|
22
31
|
|
|
23
32
|
def stop
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@purge_job.unschedule
|
|
33
|
+
Logging::KameleoonLogger.debug('CALL: VisitorManager.stop')
|
|
34
|
+
@purge_job&.unschedule
|
|
27
35
|
@purge_job = nil
|
|
36
|
+
Logging::KameleoonLogger.debug('RETURN: VisitorManager.stop')
|
|
28
37
|
end
|
|
29
38
|
|
|
30
39
|
def get_visitor(visitor_code)
|
|
31
|
-
|
|
40
|
+
Logging::KameleoonLogger.debug("CALL: VisitorManager.get_visitor(visitor_code: '%s')", visitor_code)
|
|
41
|
+
visitor = @visitors.compute_if_present(visitor_code) do |visitor|
|
|
32
42
|
visitor.update_last_activity_time
|
|
33
43
|
visitor
|
|
34
44
|
end
|
|
45
|
+
Logging::KameleoonLogger.debug("RETURN: VisitorManager.get_visitor(visitor_code: '%s') -> (visitor: %s)",
|
|
46
|
+
visitor_code, visitor)
|
|
47
|
+
visitor
|
|
35
48
|
end
|
|
36
49
|
|
|
37
50
|
def get_or_create_visitor(visitor_code)
|
|
38
|
-
|
|
51
|
+
Logging::KameleoonLogger.debug("CALL: VisitorManager.get_or_create_visitor(visitor_code: '%s')",
|
|
52
|
+
visitor_code)
|
|
53
|
+
visitor = @visitors.compute(visitor_code) do |former_v|
|
|
39
54
|
next DataManager::Visitor.new if former_v.nil?
|
|
40
55
|
|
|
41
56
|
former_v.update_last_activity_time
|
|
42
57
|
former_v
|
|
43
58
|
end
|
|
59
|
+
Logging::KameleoonLogger.debug(
|
|
60
|
+
"RETURN: VisitorManager.get_or_create_visitor(visitor_code: '%s') -> (visitor)", visitor_code
|
|
61
|
+
)
|
|
62
|
+
visitor
|
|
44
63
|
end
|
|
45
64
|
|
|
46
65
|
def enumerate(&blk)
|
|
@@ -51,42 +70,60 @@ module Kameleoon
|
|
|
51
70
|
@visitors.size
|
|
52
71
|
end
|
|
53
72
|
|
|
54
|
-
def add_data(visitor_code, *args)
|
|
73
|
+
def add_data(visitor_code, *args, overwrite: true)
|
|
74
|
+
Logging::KameleoonLogger.debug("CALL: VisitorManager.add_data(visitor_code: '%s', args: %s, overwrite: %s)",
|
|
75
|
+
visitor_code, args, overwrite)
|
|
55
76
|
visitor = get_or_create_visitor(visitor_code)
|
|
56
|
-
|
|
77
|
+
cdi = @data_manager.data_file.custom_data_info
|
|
78
|
+
args.size.times do |i|
|
|
79
|
+
custom_data = args[i]
|
|
57
80
|
next unless custom_data.is_a?(Kameleoon::CustomData)
|
|
81
|
+
|
|
58
82
|
# We shouldn't send custom data with local only type
|
|
59
|
-
custom_data.mark_as_sent if
|
|
83
|
+
custom_data.mark_as_sent if cdi.local_only?(custom_data.id)
|
|
60
84
|
# If mappingIdentifier is passed, we should link anonymous visitor with real unique userId.
|
|
61
85
|
# After authorization, customer must be able to continue work with userId, but hash for variation
|
|
62
86
|
# should be calculated based on anonymous visitor code, that's why set MappingIdentifier to visitor.
|
|
63
|
-
if
|
|
64
|
-
custom_data.is_mapping_identifier = true
|
|
87
|
+
if Configuration::CustomDataInfo.mapping_identifier?(cdi, custom_data)
|
|
65
88
|
visitor.mapping_identifier = visitor_code
|
|
66
|
-
|
|
67
|
-
|
|
89
|
+
user_id = custom_data.values[0]
|
|
90
|
+
args[i] = MappingIdentifier.new(custom_data)
|
|
91
|
+
if visitor_code != user_id
|
|
92
|
+
@visitors[user_id] = visitor.clone
|
|
93
|
+
Logging::KameleoonLogger.info(-> { "Linked anonymous visitor '#{visitor_code}' with user '#{user_id}'" })
|
|
94
|
+
end
|
|
68
95
|
end
|
|
69
96
|
end
|
|
70
|
-
visitor.add_data(
|
|
97
|
+
visitor.add_data(*args, overwrite: overwrite)
|
|
98
|
+
Logging::KameleoonLogger.debug(
|
|
99
|
+
"RETURN: VisitorManager.add_data(visitor_code: '%s', args: %s, overwrite: %s) -> (visitor)",
|
|
100
|
+
visitor_code, args, overwrite
|
|
101
|
+
)
|
|
71
102
|
visitor
|
|
72
103
|
end
|
|
73
104
|
|
|
74
105
|
private
|
|
75
106
|
|
|
76
107
|
def purge
|
|
108
|
+
Logging::KameleoonLogger.debug('CALL: VisitorManager.purge')
|
|
77
109
|
expired_time = Time.new.to_i - @expiration_period
|
|
78
110
|
@visitors.each_pair do |vc, v|
|
|
79
111
|
next if v.last_activity_time >= expired_time
|
|
80
112
|
|
|
81
113
|
@visitors.compute_if_present(vc) { |visitor| v.last_activity_time < expired_time ? nil : visitor }
|
|
82
114
|
end
|
|
115
|
+
Logging::KameleoonLogger.debug('RETURN: VisitorManager.purge')
|
|
116
|
+
@visitors
|
|
83
117
|
end
|
|
84
118
|
|
|
85
119
|
def start
|
|
120
|
+
Logging::KameleoonLogger.debug('CALL: VisitorManager.start')
|
|
86
121
|
stop unless @purge_job.nil?
|
|
87
|
-
@purge_job =
|
|
122
|
+
@purge_job = @scheduler.schedule_every @expiration_period do
|
|
88
123
|
purge
|
|
89
124
|
end
|
|
125
|
+
Logging::KameleoonLogger.debug('RETURN: VisitorManager.start')
|
|
126
|
+
@purge_job
|
|
90
127
|
end
|
|
91
128
|
end
|
|
92
129
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'kameleoon/data/custom_data'
|
|
4
|
+
require 'kameleoon/network/uri_helper'
|
|
5
|
+
|
|
6
|
+
module Kameleoon
|
|
7
|
+
class MappingIdentifier < CustomData
|
|
8
|
+
def initialize(custom_data)
|
|
9
|
+
super(custom_data.id, *custom_data.values)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def unsent
|
|
13
|
+
true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def transmitting
|
|
17
|
+
false
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def sent
|
|
21
|
+
false
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def obtain_full_post_text_line
|
|
25
|
+
mip = Kameleoon::Network::UriHelper.encode_query({ mappingIdentifier: true })
|
|
26
|
+
"#{super}&#{mip}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_s
|
|
30
|
+
"MappingIdentifier{id:#{@id},values:#{@values}}"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -52,6 +52,10 @@ module Kameleoon
|
|
|
52
52
|
class OperatingSystem < DuplicationUnsafeData
|
|
53
53
|
attr_reader :os_type
|
|
54
54
|
|
|
55
|
+
def to_s
|
|
56
|
+
"OperatingSystem{os_type:#{@os_type}}"
|
|
57
|
+
end
|
|
58
|
+
|
|
55
59
|
# @param [OperatingSystemType] os_type Operating system type, can be: WINDOWS, MAC, IOS, LINUX, ANDROID, WINDOWS_PHONE
|
|
56
60
|
def initialize(os_type)
|
|
57
61
|
super(DataType::OPERATING_SYSTEM)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'json'
|
|
4
|
+
require 'kameleoon/logging/kameleoon_logger'
|
|
4
5
|
require 'kameleoon/network/uri_helper'
|
|
5
6
|
require_relative 'data'
|
|
6
7
|
|
|
@@ -9,13 +10,17 @@ module Kameleoon
|
|
|
9
10
|
class PageView < DuplicationSafeData
|
|
10
11
|
attr_reader :url, :title, :referrer
|
|
11
12
|
|
|
13
|
+
def to_s
|
|
14
|
+
"PageView{url:'#{@url}',title:'#{@title}',referrers:#{@referrers}}"
|
|
15
|
+
end
|
|
16
|
+
|
|
12
17
|
# @param [String] url Url of the page
|
|
13
18
|
# @param [String] title Optional field - title of the page
|
|
14
19
|
# @param [Array] referrers Optional field - Referrer ids
|
|
15
20
|
def initialize(url, title = nil, referrers = nil)
|
|
16
21
|
super(DataType::PAGE_VIEW)
|
|
17
22
|
@url = url || ''
|
|
18
|
-
|
|
23
|
+
Logging::KameleoonLogger.error('Url for PageView is required parameter, the data will be ignored.') if @url == ''
|
|
19
24
|
@title = title || ''
|
|
20
25
|
@referrers = referrers.instance_of?(Integer) ? [referrers] : referrers
|
|
21
26
|
end
|
|
@@ -4,10 +4,21 @@ module Kameleoon
|
|
|
4
4
|
class VisitorVisits
|
|
5
5
|
attr_reader :previous_visit_timestamps
|
|
6
6
|
|
|
7
|
+
def to_s
|
|
8
|
+
"VisitorVisits{previous_visit_timestamps:#{@previous_visit_timestamps}}"
|
|
9
|
+
end
|
|
10
|
+
|
|
7
11
|
def initialize(previous_visit_timestamps = [])
|
|
8
12
|
@previous_visit_timestamps = previous_visit_timestamps
|
|
9
13
|
@previous_visit_timestamps.freeze
|
|
10
14
|
end
|
|
15
|
+
|
|
16
|
+
def self.get_previous_visit_timestamps(visitor_visits)
|
|
17
|
+
visitor_visits.is_a?(VisitorVisits) ? visitor_visits.previous_visit_timestamps : []
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.visitor_visits?(obj)
|
|
21
|
+
obj.nil? || obj.is_a?(VisitorVisits)
|
|
22
|
+
end
|
|
11
23
|
end
|
|
12
24
|
end
|
|
13
|
-
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'kameleoon/logging/kameleoon_logger'
|
|
4
|
+
|
|
3
5
|
module Kameleoon
|
|
4
6
|
module Hybrid
|
|
5
7
|
TC_INIT = 'window.kameleoonQueue=window.kameleoonQueue||[];'
|
|
@@ -17,14 +19,16 @@ module Kameleoon
|
|
|
17
19
|
|
|
18
20
|
# Implementation of Cache with auto cleaning feature
|
|
19
21
|
class ManagerImpl < Manager
|
|
20
|
-
def initialize(expiration_time
|
|
22
|
+
def initialize(expiration_time)
|
|
21
23
|
super()
|
|
24
|
+
Logging::KameleoonLogger.debug('CALL: HybridManager.new(expiration_time: %s)', expiration_time)
|
|
22
25
|
@expiration_time = expiration_time
|
|
23
|
-
|
|
24
|
-
@log.call('Hybrid Manager was successfully initialized')
|
|
26
|
+
Logging::KameleoonLogger.debug('RETURN: HybridManager.new(expiration_time: %s)', expiration_time)
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
def get_engine_tracking_code(visitor_variations)
|
|
30
|
+
Logging::KameleoonLogger.debug('CALL: HybridManager.get_engine_tracking_code(visitor_variations: %s)',
|
|
31
|
+
visitor_variations)
|
|
28
32
|
tracking_code = [TC_INIT]
|
|
29
33
|
unless visitor_variations.nil?
|
|
30
34
|
expired_time = (Time.now - @expiration_time).to_i
|
|
@@ -35,7 +39,12 @@ module Kameleoon
|
|
|
35
39
|
end
|
|
36
40
|
end
|
|
37
41
|
end
|
|
38
|
-
tracking_code.join
|
|
42
|
+
tracking_code = tracking_code.join
|
|
43
|
+
Logging::KameleoonLogger.debug(
|
|
44
|
+
"RETURN: HybridManager.get_engine_tracking_code(visitor_variations: %s) -> (tracking_code: '%s')",
|
|
45
|
+
visitor_variations, tracking_code
|
|
46
|
+
)
|
|
47
|
+
tracking_code
|
|
39
48
|
end
|
|
40
49
|
end
|
|
41
50
|
end
|