kameleoon-client-ruby 3.3.0 → 3.4.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 +37 -15
  4. data/lib/kameleoon/configuration/feature_flag.rb +10 -0
  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 +5 -0
  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 +13 -4
  29. data/lib/kameleoon/kameleoon_client.rb +303 -148
  30. data/lib/kameleoon/kameleoon_client_config.rb +64 -17
  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 +97 -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 +45 -7
  43. data/lib/kameleoon/network/net_provider.rb +2 -3
  44. data/lib/kameleoon/network/network_manager.rb +16 -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 +4 -4
  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 +4 -0
  65. data/lib/kameleoon/utils.rb +18 -0
  66. data/lib/kameleoon/version.rb +1 -27
  67. metadata +12 -2
@@ -1,26 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'kameleoon/client_readiness'
4
- require 'kameleoon/targeting/models'
5
- require 'kameleoon/targeting/targeting_manager'
6
- require 'kameleoon/exceptions'
4
+ require 'kameleoon/configuration/feature_flag'
5
+ require 'kameleoon/configuration/variation'
6
+ require 'kameleoon/configuration/data_file'
7
7
  require 'kameleoon/data/custom_data'
8
8
  require 'kameleoon/data/user_agent'
9
9
  require 'kameleoon/data/manager/assigned_variation'
10
10
  require 'kameleoon/data/manager/visitor_manager'
11
- require 'kameleoon/configuration/feature_flag'
12
- require 'kameleoon/configuration/variation'
13
- require 'kameleoon/configuration/data_file'
11
+ require 'kameleoon/exceptions'
12
+ require 'kameleoon/hybrid/manager'
13
+ require 'kameleoon/managers/data/data_manager'
14
+ require 'kameleoon/managers/remote_data/remote_data_manager'
15
+ require 'kameleoon/managers/tracking/tracking_manager'
16
+ require 'kameleoon/managers/tracking/visitor_tracking_registry'
17
+ require 'kameleoon/managers/warehouse/warehouse_manager'
14
18
  require 'kameleoon/network/access_token_source'
15
19
  require 'kameleoon/network/activity_event'
16
20
  require 'kameleoon/network/network_manager'
17
21
  require 'kameleoon/network/url_provider'
18
22
  require 'kameleoon/network/cookie/cookie_manager'
19
- require 'kameleoon/managers/warehouse/warehouse_manager'
20
23
  require 'kameleoon/real_time/real_time_configuration_service'
21
- require 'kameleoon/hybrid/manager'
22
24
  require 'kameleoon/storage/cache_factory'
23
- require 'kameleoon/managers/remote_data/remote_data_manager'
25
+ require 'kameleoon/targeting/models'
26
+ require 'kameleoon/targeting/targeting_manager'
24
27
  require 'rufus/scheduler'
25
28
  require 'yaml'
26
29
  require 'json'
@@ -43,32 +46,50 @@ module Kameleoon
43
46
  def initialize(site_code, config)
44
47
  raise Exception::SiteCodeIsEmpty, 'Provided site_sode is empty' if site_code&.empty? != false
45
48
 
49
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.new(site_code: '%s', config: %s)",
50
+ site_code, config)
51
+ @scheduler = Rufus::Scheduler.new
46
52
  @site_code = site_code
47
53
  @config = config
48
54
  @real_time_configuration_service = nil
49
55
  @update_configuration_handler = nil
50
56
  @fetch_configuration_update_job = nil
51
- @data_file = Configuration::DataFile.new(config.environment, method(:log))
52
- @visitor_manager = Kameleoon::DataManager::VisitorManager.new(config.session_duration_second, method(:log))
53
- @hybrid_manager = Kameleoon::Hybrid::ManagerImpl.new(HYBRID_EXPIRATION_TIME, method(:log))
57
+ data_file = Configuration::DataFile.new(config.environment, nil)
58
+ @data_manager = Managers::Data::DataManager.new(data_file)
59
+ @visitor_manager = Kameleoon::DataManager::VisitorManager.new(
60
+ @data_manager, config.session_duration_second, @scheduler
61
+ )
62
+ @hybrid_manager = Hybrid::ManagerImpl.new(HYBRID_EXPIRATION_TIME)
54
63
  @network_manager = Network::NetworkManager.new(
55
64
  config.environment,
56
65
  config.default_timeout_millisecond,
57
- Network::AccessTokenSourceFactory.new(config.client_id, config.client_secret, method(:log)),
58
- Network::UrlProvider.new(site_code),
59
- method(:log)
66
+ Network::AccessTokenSourceFactory.new(config.client_id, config.client_secret),
67
+ Network::UrlProvider.new(site_code)
68
+ )
69
+ @tracking_manager = Managers::Tracking::TrackingManager.new(
70
+ @data_manager, @network_manager, @visitor_manager, config.tracking_interval_second, @scheduler
60
71
  )
61
- @warehouse_manager = Managers::Warehouse::WarehouseManager.new(@network_manager, @visitor_manager, method(:log))
62
- @remote_data_manager = Kameleoon::Managers::RemoteData::RemoteDataManager.new(@network_manager, @visitor_manager,
63
- method(:log))
64
- @cookie_manager = Network::Cookie::CookieManager.new(config.top_level_domain)
72
+ @warehouse_manager = Managers::Warehouse::WarehouseManager.new(@network_manager, @visitor_manager)
73
+ @remote_data_manager = Managers::RemoteData::RemoteDataManager.new(
74
+ @data_manager, @network_manager, @visitor_manager
75
+ )
76
+ @cookie_manager = Network::Cookie::CookieManager.new(@data_manager, config.top_level_domain)
65
77
  @readiness = ClientReadiness.new
