kameleoon-client-ruby 3.3.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -1,26 +1,31 @@
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'
27
+ require 'kameleoon/types/variable'
28
+ require 'kameleoon/types/variation'
24
29
  require 'rufus/scheduler'
25
30
  require 'yaml'
26
31
  require 'json'
@@ -43,32 +48,50 @@ module Kameleoon
43
48
  def initialize(site_code, config)
44
49
  raise Exception::SiteCodeIsEmpty, 'Provided site_sode is empty' if site_code&.empty? != false
45
50
 
51
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.new(site_code: '%s', config: %s)",
52
+ site_code, config)
53
+ @scheduler = Rufus::Scheduler.new
46
54
  @site_code = site_code
47
55
  @config = config
48
56
  @real_time_configuration_service = nil
49
57
  @update_configuration_handler = nil
50
58
  @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))
59
+ data_file = Configuration::DataFile.new(config.environment, nil)
60
+ @data_manager = Managers::Data::DataManager.new(data_file)
61
+ @visitor_manager = Kameleoon::DataManager::VisitorManager.new(
62
+ @data_manager, config.session_duration_second, @scheduler
63
+ )
64
+ @hybrid_manager = Hybrid::ManagerImpl.new(HYBRID_EXPIRATION_TIME, @data_manager)
54
65
  @network_manager = Network::NetworkManager.new(
55
66
  config.environment,
56
67
  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)
60
- )
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)
68
+ Network::AccessTokenSourceFactory.new(config.client_id, config.client_secret),
69
+ Network::UrlProvider.new(site_code)
70
+ )
71
+ @tracking_manager = Managers::Tracking::TrackingManager.new(
72
+ @data_manager, @network_manager, @visitor_manager, config.tracking_interval_second, @scheduler
73
+ )
74
+ @warehouse_manager = Managers::Warehouse::WarehouseManager.new(@network_manager, @visitor_manager)
75
+ @remote_data_manager = Managers::RemoteData::RemoteDataManager.new(
76
+ @data_manager, @network_manager, @visitor_manager
77
+ )
78
+ @cookie_manager = Network::Cookie::CookieManager.new(@data_manager, config.top_level_domain)
65
79
  @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
80
+ @targeting_manager = Targeting::TargetingManager.new(@data_manager, @visitor_manager)
81
+
82
+ if @config.verbose_mode == true && Logging::KameleoonLogger.log_level == Logging::LogLevel::WARNING
83
+ Logging::KameleoonLogger.log_level = Logging::LogLevel::INFO
84
+ end
85
+
86
+ Logging::KameleoonLogger.info("RETURN: KameleoonClient.new(site_code: '%s', config: %s)",
87
+ site_code, config)
68
88
  end
69
89
 
70
90
  def wait_init
71
- @readiness.wait
91
+ Logging::KameleoonLogger.info('CALL: KameleoonClient.wait_init')
92
+ result = @readiness.wait
93
+ Logging::KameleoonLogger.info('RETURN: KameleoonClient.wait_init -> (result: %s)', result)
94
+ result
72
95
  end
73
96
 
74
97
  ##
@@ -98,14 +121,29 @@ module Kameleoon
98
121
  # visitor_code = get_visitor_code(cookies, 'my-domaine.com')
99
122
  #
100
123
  def get_visitor_code(cookies, default_visitor_code = nil)
101
- @cookie_manager.get_or_add(cookies, default_visitor_code)
124
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.get_visitor_code(cookies: %s, default_visitor_code: '%s')",
125
+ cookies, default_visitor_code)
126
+ visitor_code = @cookie_manager.get_or_add(cookies, default_visitor_code)
127
+ Logging::KameleoonLogger.info(
128
+ "RETURN: KameleoonClient.get_visitor_code(cookies: %s, default_visitor_code: '%s') -> (visitor_code: '%s')",
129
+ cookies, default_visitor_code, visitor_code
130
+ )
131
+ visitor_code
102
132
  end
103
133
 
104
134
  def set_legal_consent(visitor_code, consent, cookies = nil)
135
+ Logging::KameleoonLogger.info(
136
+ "CALL: KameleoonClient.set_legal_consent(visitor_code: '%s', consent: %s, cookies: %s)",
137
+ visitor_code, consent, cookies
138
+ )
105
139
  Utils::VisitorCode.validate(visitor_code)
106
140
  visitor = @visitor_manager.get_or_create_visitor(visitor_code)
107
141
  visitor.legal_consent = consent
108
142
  @cookie_manager.update(visitor_code, consent, cookies)
143
+ Logging::KameleoonLogger.info(
144
+ "RETURN: KameleoonClient.set_legal_consent(visitor_code: '%s', consent: %s, cookies: %s)",
145
+ visitor_code, consent, cookies
146
+ )
109
147
  end
110
148
 
111
149
  ##
@@ -122,8 +160,14 @@ module Kameleoon
122
160
  # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars
123
161
  #
124
162
  def add_data(visitor_code, *args)
163
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.add_data(visitor_code: '%s', args: %s)",
164
+ visitor_code, args)
125
165
  Utils::VisitorCode.validate(visitor_code)
126
166
  @visitor_manager.add_data(visitor_code, *args)
167
+ Logging::KameleoonLogger.info(
168
+ "RETURN: KameleoonClient.add_data(visitor_code: '%s', args: %s)",
169
+ visitor_code, args
170
+ )
127
171
  end
128
172
 
129
173
  ##
@@ -138,15 +182,24 @@ module Kameleoon
138
182
  # @param [String] visitor_code Visitor code
139
183
  # @param [Integer] goal_id Id of the goal
140
184
  # @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.
185
+ # @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
186
+ # identifier. This field is optional.
143
187
  #
144
188
  # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars
145
189
  #
