kameleoon-client-ruby 3.3.0 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/kameleoon/configuration/custom_data_info.rb +16 -8
- data/lib/kameleoon/configuration/data_file.rb +52 -16
- data/lib/kameleoon/configuration/feature_flag.rb +11 -1
- 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 +4 -0
- data/lib/kameleoon/data/manager/assigned_variation.rb +8 -1
- 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 +197 -73
- 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 +4 -0
- data/lib/kameleoon/hybrid/manager.rb +19 -7
- data/lib/kameleoon/kameleoon_client.rb +477 -178
- data/lib/kameleoon/kameleoon_client_config.rb +65 -18
- 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 +32 -15
- data/lib/kameleoon/managers/tracking/tracking_builder.rb +149 -0
- data/lib/kameleoon/managers/tracking/tracking_manager.rb +98 -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 +46 -7
- data/lib/kameleoon/network/net_provider.rb +2 -3
- data/lib/kameleoon/network/network_manager.rb +17 -21
- data/lib/kameleoon/network/request.rb +14 -3
- data/lib/kameleoon/network/response.rb +4 -0
- data/lib/kameleoon/network/url_provider.rb +3 -3
- 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 +4 -2
- 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/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/models.rb +0 -14
- data/lib/kameleoon/targeting/targeting_manager.rb +35 -7
- data/lib/kameleoon/targeting/tree_builder.rb +10 -5
- data/lib/kameleoon/types/remote_visitor_data_filter.rb +13 -0
- data/lib/kameleoon/types/variable.rb +4 -0
- data/lib/kameleoon/types/variation.rb +8 -0
- data/lib/kameleoon/utils.rb +49 -0
- data/lib/kameleoon/version.rb +1 -27
- metadata +12 -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,132 +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
|
-
:kcs_heat, :visitor_visits
|
23
|
-
attr_accessor :legal_consent, :mapping_identifier
|
24
|
+
attr_reader :data, :is_unique_identifier
|
24
25
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
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
|
28
38
|
update_last_activity_time
|
29
39
|
end
|
30
40
|
|
41
|
+
def last_activity_time
|
42
|
+
@data.last_activity_time
|
43
|
+
end
|
44
|
+
|
31
45
|
def update_last_activity_time
|
32
|
-
@last_activity_time = Time.new.to_i
|
46
|
+
@data.last_activity_time = Time.new.to_i
|
33
47
|
end
|
34
48
|
|
35
49
|
def enumerate_sendable_data(&blk)
|
36
|
-
|
37
|
-
blk.call(@browser) unless @browser.nil?
|
38
|
-
blk.call(@operating_system) unless @operating_system.nil?
|
39
|
-
blk.call(@geolocation) unless @geolocation.nil?
|
40
|
-
@mutex.with_read_lock do
|
41
|
-
@custom_data_map&.each { |_, cd| blk.call(cd) }
|
42
|
-
@page_view_visits&.each { |_, pvv| blk.call(pvv.page_view) }
|
43
|
-
@conversions&.each { |c| blk.call(c) }
|
44
|
-
@variations&.each { |_, av| blk.call(av) }
|
45
|
-
end
|
50
|
+
@data.enumerate_sendable_data(&blk)
|
46
51
|
end
|
47
52
|
|
48
53
|
def count_sendable_data
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
61
126
|
end
|
62
127
|
|
63
128
|
def custom_data
|
64
|
-
|
129
|
+
custom_data = @data.custom_data
|
130
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.custom_data -> (custom_data: %s)', custom_data)
|
131
|
+
custom_data
|
65
132
|
end
|
66
133
|
|
67
134
|
def page_view_visits
|
68
|
-
|
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
|
69
139
|
end
|
70
140
|
|
71
141
|
def conversions
|
72
|
-
|
142
|
+
conversions = @data.conversions
|
143
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.conversions -> (conversions: %s)', conversions)
|
144
|
+
conversions
|
73
145
|
end
|
74
146
|
|
75
147
|
def variations
|
76
|
-
|
148
|
+
variations = @data.variations
|
149
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.variations -> (variations: %s)', variations)
|
150
|
+
variations
|
77
151
|
end
|
78
152
|
|
79
|
-
def add_data(
|
80
|
-
|
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
|
81
156
|
args.each do |data|
|
82
157
|
case data
|
83
158
|
when Kameleoon::UserAgent
|
84
|
-
|
159
|
+
@data.user_agent = data.value
|
85
160
|
when Kameleoon::DataManager::AssignedVariation
|
86
|
-
add_variation(data, overwrite)
|
161
|
+
@data.add_variation(data, overwrite)
|
87
162
|
when Kameleoon::Device
|
88
|
-
set_device(data, overwrite)
|
163
|
+
@data.set_device(data, overwrite)
|
89
164
|
when Kameleoon::Browser
|
90
|
-
set_browser(data, overwrite)
|
165
|
+
@data.set_browser(data, overwrite)
|
91
166
|
when Kameleoon::CustomData
|
92
|
-
add_custom_data(data, overwrite)
|
167
|
+
@data.add_custom_data(data, overwrite)
|
93
168
|
when Kameleoon::PageView
|
94
|
-
add_page_view(data)
|
169
|
+
@data.add_page_view(data)
|
95
170
|
when Kameleoon::DataManager::PageViewVisit
|
96
|
-
add_page_view_visit(data)
|
171
|
+
@data.add_page_view_visit(data)
|
97
172
|
when Kameleoon::Conversion
|
98
|
-
add_conversion(data)
|
173
|
+
@data.add_conversion(data)
|
99
174
|
when Kameleoon::Cookie
|
100
|
-
|
175
|
+
@data.cookie = data
|
101
176
|
when Kameleoon::OperatingSystem
|
102
|
-
set_operating_system(data, overwrite)
|
177
|
+
@data.set_operating_system(data, overwrite)
|
103
178
|
when Kameleoon::Geolocation
|
104
|
-
set_geolocation(data, overwrite)
|
179
|
+
@data.set_geolocation(data, overwrite)
|
105
180
|
when Kameleoon::KcsHeat
|
106
|
-
|
181
|
+
@data.kcs_heat = data
|
107
182
|
when Kameleoon::VisitorVisits
|
108
|
-
|
183
|
+
@data.visitor_visits = data
|
184
|
+
when Kameleoon::UniqueIdentifier
|
185
|
+
@is_unique_identifier = data.value
|
109
186
|
else
|
110
|
-
|
187
|
+
Logging::KameleoonLogger.warning("Data has unsupported type '%s'", data.class)
|
111
188
|
end
|
112
189
|
end
|
113
190
|
end
|
191
|
+
Logging::KameleoonLogger.debug('RETURN: Visitor.add_data(args: %s, overwrite: %s)', args, overwrite)
|
114
192
|
end
|
115
193
|
|
116
194
|
def assign_variation(variation)
|
117
|
-
@mutex.with_write_lock do
|
118
|
-
@
|
119
|
-
|
195
|
+
@data.mutex.with_write_lock do
|
196
|
+
@data.add_variation(variation, true)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
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
|
209
|
+
|
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?
|
120
242
|
end
|
243
|
+
Logging::KameleoonLogger.debug('RETURN: VisitorData.count_sendable_data -> (count: %s)', count)
|
244
|
+
count
|
121
245
|
end
|
122
246
|
|
123
|
-
|
247
|
+
def custom_data
|
248
|
+
DataMapStorage.new(@mutex, @custom_data_map)
|
249
|
+
end
|
124
250
|
|
125
|
-
def
|
126
|
-
@
|
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)
|
127
261
|
end
|
128
262
|
|
129
263
|
def set_device(device, overwrite)
|
130
|
-
@device = device if overwrite || @device
|
264
|
+
@device = device if overwrite || @device.nil?
|
131
265
|
end
|
132
266
|
|
133
267
|
def add_variation(variation, overwrite)
|
134
|
-
@variations = {} if @variations
|
268
|
+
@variations = {} if @variations.nil?
|
135
269
|
if overwrite || !@variations.include?(variation.experiment_id)
|
136
270
|
@variations[variation.experiment_id] = variation
|
137
271
|
end
|
138
272
|
end
|
139
273
|
|
140
274
|
def set_browser(browser, overwrite)
|
141
|
-
@browser = browser if overwrite || @browser
|
275
|
+
@browser = browser if overwrite || @browser.nil?
|
142
276
|
end
|
143
277
|
|
144
278
|
def add_custom_data(custom_data, overwrite)
|
145
279
|
@custom_data_map = {} if @custom_data_map.nil?
|
146
|
-
|
280
|
+
if overwrite || !@custom_data_map.include?(custom_data.id)
|
281
|
+
@custom_data_map[custom_data.id] = custom_data
|
282
|
+
end
|
147
283
|
end
|
148
284
|
|
149
285
|
def add_page_view(page_view)
|
@@ -176,23 +312,11 @@ module Kameleoon
|
|
176
312
|
end
|
177
313
|
|
178
314
|
def set_geolocation(geolocation, overwrite)
|
179
|
-
@geolocation = geolocation if overwrite || @geolocation
|
180
|
-
end
|
181
|
-
|
182
|
-
def set_cookie(cookie)
|
183
|
-
@cookie = cookie
|
315
|
+
@geolocation = geolocation if overwrite || @geolocation.nil?
|
184
316
|
end
|
185
317
|
|
186
318
|
def set_operating_system(operating_system, overwrite)
|
187
|
-
@operating_system = operating_system if overwrite || @operating_system
|
188
|
-
end
|
189
|
-
|
190
|
-
def set_kcs_heat(kcs_heat)
|
191
|
-
@kcs_heat = kcs_heat
|
192
|
-
end
|
193
|
-
|
194
|
-
def set_visitor_visits(visitor_visits)
|
195
|
-
@visitor_visits = visitor_visits
|
319
|
+
@operating_system = operating_system if overwrite || @operating_system.nil?
|
196
320
|
end
|
197
321
|
end
|
198
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,6 +4,10 @@ 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
|
@@ -1,10 +1,12 @@
|
|
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||[];'
|
6
|
-
TC_ASSIGN_VARIATION_FORMAT = "window.kameleoonQueue.push(['Experiments.assignVariation',%d,%d]);"
|
7
|
-
TC_TRIGGER_FORMAT = "window.kameleoonQueue.push(['Experiments.trigger',%d
|
8
|
+
TC_ASSIGN_VARIATION_FORMAT = "window.kameleoonQueue.push(['Experiments.assignVariation',%d,%d,true]);"
|
9
|
+
TC_TRIGGER_FORMAT = "window.kameleoonQueue.push(['Experiments.trigger',%d,%s]);"
|
8
10
|
TC_ASSIGN_VARIATION_TRIGGER_FORMAT = TC_ASSIGN_VARIATION_FORMAT + TC_TRIGGER_FORMAT
|
9
11
|
|
10
12
|
# Will be useful for Ruby 3.0
|
@@ -17,25 +19,35 @@ 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, data_manager)
|
21
23
|
super()
|
24
|
+
Logging::KameleoonLogger.debug('CALL: HybridManager.new(expiration_time: %s)', expiration_time)
|
22
25
|
@expiration_time = expiration_time
|
23
|
-
@
|
24
|
-
|
26
|
+
@data_manager = data_manager
|
27
|
+
Logging::KameleoonLogger.debug('RETURN: HybridManager.new(expiration_time: %s)', expiration_time)
|
25
28
|
end
|
26
29
|
|
27
30
|
def get_engine_tracking_code(visitor_variations)
|
31
|
+
Logging::KameleoonLogger.debug('CALL: HybridManager.get_engine_tracking_code(visitor_variations: %s)',
|
32
|
+
visitor_variations)
|
28
33
|
tracking_code = [TC_INIT]
|
29
34
|
unless visitor_variations.nil?
|
30
35
|
expired_time = (Time.now - @expiration_time).to_i
|
31
36
|
visitor_variations.enumerate do |v|
|
32
37
|
if v.assignment_time > expired_time
|
33
|
-
|
38
|
+
tracking_only = !@data_manager.data_file.experiment_js_css_variable?(v.experiment_id)
|
39
|
+
v_code = format(TC_ASSIGN_VARIATION_TRIGGER_FORMAT, v.experiment_id, v.variation_id, v.experiment_id,
|
40
|
+
tracking_only)
|
34
41
|
tracking_code.push(v_code)
|
35
42
|
end
|
36
43
|
end
|
37
44
|
end
|
38
|
-
tracking_code.join
|
45
|
+
tracking_code = tracking_code.join
|
46
|
+
Logging::KameleoonLogger.debug(
|
47
|
+
"RETURN: HybridManager.get_engine_tracking_code(visitor_variations: %s) -> (tracking_code: '%s')",
|
48
|
+
visitor_variations, tracking_code
|
49
|
+
)
|
50
|
+
tracking_code
|
39
51
|
end
|
40
52
|
end
|
41
53
|
end
|