66
- @targeting_manager = Kameleoon::Targeting::TargetingManager.new(@visitor_manager, @data_file)
67
- @visitor_manager.custom_data_info = @data_file.custom_data_info
78
+ @targeting_manager = Targeting::TargetingManager.new(@data_manager, @visitor_manager)
79
+
80
+ if @config.verbose_mode == true && Logging::KameleoonLogger.log_level == Logging::LogLevel::WARNING
81
+ Logging::KameleoonLogger.log_level = Logging::LogLevel::INFO
82
+ end
83
+
84
+ Logging::KameleoonLogger.info("RETURN: KameleoonClient.new(site_code: '%s', config: %s)",
85
+ site_code, config)
68
86
  end
69
87
 
70
88
  def wait_init
71
- @readiness.wait
89
+ Logging::KameleoonLogger.info('CALL: KameleoonClient.wait_init')
90
+ result = @readiness.wait
91
+ Logging::KameleoonLogger.info('RETURN: KameleoonClient.wait_init -> (result: %s)', result)
92
+ result
72
93
  end
73
94
 
74
95
  ##
@@ -98,14 +119,29 @@ module Kameleoon
98
119
  # visitor_code = get_visitor_code(cookies, 'my-domaine.com')
99
120
  #
100
121
  def get_visitor_code(cookies, default_visitor_code = nil)
101
- @cookie_manager.get_or_add(cookies, default_visitor_code)
122
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.get_visitor_code(cookies: %s, default_visitor_code: '%s')",
123
+ cookies, default_visitor_code)
124
+ visitor_code = @cookie_manager.get_or_add(cookies, default_visitor_code)
125
+ Logging::KameleoonLogger.info(
126
+ "RETURN: KameleoonClient.get_visitor_code(cookies: %s, default_visitor_code: '%s') -> (visitor_code: '%s')",
127
+ cookies, default_visitor_code, visitor_code
128
+ )
129
+ visitor_code
102
130
  end
103
131
 
104
132
  def set_legal_consent(visitor_code, consent, cookies = nil)
133
+ Logging::KameleoonLogger.info(
134
+ "CALL: KameleoonClient.set_legal_consent(visitor_code: '%s', consent: %s, cookies: %s)",
135
+ visitor_code, consent, cookies
136
+ )
105
137
  Utils::VisitorCode.validate(visitor_code)
106
138
  visitor = @visitor_manager.get_or_create_visitor(visitor_code)
107
139
  visitor.legal_consent = consent
108
140
  @cookie_manager.update(visitor_code, consent, cookies)
141
+ Logging::KameleoonLogger.info(
142
+ "RETURN: KameleoonClient.set_legal_consent(visitor_code: '%s', consent: %s, cookies: %s)",
143
+ visitor_code, consent, cookies
144
+ )
109
145
  end
110
146
 
111
147
  ##
@@ -122,8 +158,14 @@ module Kameleoon
122
158
  # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars
123
159
  #
124
160
  def add_data(visitor_code, *args)
161
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.add_data(visitor_code: '%s', args: %s)",
162
+ visitor_code, args)
125
163
  Utils::VisitorCode.validate(visitor_code)
126
164
  @visitor_manager.add_data(visitor_code, *args)
165
+ Logging::KameleoonLogger.info(
166
+ "RETURN: KameleoonClient.add_data(visitor_code: '%s', args: %s)",
167
+ visitor_code, args
168
+ )
127
169
  end
128
170
 
129
171
  ##
@@ -138,15 +180,24 @@ module Kameleoon
138
180
  # @param [String] visitor_code Visitor code
139
181
  # @param [Integer] goal_id Id of the goal
140
182
  # @param [Float] revenue Optional - Revenue of the conversion.
141
- # @param [Bool] is_unique_identifier Parameter that specifies whether the visitorCode is a unique identifier.
142
- # This field is optional.
183
+ # @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
184
+ # identifier. This field is optional.
143
185
  #
144
186
  # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars
145
187
  #
146
- def track_conversion(visitor_code, goal_id, revenue = 0.0, is_unique_identifier: false)
188
+ def track_conversion(visitor_code, goal_id, revenue = 0.0, is_unique_identifier: nil)
189
+ Logging::KameleoonLogger.info(
190
+ "CALL: KameleoonClient.track_conversion(visitor_code: '%s', goal_id: %s, revenue: %s, is_unique_identifier: %s)",
191
+ visitor_code, goal_id, revenue, is_unique_identifier
192
+ )
147
193
  Utils::VisitorCode.validate(visitor_code)
194
+ set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
148
195
  add_data(visitor_code, Conversion.new(goal_id, revenue))
149
- flush(visitor_code, is_unique_identifier: is_unique_identifier)
196
+ @tracking_manager.add_visitor_code(visitor_code)
197
+ Logging::KameleoonLogger.info(
198
+ "RETURN: KameleoonClient.track_conversion(visitor_code: '%s', goal_id: %s, revenue: %s, is_unique_identifier: %s)",
199
+ visitor_code, goal_id, revenue, is_unique_identifier
200
+ )
150
201
  end
151
202
 
152
203
  ##
@@ -157,20 +208,44 @@ module Kameleoon
157
208
  # With this method you can manually send it.
158
209
  #
159
210
  # @param [String] visitor_code Optional field - Visitor code, without visitor code it flush all of the data