146
- def track_conversion(visitor_code, goal_id, revenue = 0.0, is_unique_identifier: false)
190
+ def track_conversion(visitor_code, goal_id, revenue = 0.0, is_unique_identifier: nil)
191
+ Logging::KameleoonLogger.info(
192
+ "CALL: KameleoonClient.track_conversion(visitor_code: '%s', goal_id: %s, revenue: %s, is_unique_identifier: %s)",
193
+ visitor_code, goal_id, revenue, is_unique_identifier
194
+ )
147
195
  Utils::VisitorCode.validate(visitor_code)
196
+ set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
148
197
  add_data(visitor_code, Conversion.new(goal_id, revenue))
149
- flush(visitor_code, is_unique_identifier: is_unique_identifier)
198
+ @tracking_manager.add_visitor_code(visitor_code)
199
+ Logging::KameleoonLogger.info(
200
+ "RETURN: KameleoonClient.track_conversion(visitor_code: '%s', goal_id: %s, revenue: %s, is_unique_identifier: %s)",
201
+ visitor_code, goal_id, revenue, is_unique_identifier
202
+ )
150
203
  end
151
204
 
152
205
  ##
@@ -157,20 +210,44 @@ module Kameleoon
157
210
  # With this method you can manually send it.
158
211
  #
159
212
  # @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?
213
+ # @param [Bool] instant A boolean flag indicating whether the data should be sent instantly (`true`) or
214
+ # according to the scheduled tracking interval (`false`).
215
+ # @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
216
+ # identifier. This field is optional.
217
+ #
218
+ # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is not nil and is empty or
219
+ # longer than 255 chars
220
+ #
221
+ def flush(visitor_code = nil, instant: false, is_unique_identifier: nil)
222
+ Logging::KameleoonLogger.info(
223
+ "CALL: KameleoonClient.flush(visitor_code: '%s', instant: %s, is_unique_identifier: %s)",
224
+ visitor_code, instant, is_unique_identifier
225
+ )
167
226
  if visitor_code.nil?
168
227
  @visitor_manager.enumerate do |visitor_code, visitor|
169
- _send_tracking_request(visitor_code, visitor, false, is_unique_identifier)
228
+ has_unsent_data = false
229
+ visitor.enumerate_sendable_data do |data|
230
+ if data.unsent
231
+ has_unsent_data = true
232
+ next false
233
+ end
234
+ next true
235
+ end
236
+ @tracking_manager.add_visitor_code(visitor_code) if has_unsent_data
170
237
  end
171
238
  else
172
- _send_tracking_request(visitor_code, nil, true, is_unique_identifier)
239
+ Utils::VisitorCode.validate(visitor_code)
240
+ set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
241
+ if instant
242
+ @tracking_manager.track_visitor(visitor_code)
243
+ else
244
+ @tracking_manager.add_visitor_code(visitor_code)
245
+ end
173
246
  end
247
+ Logging::KameleoonLogger.info(
248
+ "RETURN: KameleoonClient.flush(visitor_code: '%s', instant: %s, is_unique_identifier: %s)",
249
+ visitor_code, instant, is_unique_identifier
250
+ )
174
251
  end
175
252
 
176
253
  ##
@@ -186,20 +263,117 @@ module Kameleoon
186
263
  #
187
264
  # @param [String] visitor_code Unique identifier of the user. This field is mandatory.
188
265
  # @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.
266
+ # @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
267
+ # identifier. This field is optional.
268
+ # @param [Bool] track Optional flag indicating whether tracking of the feature evaluation is enabled
269
+ # (`true`) or disabled (`false`); the default value is `true`.
270
+ #
271
+ # @return [Bool] If the user has not been associated with your feature flag before, the SDK returns
272
+ # a random boolean value (`true` if the user should have this feature or `false` if not).
191
273
  #
192
274
  # @raise [Kameleoon::Exception::FeatureNotFound] Feature Flag isn't found in this configuration
193
275
  # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars
194
276
  #
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
277
+ def feature_active?(visitor_code, feature_key, is_unique_identifier: nil, track: true)
278
+ Logging::KameleoonLogger.info(
279
+ "CALL: KameleoonClient.feature_active?(visitor_code: '%s', feature_key: '%s', " \
280
+ 'is_unique_identifier: %s, track: %s)',
281
+ visitor_code, feature_key, is_unique_identifier, track
282
+ )
283
+ Utils::VisitorCode.validate(visitor_code)
284
+ set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
285
+ feature_flag = @data_manager.data_file.get_feature_flag(feature_key)
286
+ variation_key, = get_variation_info(visitor_code, feature_flag, track)
287
+ feature_active = variation_key != Kameleoon::Configuration::VariationType::VARIATION_OFF
288
+ @tracking_manager.add_visitor_code(visitor_code) if track
289
+ Logging::KameleoonLogger.info(
290
+ "RETURN: KameleoonClient.feature_active?(visitor_code: '%s', feature_key: '%s', " \
291
+ 'is_unique_identifier: %s, track: %s) -> (feature_active: %s)',
292
+ visitor_code, feature_key, is_unique_identifier, track, feature_active
293
+ )
294
+ feature_active
198
295
  rescue Exception::FeatureEnvironmentDisabled
296
+ Logging::KameleoonLogger.debug('Feature environment disabled')
199
297
  false
200
298
  end
201
299
 
