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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/lib/kameleoon/configuration/custom_data_info.rb +16 -8
  3. data/lib/kameleoon/configuration/data_file.rb +52 -16
  4. data/lib/kameleoon/configuration/feature_flag.rb +11 -1
  5. data/lib/kameleoon/configuration/rule.rb +4 -0
  6. data/lib/kameleoon/configuration/settings.rb +13 -8
  7. data/lib/kameleoon/configuration/variation_exposition.rb +4 -0
  8. data/lib/kameleoon/data/browser.rb +4 -0
  9. data/lib/kameleoon/data/conversion.rb +4 -0
  10. data/lib/kameleoon/data/cookie.rb +4 -0
  11. data/lib/kameleoon/data/custom_data.rb +11 -3
  12. data/lib/kameleoon/data/data.rb +30 -4
  13. data/lib/kameleoon/data/device.rb +4 -0
  14. data/lib/kameleoon/data/geolocation.rb +5 -0
  15. data/lib/kameleoon/data/kcs_heat.rb +4 -0
  16. data/lib/kameleoon/data/manager/assigned_variation.rb +8 -1
  17. data/lib/kameleoon/data/manager/data_array_storage.rb +7 -0
  18. data/lib/kameleoon/data/manager/data_map_storage.rb +7 -0
  19. data/lib/kameleoon/data/manager/page_view_visit.rb +4 -0
  20. data/lib/kameleoon/data/manager/visitor.rb +197 -73
  21. data/lib/kameleoon/data/manager/visitor_manager.rb +54 -17
  22. data/lib/kameleoon/data/mapping_identifier.rb +33 -0
  23. data/lib/kameleoon/data/operating_system.rb +4 -0
  24. data/lib/kameleoon/data/page_view.rb +6 -1
  25. data/lib/kameleoon/data/unique_identifier.rb +11 -0
  26. data/lib/kameleoon/data/user_agent.rb +4 -0
  27. data/lib/kameleoon/data/visitor_visits.rb +4 -0
  28. data/lib/kameleoon/hybrid/manager.rb +19 -7
  29. data/lib/kameleoon/kameleoon_client.rb +477 -178
  30. data/lib/kameleoon/kameleoon_client_config.rb +65 -18
  31. data/lib/kameleoon/kameleoon_client_factory.rb +15 -2
  32. data/lib/kameleoon/logging/default_logger.rb +20 -0
  33. data/lib/kameleoon/logging/kameleoon_logger.rb +77 -0
  34. data/lib/kameleoon/logging/logger.rb +12 -0
  35. data/lib/kameleoon/managers/data/data_manager.rb +36 -0
  36. data/lib/kameleoon/managers/remote_data/remote_data_manager.rb +32 -15
  37. data/lib/kameleoon/managers/tracking/tracking_builder.rb +149 -0
  38. data/lib/kameleoon/managers/tracking/tracking_manager.rb +98 -0
  39. data/lib/kameleoon/managers/tracking/visitor_tracking_registry.rb +94 -0
  40. data/lib/kameleoon/managers/warehouse/warehouse_manager.rb +22 -5
  41. data/lib/kameleoon/network/access_token_source.rb +46 -14
  42. data/lib/kameleoon/network/cookie/cookie_manager.rb +46 -7
  43. data/lib/kameleoon/network/net_provider.rb +2 -3
  44. data/lib/kameleoon/network/network_manager.rb +17 -21
  45. data/lib/kameleoon/network/request.rb +14 -3
  46. data/lib/kameleoon/network/response.rb +4 -0
  47. data/lib/kameleoon/network/url_provider.rb +3 -3
  48. data/lib/kameleoon/real_time/real_time_configuration_service.rb +10 -11
  49. data/lib/kameleoon/sdk_version.rb +31 -0
  50. data/lib/kameleoon/targeting/condition.rb +4 -2
  51. data/lib/kameleoon/targeting/conditions/browser_condition.rb +3 -3
  52. data/lib/kameleoon/targeting/conditions/cookie_condition.rb +10 -10
  53. data/lib/kameleoon/targeting/conditions/geolocation_condition.rb +0 -1
  54. data/lib/kameleoon/targeting/conditions/number_condition.rb +4 -4
  55. data/lib/kameleoon/targeting/conditions/operating_system_condition.rb +1 -2
  56. data/lib/kameleoon/targeting/conditions/sdk_language_condition.rb +2 -1
  57. data/lib/kameleoon/targeting/conditions/segment_condition.rb +3 -3
  58. data/lib/kameleoon/targeting/conditions/string_value_condition.rb +2 -1
  59. data/lib/kameleoon/targeting/models.rb +0 -14
  60. data/lib/kameleoon/targeting/targeting_manager.rb +35 -7
  61. data/lib/kameleoon/targeting/tree_builder.rb +10 -5
  62. data/lib/kameleoon/types/remote_visitor_data_filter.rb +13 -0
  63. data/lib/kameleoon/types/variable.rb +4 -0
  64. data/lib/kameleoon/types/variation.rb +8 -0
  65. data/lib/kameleoon/utils.rb +49 -0
  66. data/lib/kameleoon/version.rb +1 -27
  67. 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 :last_activity_time, :user_agent, :device, :browser, :geolocation, :operating_system, :cookie,