160
- # @param [Bool] is_unique_identifier Parameter that specifies whether the visitorCode is a unique identifier.
161
- # This field is optional.
162
- #
163
- # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is not nil and is empty or longer than 255 chars
164
- #
165
- def flush(visitor_code = nil, is_unique_identifier: false)
166
- Utils::VisitorCode.validate(visitor_code) unless visitor_code.nil?
211
+ # @param [Bool] instant A boolean flag indicating whether the data should be sent instantly (`true`) or
212
+ # according to the scheduled tracking interval (`false`).
213
+ # @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
214
+ # identifier. This field is optional.
215
+ #
216
+ # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is not nil and is empty or
217
+ # longer than 255 chars
218
+ #
219
+ def flush(visitor_code = nil, instant: false, is_unique_identifier: nil)
220
+ Logging::KameleoonLogger.info(
221
+ "CALL: KameleoonClient.flush(visitor_code: '%s', instant: %s, is_unique_identifier: %s)",
222
+ visitor_code, instant, is_unique_identifier
223
+ )
167
224
  if visitor_code.nil?
168
225
  @visitor_manager.enumerate do |visitor_code, visitor|
169
- _send_tracking_request(visitor_code, visitor, false, is_unique_identifier)
226
+ has_unsent_data = false
227
+ visitor.enumerate_sendable_data do |data|
228
+ if data.unsent
229
+ has_unsent_data = true
230
+ next false
231
+ end
232
+ next true
233
+ end
234
+ @tracking_manager.add_visitor_code(visitor_code) if has_unsent_data
170
235
  end
171
236
  else
172
- _send_tracking_request(visitor_code, nil, true, is_unique_identifier)
237
+ Utils::VisitorCode.validate(visitor_code)
238
+ set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
239
+ if instant
240
+ @tracking_manager.track_visitor(visitor_code)
241
+ else
242
+ @tracking_manager.add_visitor_code(visitor_code)
243
+ end
173
244
  end
245
+ Logging::KameleoonLogger.info(
246
+ "RETURN: KameleoonClient.flush(visitor_code: '%s', instant: %s, is_unique_identifier: %s)",
247
+ visitor_code, instant, is_unique_identifier
248
+ )
174
249
  end
175
250
 
176
251
  ##
@@ -186,20 +261,32 @@ module Kameleoon
186
261
  #
187
262
  # @param [String] visitor_code Unique identifier of the user. This field is mandatory.
188
263
  # @param [String] feature_key Key of the feature flag you want to expose to a user. This field is mandatory.
189
- # @param [Bool] is_unique_identifier Parameter that specifies whether the visitorCode is a unique identifier.
190
- # This field is optional.
264
+ # @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
265
+ # identifier. This field is optional.
191
266
  #
192
267
  # @raise [Kameleoon::Exception::FeatureNotFound] Feature Flag isn't found in this configuration
193
268
  # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars
194
269
  #
195
- def feature_active?(visitor_code, feature_key, is_unique_identifier: false)
196
- _, variation_key = _get_feature_variation_key(visitor_code, feature_key, is_unique_identifier)
197
- variation_key != Kameleoon::Configuration::VariationType::VARIATION_OFF
270
+ def feature_active?(visitor_code, feature_key, is_unique_identifier: nil)
271
+ Logging::KameleoonLogger.info(
272
+ "CALL: KameleoonClient.feature_active?(visitor_code: '%s', feature_key: '%s', is_unique_identifier: %s)",
273
+ visitor_code, feature_key, is_unique_identifier
274
+ )
275
+ Utils::VisitorCode.validate(visitor_code)
276
+ set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
277
+ _, variation_key = _get_feature_variation_key(visitor_code, feature_key)
278
+ feature_active = variation_key != Kameleoon::Configuration::VariationType::VARIATION_OFF
279
+ Logging::KameleoonLogger.info(
280
+ "RETURN: KameleoonClient.feature_active?(visitor_code: '%s', feature_key: '%s', is_unique_identifier: %s) " \
281
+ '-> (feature_active: false)', visitor_code, feature_key, is_unique_identifier
282
+ )
283
+ feature_active
198
284
  rescue Exception::FeatureEnvironmentDisabled
285
+ Logging::KameleoonLogger.debug('Feature environment disabled')
199
286
  false
200
287
  end
201
288
 
202
- #
289
+ ##
203
290
  # get_feature_variation_key returns a variation key for visitor code
204
291
  #
205
292
  # This method takes a visitorCode and featureKey as mandatory arguments and
@@ -210,16 +297,28 @@ module Kameleoon
210
297
  #
211
298
  # @param [String] visitor_code
212
299
  # @param [String] feature_key
213
- # @param [Bool] is_unique_identifier Parameter that specifies whether the visitorCode is a unique identifier.
214
- # This field is optional.
300
+ # @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
301
+ # identifier. This field is optional.
215
302
  #
216
303
  # @raise [Kameleoon::Exception::FeatureNotFound] Feature Flag isn't found in this configuration
217
304
  # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars
218
305
  # @raise [Kameleoon::Exception::FeatureEnvironmentDisabled] If the requested feature flag is disabled for
219
306
  # the current environment
220
307
  #