300
+ ##
301
+ # Retrieves the variation assigned to the given visitor for a specific feature flag.
302
+ #
303
+ # @param [String] visitor_code The unique identifier of the visitor.
304
+ # @param [String] feature_key The unique identifier of the feature flag.
305
+ # @param [Bool] track Optional flag indicating whether tracking of the feature evaluation is enabled
306
+ # (`true`) or disabled (`false`); the default value is `true`.
307
+ #
308
+ # @return [Kameleoon::Types::Variation] The variation assigned to the visitor if the visitor is associated with some
309
+ # rule of the feature flag, otherwise the method returns the default variation of the feature flag.
310
+ #
311
+ # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars.
312
+ # @raise [Kameleoon::Exception::FeatureNotFound] Feature Flag isn't found in this configuration.
313
+ # @raise [Kameleoon::Exception::FeatureEnvironmentDisabled] If the requested feature flag is disabled for
314
+ # the current environment.
315
+ def get_variation(visitor_code, feature_key, track: true)
316
+ Logging::KameleoonLogger.info(
317
+ "CALL: KameleoonClient.get_variation(visitor_code: '%s', feature_key: '%s', track: %s)",
318
+ visitor_code, feature_key, track
319
+ )
320
+ Utils::VisitorCode.validate(visitor_code)
321
+ feature_flag = @data_manager.data_file.get_feature_flag(feature_key)
322
+ variation_key, var_by_exp, rule = get_variation_info(visitor_code, feature_flag, track)
323
+ variation = feature_flag.get_variation_by_key(variation_key)
324
+ external_variation = make_external_variation(variation, var_by_exp&.variation_id, rule&.experiment_id)
325
+ @tracking_manager.add_visitor_code(visitor_code) if track
326
+ Logging::KameleoonLogger.info(
327
+ "RETURN: KameleoonClient.get_variation(visitor_code: '%s', feature_key: '%s', track: %s)" \
328
+ ' -> (variation: %s)',
329
+ visitor_code, feature_key, track, external_variation
330
+ )
331
+ external_variation
332
+ end
333
+
334
+ ##
335
+ # Forms a dictionary of variations assigned to a given visitor across all feature flags.
336
+ # This method iterates over all available feature flags and returns the assigned variation for each flag
337
+ # associated with the specified visitor.
202
338
  #
339
+ # @param [String] visitor_code The unique identifier of the visitor.
340
+ # @param [Bool] only_active Optional flag indicating whether to return only variations for active feature
341
+ # flags (`true`) or for any feature flags (`false`); the default value is `false`.
342
+ # @param [Bool] track Optional flag indicating whether tracking of the feature evaluation is enabled
343
+ # (`true`) or disabled (`false`); the default value is `true`.
344
+ #
345
+ # @return [Hash] A hash consisting of feature flag keys as keys (`String`) and their corresponding
346
+ # variations (or the default variation of that feature flag) as values (`Kameleoon::Types::Variation`).
347
+ #
348
+ # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars.
349
+ def get_variations(visitor_code, only_active: false, track: true)
350
+ Logging::KameleoonLogger.info(
351
+ "CALL: KameleoonClient.get_variations(visitor_code: '%s', only_active: %s, track: %s)",
352
+ visitor_code, only_active, track
353
+ )
354
+ Utils::VisitorCode.validate(visitor_code)
355
+ variations = {}
356
+ @data_manager.data_file.feature_flags.each_value do |feature_flag|
357
+ next unless feature_flag.environment_enabled
358
+
359
+ variation_key, var_by_exp, rule = get_variation_info(visitor_code, feature_flag, track)
360
+ next if only_active && (variation_key == Configuration::VariationType::VARIATION_OFF)
361
+
362
+ variation = feature_flag.get_variation_by_key(variation_key)
363
+ variations[feature_flag.feature_key] =
364
+ make_external_variation(variation, var_by_exp&.variation_id, rule&.experiment_id)
365
+ end
366
+ variations.freeze
367
+ @tracking_manager.add_visitor_code(visitor_code) if track
368
+ Logging::KameleoonLogger.info(
369
+ "RETURN: KameleoonClient.get_variations(visitor_code: '%s', only_active: %s, track: %s)" \
370
+ ' -> (variations: %s)',
371
+ visitor_code, only_active, track, variations
372
+ )
373
+ variations
374
+ end
375
+
376
+ ##
203
377
  # get_feature_variation_key returns a variation key for visitor code
204
378
  #
205
379
  # This method takes a visitorCode and featureKey as mandatory arguments and
@@ -210,16 +384,33 @@ module Kameleoon
210
384
  #
211
385
  # @param [String] visitor_code
212
386
  # @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.
387
+ # @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
388
+ # identifier. This field is optional.
215
389
  #
216
390
  # @raise [Kameleoon::Exception::FeatureNotFound] Feature Flag isn't found in this configuration
217
391
  # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars
218
392
  # @raise [Kameleoon::Exception::FeatureEnvironmentDisabled] If the requested feature flag is disabled for
219
393
  # the current environment
220
394
  #
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)
395
+ # DEPRECATED. Please use `get_variation(visitor_code, feature_key, track: true)` instead.
396
+ def get_feature_variation_key(visitor_code, feature_key, is_unique_identifier: nil)
397
+ Logging::KameleoonLogger.info(
398
+ '[DEPRECATION] `get_feature_variation_key` is deprecated. ' \
399
+ 'Please use `get_variation(visitor_code, feature_key, track: true)` instead.'
400
+ )
401
+ Logging::KameleoonLogger.info(
402
+ "CALL: KameleoonClient.get_feature_variation_key(visitor_code: '%s', feature_key: '%s', " \
403
+ 'is_unique_identifier: %s)',
404
+ visitor_code, feature_key, is_unique_identifier
405
+ )
406
+ Utils::VisitorCode.validate(visitor_code)
407
+ set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
408
+ _, variation_key = _get_feature_variation_key(visitor_code, feature_key)
409
+ Logging::KameleoonLogger.info(
410
+ "RETURN: KameleoonClient.get_feature_variation_key(visitor_code: '%s', feature_key: '%s', " \
411
+ "is_unique_identifier: %s) -> (variation_key: '%s')",
412
+ visitor_code, feature_key, is_unique_identifier, variation_key
413
+ )
223
414
  variation_key
224
415
  end
225
416
 
