kameleoon-client-ruby 3.3.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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