221
- def get_feature_variation_key(visitor_code, feature_key, is_unique_identifier: false)
222
- _, variation_key = _get_feature_variation_key(visitor_code, feature_key, is_unique_identifier)
308
+ def get_feature_variation_key(visitor_code, feature_key, is_unique_identifier: nil)
309
+ Logging::KameleoonLogger.info(
310
+ "CALL: KameleoonClient.get_feature_variation_key(visitor_code: '%s', feature_key: '%s', " \
311
+ 'is_unique_identifier: %s)',
312
+ visitor_code, feature_key, is_unique_identifier
313
+ )
314
+ Utils::VisitorCode.validate(visitor_code)
315
+ set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
316
+ _, variation_key = _get_feature_variation_key(visitor_code, feature_key)
317
+ Logging::KameleoonLogger.info(
318
+ "RETURN: KameleoonClient.get_feature_variation_key(visitor_code: '%s', feature_key: '%s', " \
319
+ "is_unique_identifier: %s) -> (variation_key: '%s')",
320
+ visitor_code, feature_key, is_unique_identifier, variation_key
321
+ )
223
322
  variation_key
224
323
  end
225
324
 
@@ -231,8 +330,8 @@ module Kameleoon
231
330
  # @param [String] visitor_code
232
331
  # @param [String] feature_key
233
332
  # @param [String] variable_name
234
- # @param [Bool] is_unique_identifier Parameter that specifies whether the visitorCode is a unique identifier.
235
- # This field is optional.
333
+ # @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
334
+ # identifier. This field is optional.
236
335
  #
237
336
  # @raise [Kameleoon::Exception::FeatureNotFound] Feature Flag isn't found in this configuration
238
337
  # @raise [Kameleoon::Exception::FeatureVariableNotFound]
@@ -240,15 +339,27 @@ module Kameleoon
240
339
  # @raise [Kameleoon::Exception::FeatureEnvironmentDisabled] If the requested feature flag is disabled for
241
340
  # the current environment
242
341
  #
243
- def get_feature_variable(visitor_code, feature_key, variable_name, is_unique_identifier: false)
244
- feature_flag, variation_key = _get_feature_variation_key(visitor_code, feature_key, is_unique_identifier)
342
+ def get_feature_variable(visitor_code, feature_key, variable_name, is_unique_identifier: nil)
343
+ Logging::KameleoonLogger.info(
344
+ "CALL: KameleoonClient.get_feature_variable(visitor_code: '%s', feature_key: '%s', variable_name: '%s', " \
345
+ 'is_unique_identifier: %s)', visitor_code, feature_key, variable_name, is_unique_identifier
346
+ )
347
+ Utils::VisitorCode.validate(visitor_code)
348
+ set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
349
+ feature_flag, variation_key = _get_feature_variation_key(visitor_code, feature_key)
245
350
  variation = feature_flag.get_variation_key(variation_key)
246
351
  variable = variation&.get_variable_by_key(variable_name)
247
352
  if variable.nil?
248
353
  raise Exception::FeatureVariableNotFound.new(variable_name),
249
354
  "Feature variable #{variable_name} not found"
250
355
  end
251
- _parse_feature_variable(variable)
356
+ value = _parse_feature_variable(variable)
357
+ Logging::KameleoonLogger.info(
358
+ "RETURN: KameleoonClient.get_feature_variable(visitor_code: '%s', feature_key: '%s', variable_name: '%s', " \
359
+ 'is_unique_identifier: %s) -> (variable: %s)',
360
+ visitor_code, feature_key, variable_name, is_unique_identifier, value
361
+ )
362
+ value
252
363
  end
253
364
 
254
365
  ##
@@ -266,7 +377,11 @@ module Kameleoon
266
377
  # @raise [Kameleoon::Exception::FeatureEnvironmentDisabled]
267
378
  #
268
379
  def get_feature_variation_variables(feature_key, variation_key)
269
- feature_flag = @data_file.get_feature_flag(feature_key)
380
+ Logging::KameleoonLogger.info(
381
+ "CALL: KameleoonClient.get_feature_variation_variables(feature_key: '%s', variation_key: '%s')",
382
+ feature_key, variation_key
383
+ )
384
+ feature_flag = @data_manager.data_file.get_feature_flag(feature_key)
270
385
  variation = feature_flag.get_variation_key(variation_key)
271
386
  if variation.nil?
272
387
  raise Exception::FeatureVariationNotFound.new(variation_key),
@@ -274,6 +389,10 @@ module Kameleoon
274
389
  end
275
390
  variables = {}
276
391
  variation.variables.each { |var| variables[var.key] = _parse_feature_variable(var) }
392
+ Logging::KameleoonLogger.info(
393
+ "RETURN: KameleoonClient.get_feature_variation_variables(feature_key: '%s', variation_key: '%s') " \
394
+ '-> (variables: %s)', feature_key, variation_key, variables
395
+ )
277
396
  variables
278
397
  end
279
398
 
@@ -290,7 +409,14 @@ module Kameleoon
290
409
  #
291
410
  # @return [Hash] Hash object of the json object.
292
411
  def get_remote_data(key, timeout = @default_timeout)
293
- @remote_data_manager.get_data(key, timeout)
412
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.get_remote_data(key: '%s', timeout: %s)",
413
+ key, timeout)
414
+ remote_data = @remote_data_manager.get_data(key, timeout)
415
+ Logging::KameleoonLogger.info(
416
+ "RETURN: KameleoonClient.get_remote_data(key: '%s', timeout: %s) -> (remote_data: %s)",
417
+ key, timeout, remote_data
418
+ )
419
+ remote_data
294
420
  end
295
421
 
296
422
  ##
@@ -304,12 +430,24 @@ module Kameleoon
304
430
  # for a visitor. If not specified, the default value is `True`. This field is optional.
305
431
  # @param [Integer] timeout Timeout for request (in milliseconds). Equals default_timeout in a config file.
306
432
  # This field is optional.