@@ -231,8 +422,8 @@ module Kameleoon
231
422
  # @param [String] visitor_code
232
423
  # @param [String] feature_key
233
424
  # @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.
425
+ # @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
426
+ # identifier. This field is optional.
236
427
  #
237
428
  # @raise [Kameleoon::Exception::FeatureNotFound] Feature Flag isn't found in this configuration
238
429
  # @raise [Kameleoon::Exception::FeatureVariableNotFound]
@@ -240,15 +431,32 @@ module Kameleoon
240
431
  # @raise [Kameleoon::Exception::FeatureEnvironmentDisabled] If the requested feature flag is disabled for
241
432
  # the current environment
242
433
  #
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)
245
- variation = feature_flag.get_variation_key(variation_key)
434
+ # DEPRECATED. Please use `get_variation(visitor_code, feature_key, track: true)` instead.
435
+ def get_feature_variable(visitor_code, feature_key, variable_name, is_unique_identifier: nil)
436
+ Logging::KameleoonLogger.info(
437
+ '[DEPRECATION] `get_feature_variable` is deprecated. ' \
438
+ 'Please use `get_variation(visitor_code, feature_key, track: true)` instead.'
439
+ )
440
+ Logging::KameleoonLogger.info(
441
+ "CALL: KameleoonClient.get_feature_variable(visitor_code: '%s', feature_key: '%s', variable_name: '%s', " \
442
+ 'is_unique_identifier: %s)', visitor_code, feature_key, variable_name, is_unique_identifier
443
+ )
444
+ Utils::VisitorCode.validate(visitor_code)
445
+ set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
446
+ feature_flag, variation_key = _get_feature_variation_key(visitor_code, feature_key)
447
+ variation = feature_flag.get_variation_by_key(variation_key)
246
448
  variable = variation&.get_variable_by_key(variable_name)
247
449
  if variable.nil?
248
450
  raise Exception::FeatureVariableNotFound.new(variable_name),
249
451
  "Feature variable #{variable_name} not found"
250
452
  end
251
- _parse_feature_variable(variable)
453
+ value = _parse_feature_variable(variable)
454
+ Logging::KameleoonLogger.info(
455
+ "RETURN: KameleoonClient.get_feature_variable(visitor_code: '%s', feature_key: '%s', variable_name: '%s', " \
456
+ 'is_unique_identifier: %s) -> (variable: %s)',
457
+ visitor_code, feature_key, variable_name, is_unique_identifier, value
458
+ )
459
+ value
252
460
  end
253
461
 
254
462
  ##
@@ -265,15 +473,28 @@ module Kameleoon
265
473
  # @raise [Kameleoon::Exception::FeatureVariationNotFound]
266
474
  # @raise [Kameleoon::Exception::FeatureEnvironmentDisabled]
267
475
  #
476
+ # DEPRECATED. Please use `get_variation(visitor_code, feature_key, track: false)` instead.
268
477
  def get_feature_variation_variables(feature_key, variation_key)
269
- feature_flag = @data_file.get_feature_flag(feature_key)
270
- variation = feature_flag.get_variation_key(variation_key)
478
+ Logging::KameleoonLogger.info(
479
+ '[DEPRECATION] `get_feature_variation_variables` is deprecated. ' \
480
+ 'Please use `get_variation(visitor_code, feature_key, track: false)` instead.'
481
+ )
482
+ Logging::KameleoonLogger.info(
483
+ "CALL: KameleoonClient.get_feature_variation_variables(feature_key: '%s', variation_key: '%s')",
484
+ feature_key, variation_key
485
+ )
486
+ feature_flag = @data_manager.data_file.get_feature_flag(feature_key)
487
+ variation = feature_flag.get_variation_by_key(variation_key)
271
488
  if variation.nil?
272
489
  raise Exception::FeatureVariationNotFound.new(variation_key),
273
490
  "Variation key #{variation_key} not found"
274
491
  end
275
492
  variables = {}
276
493
  variation.variables.each { |var| variables[var.key] = _parse_feature_variable(var) }
494
+ Logging::KameleoonLogger.info(
495
+ "RETURN: KameleoonClient.get_feature_variation_variables(feature_key: '%s', variation_key: '%s') " \
496
+ '-> (variables: %s)', feature_key, variation_key, variables
497
+ )
277
498
  variables
278
499
  end
279
500
 
@@ -290,7 +511,14 @@ module Kameleoon
290
511
  #
291
512
  # @return [Hash] Hash object of the json object.
292
513
  def get_remote_data(key, timeout = @default_timeout)
293
- @remote_data_manager.get_data(key, timeout)
514
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.get_remote_data(key: '%s', timeout: %s)",
515
+ key, timeout)
516
+ remote_data = @remote_data_manager.get_data(key, timeout)
517
+ Logging::KameleoonLogger.info(
518
+ "RETURN: KameleoonClient.get_remote_data(key: '%s', timeout: %s) -> (remote_data: %s)",
519
+ key, timeout, remote_data
520
+ )
521
+ remote_data
294
522
  end
295
523
 
296
524
  ##
@@ -304,12 +532,24 @@ module Kameleoon
304
532
  # for a visitor. If not specified, the default value is `True`. This field is optional.
305
533
  # @param [Integer] timeout Timeout for request (in milliseconds). Equals default_timeout in a config file.
306
534
  # 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.
535
+ # @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
536
+ # identifier. This field is optional.
309
537
  #
310
538
  # @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)