22
- :kcs_heat, :visitor_visits
23
- attr_accessor :legal_consent, :mapping_identifier
24
+ attr_reader :data, :is_unique_identifier
24
25
 
25
- def initialize
26
- @mutex = Concurrent::ReadWriteLock.new
27
- @legal_consent = false
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
- blk.call(@device) unless @device.nil?
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
- count = 0
50
- @mutex.with_read_lock do
51
- count += 1 unless @device.nil?
52
- count += 1 unless @browser.nil?
53
- count += 1 unless @geolocation.nil?
54
- count += 1 unless @operating_system.nil?
55
- count += @custom_data_map.size unless @custom_data_map.nil?
56
- count += @page_view_visits.size unless @page_view_visits.nil?
57
- count += @conversions.size unless @conversions.nil?
58
- count += @variations.size unless @variations.nil?
59
- end
60
- count
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
- DataMapStorage.new(@mutex, @custom_data_map)
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
- DataMapStorage.new(@mutex, @page_view_visits)
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
- DataArrayStorage.new(@mutex, @conversions)
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
- DataMapStorage.new(@mutex, @variations)
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(log_func, *args, overwrite: true)
80
- @mutex.with_write_lock do
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
- set_user_agent(data)
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
- set_cookie(data)
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
- set_kcs_heat(data)
181
+ @data.kcs_heat = data
107
182
  when Kameleoon::VisitorVisits
108
- set_visitor_visits(data)
183
+ @data.visitor_visits = data
184
+ when Kameleoon::UniqueIdentifier
185
+ @is_unique_identifier = data.value
109
186
  else
110
- log_func&.call("Data has unsupported type '#{data.class}'")
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
- @variations = {} if @variations.nil?
119
- @variations[variation.experiment_id] = variation
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
- private
247
+ def custom_data
248
+ DataMapStorage.new(@mutex, @custom_data_map)
249
+ end
124
250
 
125
- def set_user_agent(user_agent)
126
- @user_agent = user_agent.value
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 == nil
264
+ @device = device if overwrite || @device.nil?
131
265
  end
132
266
 
133
267
  def add_variation(variation, overwrite)
134
- @variations = {} if @variations == nil
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 == nil
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
- @custom_data_map[custom_data.id] = custom_data if overwrite || !@custom_data_map.include?(custom_data.id)
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 == nil
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 == nil
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, log_func = nil)
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
- return if @purge_job.nil?
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
- @visitors.compute_if_present(visitor_code) do |visitor|
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
- @visitors.compute(visitor_code) do |former_v|
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
- for custom_data in args
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 @custom_data_info.local_only?(custom_data.id)
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 @custom_data_info.mapping_identifier?(custom_data.id) && custom_data.values.size > 0 && custom_data.values[0].size > 0
64
- custom_data.is_mapping_identifier = true
87
+ if Configuration::CustomDataInfo.mapping_identifier?(cdi, custom_data)
65
88
  visitor.mapping_identifier = visitor_code
66
- target_visitor_code = custom_data.values[0]
67
- @visitors[target_visitor_code] = visitor if visitor_code != target_visitor_code
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(@log_func, *args)
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 = Rufus::Scheduler.singleton.schedule_every @expiration_period do
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
- print('Kameleoon SDK: Url for PageView is required parameter, the data will be ignored.') if url == ''
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
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kameleoon
4
+ class UniqueIdentifier
5
+ attr_reader :value
6
+
7
+ def initialize(value)
8
+ @value = value
9
+ end
10
+ end
11
+ end
@@ -7,6 +7,10 @@ module Kameleoon
7
7
  class UserAgent
8
8
  attr_reader :value
9
9
 
10
+ def to_s
11
+ "UserAgent{value:#{@value}}"
12
+ end
13
+
10
14
  def initialize(value)
11
15
  @value = value
12
16
  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,true]);"
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, log_func)
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
- @log = log_func
24
- @log.call('Hybrid Manager was successfully initialized')
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
- v_code = format(TC_ASSIGN_VARIATION_TRIGGER_FORMAT, v.experiment_id, v.variation_id, v.experiment_id)
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