307
- # @param [Bool] is_unique_identifier Parameter that specifies whether the visitorCode is a unique identifier.
308
- # This field is optional.
433
+ # @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
434
+ # identifier. This field is optional.
309
435
  #
310
436
  # @return [Array] An array of data assigned to the given visitor.
311
- def get_remote_visitor_data(visitor_code, timeout = nil, add_data: true, filter: nil, is_unique_identifier: false)
312
- @remote_data_manager.get_visitor_data(visitor_code, add_data, filter, is_unique_identifier, timeout)
437
+ #
438
+ def get_remote_visitor_data(visitor_code, timeout = nil, add_data: true, filter: nil, is_unique_identifier: nil)
439
+ Logging::KameleoonLogger.info(
440
+ "CALL: KameleoonClient.get_remote_visitor_data(visitor_code: '%s', timeout: %s, add_data: %s, " \
441
+ 'filter: %s, is_unique_identifier: %s)', visitor_code, timeout, add_data, filter, is_unique_identifier
442
+ )
443
+ set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
444
+ visitor_data = @remote_data_manager.get_visitor_data(visitor_code, add_data, filter, timeout)
445
+ Logging::KameleoonLogger.info(
446
+ "RETURN: KameleoonClient.get_remote_visitor_data(visitor_code: '%s', timeout: %s, add_data: %s, " \
447
+ 'filter: %s, is_unique_identifier: %s) -> (visitor_data: %s)',
448
+ visitor_code, timeout, add_data, filter, is_unique_identifier, visitor_data
449
+ )
450
+ visitor_data
313
451
  end
314
452
 
315
453
  ##
@@ -336,7 +474,18 @@ module Kameleoon
336
474
  #
337
475
  # @return [Kameleoon::CustomData] A `CustomData` instance confirming that the data has been added to the visitor.
338
476
  def get_visitor_warehouse_audience(visitor_code, custom_data_index, timeout = nil, warehouse_key: nil)
339
- @warehouse_manager.get_visitor_warehouse_audience(visitor_code, custom_data_index, warehouse_key, timeout)
477
+ Logging::KameleoonLogger.info(
478
+ "CALL: KameleoonClient.get_visitor_warehouse_audience(visitor_code: '%s', custom_data_index: %s, " \
479
+ "timeout: %s, warehouse_key: '%s')", visitor_code, custom_data_index, timeout, warehouse_key
480
+ )
481
+ warehouse_audience = @warehouse_manager.get_visitor_warehouse_audience(visitor_code,
482
+ custom_data_index, warehouse_key, timeout)
483
+ Logging::KameleoonLogger.info(
484
+ "RETURN: KameleoonClient.get_visitor_warehouse_audience(visitor_code: '%s', custom_data_index: %s, " \
485
+ "timeout: %s, warehouse_key: '%s') -> (warehouse_audience: %s)",
486
+ visitor_code, custom_data_index, timeout, warehouse_key, warehouse_audience
487
+ )
488
+ warehouse_audience
340
489
  end
341
490
 
342
491
  ##
@@ -344,7 +493,10 @@ module Kameleoon
344
493
  #
345
494
  # @return [Array] array of all feature flag keys
346
495
  def get_feature_list # rubocop:disable Naming/AccessorMethodName
347
- @data_file.feature_flags.keys
496
+ Logging::KameleoonLogger.info('CALL: KameleoonClient.get_feature_list')
497
+ features = @data_manager.data_file.feature_flags.keys
498
+ Logging::KameleoonLogger.info('RETURN: KameleoonClient.get_feature_list -> (features: %s)', features)
499
+ features
348
500
  end
349
501
 
350
502
  ##
@@ -356,16 +508,23 @@ module Kameleoon
356
508
  #
357
509
  # DEPRECATED. Please use `get_active_features` instead.
358
510
  def get_active_feature_list_for_visitor(visitor_code)
359
- warn '[DEPRECATION] `get_active_feature_list_for_visitor` is deprecated. Please use `get_active_features` instead.'
511
+ Logging::KameleoonLogger.warning('[DEPRECATION] `get_active_feature_list_for_visitor` is deprecated.' \
512
+ ' Please use `get_active_features` instead.')
513
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.get_active_feature_list_for_visitor(visitor_code: '%s')",
514
+ visitor_code)
360
515
  Utils::VisitorCode.validate(visitor_code)
361
516
  list_keys = []
362
- @data_file.feature_flags.each do |feature_key, feature_flag|
517
+ @data_manager.data_file.feature_flags.each do |feature_key, feature_flag|
363
518
  next unless feature_flag.environment_enabled
364
519
 
365
520
  variation, rule, = _calculate_variation_key_for_feature(visitor_code, feature_flag)
366
521
  variation_key = _get_variation_key(variation, rule, feature_flag)
367
522
  list_keys.push(feature_key) if variation_key != Kameleoon::Configuration::VariationType::VARIATION_OFF
368
523
  end
524
+ Logging::KameleoonLogger.info(
525
+ "RETURN: KameleoonClient.get_active_feature_list_for_visitor(visitor_code: '%s') -> (features: %s)",
526
+ visitor_code, list_keys
527
+ )
369
528
  list_keys
370
529
  end
371
530
 
@@ -379,10 +538,11 @@ module Kameleoon
379
538
  #
380
539
  # @return [Hash] Hash of active features for a visitor
381
540
  def get_active_features(visitor_code)
541
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.get_active_features(visitor_code: '%s')", visitor_code)
382
542
  Utils::VisitorCode.validate(visitor_code)
383
543
  map_active_features = {}
384
544
 