539
+ #
540
+ def get_remote_visitor_data(visitor_code, timeout = nil, add_data: true, filter: nil, is_unique_identifier: nil)
541
+ Logging::KameleoonLogger.info(
542
+ "CALL: KameleoonClient.get_remote_visitor_data(visitor_code: '%s', timeout: %s, add_data: %s, " \
543
+ 'filter: %s, is_unique_identifier: %s)', visitor_code, timeout, add_data, filter, is_unique_identifier
544
+ )
545
+ set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
546
+ visitor_data = @remote_data_manager.get_visitor_data(visitor_code, add_data, filter, timeout)
547
+ Logging::KameleoonLogger.info(
548
+ "RETURN: KameleoonClient.get_remote_visitor_data(visitor_code: '%s', timeout: %s, add_data: %s, " \
549
+ 'filter: %s, is_unique_identifier: %s) -> (visitor_data: %s)',
550
+ visitor_code, timeout, add_data, filter, is_unique_identifier, visitor_data
551
+ )
552
+ visitor_data
313
553
  end
314
554
 
315
555
  ##
@@ -336,7 +576,18 @@ module Kameleoon
336
576
  #
337
577
  # @return [Kameleoon::CustomData] A `CustomData` instance confirming that the data has been added to the visitor.
338
578
  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)
579
+ Logging::KameleoonLogger.info(
580
+ "CALL: KameleoonClient.get_visitor_warehouse_audience(visitor_code: '%s', custom_data_index: %s, " \
581
+ "timeout: %s, warehouse_key: '%s')", visitor_code, custom_data_index, timeout, warehouse_key
582
+ )
583
+ warehouse_audience = @warehouse_manager.get_visitor_warehouse_audience(visitor_code,
584
+ custom_data_index, warehouse_key, timeout)
585
+ Logging::KameleoonLogger.info(
586
+ "RETURN: KameleoonClient.get_visitor_warehouse_audience(visitor_code: '%s', custom_data_index: %s, " \
587
+ "timeout: %s, warehouse_key: '%s') -> (warehouse_audience: %s)",
588
+ visitor_code, custom_data_index, timeout, warehouse_key, warehouse_audience
589
+ )
590
+ warehouse_audience
340
591
  end
341
592
 
342
593
  ##
@@ -344,7 +595,10 @@ module Kameleoon
344
595
  #
345
596
  # @return [Array] array of all feature flag keys
346
597
  def get_feature_list # rubocop:disable Naming/AccessorMethodName
347
- @data_file.feature_flags.keys
598
+ Logging::KameleoonLogger.info('CALL: KameleoonClient.get_feature_list')
599
+ features = @data_manager.data_file.feature_flags.keys
600
+ Logging::KameleoonLogger.info('RETURN: KameleoonClient.get_feature_list -> (features: %s)', features)
601
+ features
348
602
  end
349
603
 
350
604
  ##
@@ -356,16 +610,23 @@ module Kameleoon
356
610
  #
357
611
  # DEPRECATED. Please use `get_active_features` instead.
358
612
  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.'
613
+ Logging::KameleoonLogger.info('[DEPRECATION] `get_active_feature_list_for_visitor` is deprecated.' \
614
+ ' Please use `get_active_features` instead.')
615
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.get_active_feature_list_for_visitor(visitor_code: '%s')",
616
+ visitor_code)
360
617
  Utils::VisitorCode.validate(visitor_code)
361
618
  list_keys = []
362
- @data_file.feature_flags.each do |feature_key, feature_flag|
619
+ @data_manager.data_file.feature_flags.each do |feature_key, feature_flag|
363
620
  next unless feature_flag.environment_enabled
364
621
 
365
622
  variation, rule, = _calculate_variation_key_for_feature(visitor_code, feature_flag)
366
623
  variation_key = _get_variation_key(variation, rule, feature_flag)
367
624
  list_keys.push(feature_key) if variation_key != Kameleoon::Configuration::VariationType::VARIATION_OFF
368
625
  end
626
+ Logging::KameleoonLogger.info(
627
+ "RETURN: KameleoonClient.get_active_feature_list_for_visitor(visitor_code: '%s') -> (features: %s)",
628
+ visitor_code, list_keys
629
+ )
369
630
  list_keys
370
631
  end
371
632
 
@@ -378,11 +639,18 @@ module Kameleoon
378
639
  # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars or is nil
379
640
  #
380
641
  # @return [Hash] Hash of active features for a visitor
642
+ #
643
+ # DEPRECATED. Please use `get_variations(visitor_code, only_active: true, track: false)` instead.
381
644
  def get_active_features(visitor_code)
645
+ Logging::KameleoonLogger.info(
646
+ '[DEPRECATION] `get_active_features` is deprecated. ' \
647
+ 'Please use `get_variations(visitor_code, only_active: true, track: false)` instead.'
648
+ )
649
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.get_active_features(visitor_code: '%s')", visitor_code)
382
650
  Utils::VisitorCode.validate(visitor_code)
383
651
  map_active_features = {}
384
652
 
385
- @data_file.feature_flags.each_value do |feature_flag|
653
+ @data_manager.data_file.feature_flags.each_value do |feature_flag|
386
654
  next unless feature_flag.environment_enabled
387
655
 
388
656
  var_by_exp, rule = _calculate_variation_key_for_feature(visitor_code, feature_flag)
@@ -390,27 +658,15 @@ module Kameleoon
390
658
 
391
659
  next if variation_key == Configuration::VariationType::VARIATION_OFF
392
660
 
393
- variation = feature_flag.get_variation_key(variation_key)
394
- variables = {}
395
-
396
- variation&.variables&.each do |variable|
397
- variables[variable.key] = Kameleoon::Types::Variable.new(
398
- variable.key,
399
- variable.type,
400
- _parse_feature_variable(variable)
401
- )
402
- end
403
-
404
- variables.freeze
405
- map_active_features[feature_flag.feature_key] = Kameleoon::Types::Variation.new(
406
- variation_key,
407
- var_by_exp ? var_by_exp.variation_id : nil,
408
- rule ? rule.experiment_id : nil,
409
- variables
410
- )
661
+ variation = feature_flag.get_variation_by_key(variation_key)
662
+ map_active_features[feature_flag.feature_key] =
663
+ make_external_variation(variation, var_by_exp&.variation_id, rule&.experiment_id)
411
664
  end