385
- @data_file.feature_flags.each_value do |feature_flag|
545
+ @data_manager.data_file.feature_flags.each_value do |feature_flag|
386
546
  next unless feature_flag.environment_enabled
387
547
 
388
548
  var_by_exp, rule = _calculate_variation_key_for_feature(visitor_code, feature_flag)
@@ -411,6 +571,9 @@ module Kameleoon
411
571
  end
412
572
 
413
573
  map_active_features.freeze
574
+ Logging::KameleoonLogger.info("RETURN: KameleoonClient.get_active_features(visitor_code: '%s') -> (features: %s)",
575
+ visitor_code, map_active_features)
576
+ map_active_features
414
577
  end
415
578
 
416
579
  ##
@@ -421,6 +584,7 @@ module Kameleoon
421
584
  # @param handler [Callable | NilClass] The handler that will be called when the configuration
422
585
  # is updated using a real-time configuration event.
423
586
  def on_update_configuration(handler)
587
+ Logging::KameleoonLogger.info('CALL/RETURN: KameleoonClient.on_update_configuration(handler)')
424
588
  @update_configuration_handler = handler
425
589
  end
426
590
 
@@ -433,8 +597,14 @@ module Kameleoon
433
597
  # @return [String] JavasScript code to be inserted in your page to send automatically
434
598
  # the exposure events to the analytics solution you are using.
435
599
  def get_engine_tracking_code(visitor_code)
600
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.get_engine_tracking_code(visitor_code: '%s')", visitor_code)
436
601
  visitor_variations = @visitor_manager.get_visitor(visitor_code)&.variations
437
- @hybrid_manager.get_engine_tracking_code(visitor_variations)
602
+ engine_tracking_code = @hybrid_manager.get_engine_tracking_code(visitor_variations)
603
+ Logging::KameleoonLogger.info(
604
+ "RETURN: KameleoonClient.get_engine_tracking_code(visitor_code: '%s') -> (engine_tracking_code: '%s')",
605
+ visitor_code, engine_tracking_code
606
+ )
607
+ engine_tracking_code
438
608
  end
439
609
 
440
610
  private
@@ -442,17 +612,17 @@ module Kameleoon
442
612
  HYBRID_EXPIRATION_TIME = 5
443
613
 
444
614
  def fetch_configuration_initially
445
- log('Initial configuration fetch is started.')
615
+ Logging::KameleoonLogger.info('Initial configuration fetch is started.')
446
616
  Thread.new do
447
617
  ok = false
448
618
  begin
449
619
  ok = obtain_configuration
450
- log('Initial configuration fetch failed') unless ok
620
+ Logging::KameleoonLogger.error('Initial configuration fetch failed') unless ok
451
621
  rescue StandardError => e
452
- log("Initial configuration fetch failed: #{e}")
622
+ Logging::KameleoonLogger.error('Initial configuration fetch failed: %s', e)
453
623
  end
454
624
  @readiness.set(ok)
455
- manage_configuration_update(@data_file.settings.real_time_update) if ok
625
+ manage_configuration_update(@data_manager.data_file.settings.real_time_update) if ok
456
626
  end
457
627
  end
458
628
 
@@ -462,21 +632,23 @@ module Kameleoon
462
632
  begin
463
633
  ok = obtain_configuration(time_stamp)
464
634
  rescue StandardError => e
465
- log("Error occurred during configuration fetching: #{e}")
635
+ Logging::KameleoonLogger.error('Error occurred during configuration fetching: %s', e)
466
636
  end
467
- if !ok && @data_file.settings.real_time_update
468
- @data_file.settings.real_time_update = false
469
- log('Switching to polling mode due to failed fetch')
637
+ real_time_update = @data_manager.data_file.settings.real_time_update
638
+ if !ok && real_time_update
639
+ @data_manager.data_file.settings.real_time_update = false
640
+ real_time_update = false
641
+ Logging::KameleoonLogger.warning('Switching to polling mode due to failed fetch')
470
642
  end
471
- manage_configuration_update(@data_file.settings.real_time_update)
643
+ manage_configuration_update(real_time_update)
472
644
  end
473
645
  end
474
646
 
475
647
  def start_configuration_update_job_if_needed
476
648
  return unless @fetch_configuration_update_job.nil?
477
649
 
478
- @fetch_configuration_update_job = Rufus::Scheduler.singleton.schedule_every @config.refresh_interval_second do
479
- log('Scheduled job to fetch configuration is started.')
650
+ @fetch_configuration_update_job = @scheduler.schedule_every @config.refresh_interval_second do
651
+ Logging::KameleoonLogger.info('Scheduled job to fetch configuration is started.')
480
652
  fetch_configuration_job
481
653
  end
482
654
  end
@@ -484,9 +656,9 @@ module Kameleoon
484
656
  def stop_configuration_update_job_if_needed
485
657
  return if @fetch_configuration_update_job.nil?
486
658
 
487
- @fetch_configuration_update_job.unschedule
659
+ @fetch_configuration_update_job&.unschedule
488
660
  @fetch_configuration_update_job = nil
489
- log('Scheduled job to fetch configuration is stopped.')
661
+ Logging::KameleoonLogger.info('Scheduled job to fetch configuration is stopped.')
490
662
  end
491
663
 
492
664
  def start_real_time_configuration_service_if_needed
@@ -495,13 +667,11 @@ module Kameleoon
495
667
  url = @network_manager.url_provider.make_real_time_url
496
668
  fetch_func = proc { |real_time_event| fetch_configuration_job(real_time_event.time_stamp) }