412
665
 
413
666
  map_active_features.freeze
667
+ Logging::KameleoonLogger.info("RETURN: KameleoonClient.get_active_features(visitor_code: '%s') -> (features: %s)",
668
+ visitor_code, map_active_features)
669
+ map_active_features
414
670
  end
415
671
 
416
672
  ##
@@ -421,6 +677,7 @@ module Kameleoon
421
677
  # @param handler [Callable | NilClass] The handler that will be called when the configuration
422
678
  # is updated using a real-time configuration event.
423
679
  def on_update_configuration(handler)
680
+ Logging::KameleoonLogger.info('CALL/RETURN: KameleoonClient.on_update_configuration(handler)')
424
681
  @update_configuration_handler = handler
425
682
  end
426
683
 
@@ -433,8 +690,14 @@ module Kameleoon
433
690
  # @return [String] JavasScript code to be inserted in your page to send automatically
434
691
  # the exposure events to the analytics solution you are using.
435
692
  def get_engine_tracking_code(visitor_code)
693
+ Logging::KameleoonLogger.info("CALL: KameleoonClient.get_engine_tracking_code(visitor_code: '%s')", visitor_code)
436
694
  visitor_variations = @visitor_manager.get_visitor(visitor_code)&.variations
437
- @hybrid_manager.get_engine_tracking_code(visitor_variations)
695
+ engine_tracking_code = @hybrid_manager.get_engine_tracking_code(visitor_variations)
696
+ Logging::KameleoonLogger.info(
697
+ "RETURN: KameleoonClient.get_engine_tracking_code(visitor_code: '%s') -> (engine_tracking_code: '%s')",
698
+ visitor_code, engine_tracking_code
699
+ )
700
+ engine_tracking_code
438
701
  end
439
702
 
440
703
  private
@@ -442,17 +705,17 @@ module Kameleoon
442
705
  HYBRID_EXPIRATION_TIME = 5
443
706
 
444
707
  def fetch_configuration_initially
445
- log('Initial configuration fetch is started.')
708
+ Logging::KameleoonLogger.info('Initial configuration fetch is started.')
446
709
  Thread.new do
447
710
  ok = false
448
711
  begin
449
712
  ok = obtain_configuration
450
- log('Initial configuration fetch failed') unless ok
713
+ Logging::KameleoonLogger.error('Initial configuration fetch failed') unless ok
451
714
  rescue StandardError => e
452
- log("Initial configuration fetch failed: #{e}")
715
+ Logging::KameleoonLogger.error('Initial configuration fetch failed: %s', e)
453
716
  end
454
717
  @readiness.set(ok)
455
- manage_configuration_update(@data_file.settings.real_time_update) if ok
718
+ manage_configuration_update(@data_manager.data_file.settings.real_time_update) if ok
456
719
  end
457
720
  end
458
721
 
@@ -462,21 +725,23 @@ module Kameleoon
462
725
  begin
463
726
  ok = obtain_configuration(time_stamp)
464
727
  rescue StandardError => e
465
- log("Error occurred during configuration fetching: #{e}")
728
+ Logging::KameleoonLogger.error('Error occurred during configuration fetching: %s', e)
466
729
  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')
730
+ real_time_update = @data_manager.data_file.settings.real_time_update
731
+ if !ok && real_time_update
732
+ @data_manager.data_file.settings.real_time_update = false
733
+ real_time_update = false
734
+ Logging::KameleoonLogger.warning('Switching to polling mode due to failed fetch')
470
735
  end
471
- manage_configuration_update(@data_file.settings.real_time_update)
736
+ manage_configuration_update(real_time_update)
472
737
  end
473
738
  end
474
739
 
475
740
  def start_configuration_update_job_if_needed
476
741
  return unless @fetch_configuration_update_job.nil?
477
742
 
478
- @fetch_configuration_update_job = Rufus::Scheduler.singleton.schedule_every @config.refresh_interval_second do
479
- log('Scheduled job to fetch configuration is started.')
743
+ @fetch_configuration_update_job = @scheduler.schedule_every @config.refresh_interval_second do
744
+ Logging::KameleoonLogger.info('Scheduled job to fetch configuration is started.')
480
745
  fetch_configuration_job
481
746
  end
482
747
  end
@@ -484,9 +749,9 @@ module Kameleoon
484
749
  def stop_configuration_update_job_if_needed
485
750
  return if @fetch_configuration_update_job.nil?
486
751
 
487
- @fetch_configuration_update_job.unschedule
752
+ @fetch_configuration_update_job&.unschedule
488
753
  @fetch_configuration_update_job = nil
489
- log('Scheduled job to fetch configuration is stopped.')
754
+ Logging::KameleoonLogger.info('Scheduled job to fetch configuration is stopped.')
490
755
  end
491
756
 
492
757
  def start_real_time_configuration_service_if_needed
@@ -495,13 +760,11 @@ module Kameleoon
495
760
  url = @network_manager.url_provider.make_real_time_url
496
761
  fetch_func = proc { |real_time_event| fetch_configuration_job(real_time_event.time_stamp) }
497
762
  @real_time_configuration_service =
498
- Kameleoon::RealTime::RealTimeConfigurationService.new(url, fetch_func, method(:log))
763
+ Kameleoon::RealTime::RealTimeConfigurationService.new(url, fetch_func)
499
764
  end
500
765
 
501
766
  def stop_real_time_configuration_service_if_needed
502
- return if @real_time_configuration_service.nil?
503
-
504
- @real_time_configuration_service.close
767
+ @real_time_configuration_service&.close
505
768
  @real_time_configuration_service = nil
506
769
  end
507
770
 
@@ -530,24 +793,23 @@ module Kameleoon
530
793
  # end
531
794
 