497
669
  @real_time_configuration_service =
498
- Kameleoon::RealTime::RealTimeConfigurationService.new(url, fetch_func, method(:log))
670
+ Kameleoon::RealTime::RealTimeConfigurationService.new(url, fetch_func)
499
671
  end
500
672
 
501
673
  def stop_real_time_configuration_service_if_needed
502
- return if @real_time_configuration_service.nil?
503
-
504
- @real_time_configuration_service.close
674
+ @real_time_configuration_service&.close
505
675
  @real_time_configuration_service = nil
506
676
  end
507
677
 
@@ -530,24 +700,23 @@ module Kameleoon
530
700
  # end
531
701
 
532
702
  def obtain_configuration(time_stamp = nil)
533
- log 'Fetching configuration from Client-Config service'
703
+ Logging::KameleoonLogger.info('Fetching configuration from Client-Config service')
534
704
  response = @network_manager.fetch_configuration(time_stamp)
535
705
  return false unless response
536
706
 
537
707
  configuration = JSON.parse(response)
538
- @data_file = Configuration::DataFile.new(@config.environment, method(:log)).init(configuration)
539
- apply_new_configuration(@data_file)
708
+ data_file = Configuration::DataFile.new(@config.environment, configuration)
709
+ apply_new_configuration(data_file)
540
710
  call_update_handler_if_needed(!time_stamp.nil?)
541
- log "Feature flags are fetched: #{response.inspect}"
711
+ Logging::KameleoonLogger.info('Feature flags are fetched: %s', response.inspect)
542
712
  true
543
713
  end
544
714
 
545
715
  def apply_new_configuration(data_file)
546
- @cookie_manager.consent_required =
547
- data_file.settings.is_consent_required && !data_file.has_any_targeted_delivery_rule
716
+ Logging::KameleoonLogger.debug('CALL: KameleoonClient.apply_new_configuration(data_file: %s)', data_file)
717
+ @data_manager.data_file = data_file
548
718
  @network_manager.url_provider.apply_data_api_domain(data_file.settings.data_api_domain)
549
- @targeting_manager = Kameleoon::Targeting::TargetingManager.new(@visitor_manager, data_file)
550
- @visitor_manager.custom_data_info = data_file.custom_data_info
719
+ Logging::KameleoonLogger.debug('RETURN: KameleoonClient.apply_new_configuration(data_file: %s)', data_file)
551
720
  end
552
721
 
553
722
  ##
@@ -561,13 +730,13 @@ module Kameleoon
561
730
  end
562
731
 
563
732
  def dispose
733
+ Logging::KameleoonLogger.debug('CALL: KameleoonClient.dispose')
564
734
  stop_configuration_update_job_if_needed
565
735
  stop_real_time_configuration_service_if_needed
566
736
  @visitor_manager.stop
567
- end
568
-
569
- def log(text)
570
- print "Kameleoon SDK Log: #{text}\n" if @verbose_mode
737
+ @tracking_manager.stop
738
+ @scheduler.shutdown
739
+ Logging::KameleoonLogger.debug('RETURN: KameleoonClient.dispose')
571
740
  end
572
741
 
573
742
  # Uncomment when using storage
@@ -587,8 +756,12 @@ module Kameleoon
587
756
 
588
757
  ##
589
758
  # helper method for getting variation key for feature flag
590
- def _get_feature_variation_key(visitor_code, feature_key, is_unique_identifier = false)
591
- feature_flag = @data_file.get_feature_flag(feature_key)
759
+ def _get_feature_variation_key(visitor_code, feature_key)
760
+ Logging::KameleoonLogger.debug(
761
+ "CALL: KameleoonClient._get_feature_variation_key(visitor_code: '%s', feature_key: '%s')",
762
+ visitor_code, feature_key
763
+ )
764
+ feature_flag = @data_manager.data_file.get_feature_flag(feature_key)
592
765
  variation, rule = _calculate_variation_key_for_feature(visitor_code, feature_flag)
593
766
  variation_key = _get_variation_key(variation, rule, feature_flag)
594
767
  visitor = nil
@@ -601,13 +774,22 @@ module Kameleoon
601
774
  visitor.assign_variation(as_variation)
602
775
  end
603
776
  end
604
- flush(visitor_code, is_unique_identifier: is_unique_identifier)
777
+ @tracking_manager.add_visitor_code(visitor_code)
778
+ Logging::KameleoonLogger.debug(
779
+ "RETURN: KameleoonClient._get_feature_variation_key(visitor_code: '%s', feature_key: '%s')" \
780
+ " -> (feature_flag: %s, variation_key: '%s')",
781
+ visitor_code, feature_key, feature_flag, variation_key
782
+ )
605
783
  [feature_flag, variation_key]
606
784
  end
607
785
 
608
786
  ##
609
787
  # helper method for calculate variation key for feature flag
610
788
  def _calculate_variation_key_for_feature(visitor_code, feature_flag)
789
+ Logging::KameleoonLogger.debug(
790
+ "CALL: KameleoonClient._calculate_variation_key_for_feature(visitor_code: '%s', feature_flag: %s)",
791
+ visitor_code, feature_flag
792
+ )
611
793
  # no rules -> return default_variation_key
612
794
  feature_flag.rules.each do |rule|
613
795
  # check if visitor is targeted for rule, else next rule
@@ -618,20 +800,41 @@ module Kameleoon
618
800
  code_for_hash = vis&.mapping_identifier || visitor_code
619
801
  # uses for rule exposition
620
802
  hash_rule = Utils::HashDouble.obtain_rule(code_for_hash, rule.id, rule.respool_time)