532
795
  def obtain_configuration(time_stamp = nil)
533
- log 'Fetching configuration from Client-Config service'
796
+ Logging::KameleoonLogger.info('Fetching configuration from Client-Config service')
534
797
  response = @network_manager.fetch_configuration(time_stamp)
535
798
  return false unless response
536
799
 
537
800
  configuration = JSON.parse(response)
538
- @data_file = Configuration::DataFile.new(@config.environment, method(:log)).init(configuration)
539
- apply_new_configuration(@data_file)
801
+ data_file = Configuration::DataFile.new(@config.environment, configuration)
802
+ apply_new_configuration(data_file)
540
803
  call_update_handler_if_needed(!time_stamp.nil?)
541
- log "Feature flags are fetched: #{response.inspect}"
804
+ Logging::KameleoonLogger.info('Feature flags are fetched: %s', response.inspect)
542
805
  true
543
806
  end
544
807
 
545
808
  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
809
+ Logging::KameleoonLogger.debug('CALL: KameleoonClient.apply_new_configuration(data_file: %s)', data_file)
810
+ @data_manager.data_file = data_file
548
811
  @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
812
+ Logging::KameleoonLogger.debug('RETURN: KameleoonClient.apply_new_configuration(data_file: %s)', data_file)
551
813
  end
552
814
 
553
815
  ##
@@ -561,13 +823,13 @@ module Kameleoon
561
823
  end
562
824
 
563
825
  def dispose
826
+ Logging::KameleoonLogger.debug('CALL: KameleoonClient.dispose')
564
827
  stop_configuration_update_job_if_needed
565
828
  stop_real_time_configuration_service_if_needed
566
829
  @visitor_manager.stop
567
- end
568
-
569
- def log(text)
570
- print "Kameleoon SDK Log: #{text}\n" if @verbose_mode
830
+ @tracking_manager.stop
831
+ @scheduler.shutdown
832
+ Logging::KameleoonLogger.debug('RETURN: KameleoonClient.dispose')
571
833
  end
572
834
 
573
835
  # Uncomment when using storage
@@ -585,29 +847,68 @@ module Kameleoon
585
847
  @targeting_manager.check_targeting(visitor_code, campaign_id, exp_ff_rule)
586
848
  end
587
849
 
850
+ def get_variation_info(visitor_code, feature_flag, track)
851
+ Logging::KameleoonLogger.debug(
852
+ "CALL: KameleoonClient.get_variation_info(visitor_code: '%s', feature_flag: %s, track: %s)",
853
+ visitor_code, feature_flag, track
854
+ )
855
+ var_by_exp, rule = _calculate_variation_key_for_feature(visitor_code, feature_flag)
856
+ variation_key = _get_variation_key(var_by_exp, rule, feature_flag)
857
+ save_variation(visitor_code, rule, var_by_exp, track: track)
858
+ Logging::KameleoonLogger.debug(
859
+ "RETURN: KameleoonClient.get_variation_info(visitor_code: '%s', feature_flag: %s, track: %s)" \
860
+ ' -> (variation_key: %s, variation_by_exposition: %s, rule: %s)',
861
+ visitor_code, feature_flag, track, variation_key, var_by_exp, rule
862
+ )
863
+ [variation_key, var_by_exp, rule]
864
+ end
865
+
588
866
  ##
589
867
  # 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)
868
+ def _get_feature_variation_key(visitor_code, feature_key)
869
+ Logging::KameleoonLogger.debug(
870
+ "CALL: KameleoonClient._get_feature_variation_key(visitor_code: '%s', feature_key: '%s')",
871
+ visitor_code, feature_key
872
+ )
873
+ feature_flag = @data_manager.data_file.get_feature_flag(feature_key)
592
874
  variation, rule = _calculate_variation_key_for_feature(visitor_code, feature_flag)
593
875
  variation_key = _get_variation_key(variation, rule, feature_flag)
594
- visitor = nil
595
- unless rule.nil?
596
- experiment_id = rule.experiment_id
597
- variation_id = variation.variation_id unless variation.nil?
598
- visitor = @visitor_manager.get_or_create_visitor(visitor_code)
599
- unless experiment_id.nil? || variation_id.nil?
600
- as_variation = Kameleoon::DataManager::AssignedVariation.new(experiment_id, variation_id, rule.type)
601
- visitor.assign_variation(as_variation)
602
- end
603
- end
604
- flush(visitor_code, is_unique_identifier: is_unique_identifier)
876
+ save_variation(visitor_code, rule, variation)
877
+ @tracking_manager.add_visitor_code(visitor_code)
878
+ Logging::KameleoonLogger.debug(
879
+ "RETURN: KameleoonClient._get_feature_variation_key(visitor_code: '%s', feature_key: '%s')" \
880
+ " -> (feature_flag: %s, variation_key: '%s')",
881
+ visitor_code, feature_key, feature_flag, variation_key
882
+ )
605
883
  [feature_flag, variation_key]
606
884
  end
607
885
 
886
+ def save_variation(visitor_code, rule, var_by_exp, track: true)
887
+ experiment_id = rule&.experiment_id
888
+ variation_id = var_by_exp&.variation_id
889
+ return if experiment_id.nil? || variation_id.nil?
890
+
891
+ Logging::KameleoonLogger.debug(
892
+ "CALL: KameleoonClient.save_variation(visitor_code: '%s', rule: %s, var_by_exp: %s, track: %s)",
893
+ visitor_code, rule, var_by_exp, track
894
+ )
895
+ visitor = @visitor_manager.get_or_create_visitor(visitor_code)
896
+ as_variation = Kameleoon::DataManager::AssignedVariation.new(experiment_id, variation_id, rule.type)
897
+ as_variation.mark_as_sent unless track
898
+ visitor.assign_variation(as_variation)
899
+ Logging::KameleoonLogger.debug(
900
+ "RETURN: KameleoonClient.save_variation(visitor_code: '%s', rule: %s, var_by_exp: %s, track: %s)",
901
+ visitor_code, rule, var_by_exp, track
902
+ )
903
+ end
904
+
608
905
  ##
609
906
  # helper method for calculate variation key for feature flag
610
907
  def _calculate_variation_key_for_feature(visitor_code, feature_flag)
908
+ Logging::KameleoonLogger.debug(
909
+ "CALL: KameleoonClient._calculate_variation_key_for_feature(visitor_code: '%s', feature_flag: %s)",
910
+ visitor_code, feature_flag
911
+ )
611
912
  # no rules -> return default_variation_key
612
913
  feature_flag.rules.each do |rule|
613
914
  # check if visitor is targeted for rule, else next rule
@@ -618,20 +919,41 @@ module Kameleoon
618
919
  code_for_hash = vis&.mapping_identifier || visitor_code
619
920
  # uses for rule exposition
620
921
  hash_rule = Utils::HashDouble.obtain_rule(code_for_hash, rule.id, rule.respool_time)
922
+ Logging::KameleoonLogger.debug("Calculated hash_rule: %s for visitor_code: '%s'", hash_rule, code_for_hash)
621
923
  # check main expostion for rule with hashRule
622
924
  if hash_rule <= rule.exposition
623
- return [rule.first_variation, rule] if rule.targeted_delivery_type?
925
+ if rule.targeted_delivery_type?
926
+ Logging::KameleoonLogger.debug(
927
+ "RETURN: KameleoonClient._calculate_variation_key_for_feature(visitor_code: '%s', feature_flag: %s) " \
928
+ '-> (variation: %s, rule: %s)',
929
+ visitor_code, feature_flag, rule.first_variation, rule
930
+ )
931
+ return [rule.first_variation, rule]
932
+ end
624
933
 
625
934
  # uses for variation's expositions
626
935
  hash_variation = Utils::HashDouble.obtain_rule(code_for_hash, rule.experiment_id, rule.respool_time)
936
+ Logging::KameleoonLogger.debug(
937
+ "Calculated hash_variation: %s for visitor_code: '%s'", hash_variation, code_for_hash
938
+ )
627
939
  # get variation key with new hashVariation
628
940
  variation = rule.get_variation(hash_variation)
629
- return [variation, rule] unless variation.nil?
941
+ unless variation.nil?
942
+ Logging::KameleoonLogger.debug(
943
+ "RETURN: KameleoonClient._calculate_variation_key_for_feature(visitor_code: '%s', " \
944
+ 'feature_flag: %s) -> (variation: %s, rule: %s)', visitor_code, feature_flag, variation, rule
945
+ )
946
+ return [variation, rule]
947
+ end
630
948
  # if visitor is targeted for targeted rule then break cycle -> return default
631
949
  elsif rule.targeted_delivery_type?
632
950
  break
633
951
  end
634
952
  end
953
+ Logging::KameleoonLogger.debug(
954
+ "RETURN: KameleoonClient._calculate_variation_key_for_feature(visitor_code: '%s', feature_flag: %s) " \
955
+ '-> (variation: nil, rule: nil)', visitor_code, feature_flag
956
+ )
635
957
  [nil, nil]
636
958
  end
637
959
 
@@ -642,71 +964,48 @@ module Kameleoon
642
964
  feature_flag.default_variation_key
643
965
  end
644
966
 
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
967
+ def make_external_variation(internal_variation, variation_id, experiment_id)
968
+ Logging::KameleoonLogger.debug(
969
+ 'CALL: KameleoonClient.make_external_variation(internal_variation: %s, variation_id: %s, experiment_id: %s)',
970
+ internal_variation, variation_id, experiment_id
971
+ )
972
+ variables = {}
973
+ internal_variation&.variables&.each do |variable|
974
+ variables[variable.key] = Types::Variable.new(
975
+ variable.key,
976
+ variable.type,
977
+ _parse_feature_variable(variable)
978
+ )
690
979
  end
691
- unsent
980
+ variables.freeze
981
+ variation = Types::Variation.new(internal_variation&.key, variation_id, experiment_id, variables)
982
+ Logging::KameleoonLogger.debug(
983
+ 'RETURN: KameleoonClient.make_external_variation(internal_variation: %s, variation_id: %s, experiment_id: %s)' \
984
+ ' -> (variation: %s)',
985
+ internal_variation, variation_id, experiment_id, variation
986
+ )
987
+ variation
692
988
  end
693
989
 
694
990
  ##
695
991
  # helper method for fetching values from a Variable
696
992
  def _parse_feature_variable(variable)
697
993
  case variable.type
698
- when 'BOOLEAN', 'STRING', 'NUMBER'
994
+ when 'BOOLEAN', 'STRING', 'NUMBER', 'JS', 'CSS'
699
995
  variable.value
700
996
  when 'JSON'
701
997
  JSON.parse(variable.value)
702
998
  else
703
- raise TypeError.new('Unknown type for feature variable'),
704
- 'Unknown type for feature variable'
999
+ Logging::KameleoonLogger.error("Unknown type '#{variable.type}' for feature variable")
1000
+ variable.value
705
1001
  end
706
1002
  end
707
1003
 
708
- def consent_provided?(visitor)
709
- !@data_file.settings.is_consent_required || visitor&.legal_consent
1004
+ def set_unique_identifier(visitor_code, is_unique_identifier)
1005
+ Logging::KameleoonLogger.info(
1006
+ "The 'isUniqueIdentifier' parameter is deprecated. Please, add 'UniqueIdentifier' to a visitor instead."
1007
+ )
1008
+ @visitor_manager.add_data(visitor_code, UniqueIdentifier.new(is_unique_identifier))
710
1009
  end
711
1010
  end
712
1011
  end