803
+ Logging::KameleoonLogger.debug("Calculated hash_rule: %s for visitor_code: '%s'", hash_rule, code_for_hash)
621
804
  # check main expostion for rule with hashRule
622
805
  if hash_rule <= rule.exposition
623
- return [rule.first_variation, rule] if rule.targeted_delivery_type?
806
+ if rule.targeted_delivery_type?
807
+ Logging::KameleoonLogger.debug(
808
+ "RETURN: KameleoonClient._calculate_variation_key_for_feature(visitor_code: '%s', feature_flag: %s) " \
809
+ '-> (variation: %s, rule: %s)',
810
+ visitor_code, feature_flag, rule.first_variation, rule
811
+ )
812
+ return [rule.first_variation, rule]
813
+ end
624
814
 
625
815
  # uses for variation's expositions
626
816
  hash_variation = Utils::HashDouble.obtain_rule(code_for_hash, rule.experiment_id, rule.respool_time)
817
+ Logging::KameleoonLogger.debug(
818
+ "Calculated hash_variation: %s for visitor_code: '%s'", hash_variation, code_for_hash
819
+ )
627
820
  # get variation key with new hashVariation
628
821
  variation = rule.get_variation(hash_variation)
629
- return [variation, rule] unless variation.nil?
822
+ unless variation.nil?
823
+ Logging::KameleoonLogger.debug(
824
+ "RETURN: KameleoonClient._calculate_variation_key_for_feature(visitor_code: '%s', " \
825
+ 'feature_flag: %s) -> (variation: %s, rule: %s)', visitor_code, feature_flag, variation, rule
826
+ )
827
+ return [variation, rule]
828
+ end
630
829
  # if visitor is targeted for targeted rule then break cycle -> return default
631
830
  elsif rule.targeted_delivery_type?
632
831
  break
633
832
  end
634
833
  end
834
+ Logging::KameleoonLogger.debug(
835
+ "RETURN: KameleoonClient._calculate_variation_key_for_feature(visitor_code: '%s', feature_flag: %s) " \
836
+ '-> (variation: nil, rule: nil)', visitor_code, feature_flag
837
+ )
635
838
  [nil, nil]
636
839
  end
637
840
 
@@ -642,55 +845,6 @@ module Kameleoon
642
845
  feature_flag.default_variation_key
643
846
  end
644
847
 
645
- ##
646
- # helper method for sending tracking requests for new FF
647
- def _send_tracking_request(visitor_code, visitor = nil, force_request = true, is_unique_identifier = false)
648
- if visitor.nil?
649
- visitor = @visitor_manager.get_visitor(visitor_code)
650
- return if visitor.nil? && @data_file.settings.is_consent_required
651
- end
652
- use_mapping_value, visitor = create_anonymous_if_required(visitor_code, visitor, is_unique_identifier)
653
- consent = consent_provided?(visitor)
654
- user_agent = visitor&.user_agent
655
- unsent = visitor.nil? ? [] : select_unsent_data(visitor, consent)
656
- if unsent.empty?
657
- return unless force_request && consent
658
-
659
- unsent.push(Network::ActivityEvent.new)
660
- end
661
- log "Start post tracking: #{unsent.inspect}"
662
- @network_manager.send_tracking_data(visitor_code, unsent, user_agent, use_mapping_value)
663
- end
664
-
665
- def create_anonymous_if_required(visitor_code, visitor, is_unique_identifier)
666
- use_mapping_value = is_unique_identifier && !visitor&.mapping_identifier.nil?
667
- # need to find if anonymous visitor is behind unique (anonym doesn't exist if MappingIdentifier == null)
668
- if is_unique_identifier && visitor&.mapping_identifier.nil?
669
- # We haven't anonymous behind, in this case we should create "fake" anonymous with id == visitorCode
670
- # and link it with with mapping value == visitorCode (like we do as we have real anonymous visitor)
671
- visitor = @visitor_manager.add_data(visitor_code,
672
- CustomData.new(@data_file.custom_data_info.mapping_identifier_index,
673
- visitor_code))
674
- end
675
- [use_mapping_value, visitor]
676
- end
677
-
678
- def select_unsent_data(visitor, consent)
679
- unsent = []
680
- if consent
681
- visitor.enumerate_sendable_data { |data| unsent.push(data) unless data.sent }
682
- else
683
- visitor.conversions.enumerate { |conversion| unsent.push(conversion) unless conversion.sent }
684
- if @data_file.has_any_targeted_delivery_rule
685
- visitor.variations.enumerate do |variation|
686
- unsent.push(variation) unless
687
- variation.sent || (variation.rule_type != Configuration::RuleType::TARGETED_DELIVERY)
688
- end
689
- end
690
- end
691
- unsent
692
- end
693
-
694
848
  ##
695
849
  # helper method for fetching values from a Variable
696
850
  def _parse_feature_variable(variable)
@@ -705,8 +859,9 @@ module Kameleoon
705
859
  end
706
860
  end
707
861
 
708
- def consent_provided?(visitor)
709
- !@data_file.settings.is_consent_required || visitor&.legal_consent
862
+ def set_unique_identifier(visitor_code, is_unique_identifier)
863
+ Logging::KameleoonLogger.warning("The 'isUniqueIdentifier' parameter is deprecated. Please, add 'UniqueIdentifier' to a visitor instead.")
864
+ @visitor_manager.add_data(visitor_code, UniqueIdentifier.new(is_unique_identifier))
710
865
  end
711
866
  end
712
867
  end