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.
- checksums.yaml +4 -4
- data/lib/kameleoon/configuration/custom_data_info.rb +16 -8
- data/lib/kameleoon/configuration/data_file.rb +52 -16
- data/lib/kameleoon/configuration/feature_flag.rb +11 -1
- data/lib/kameleoon/configuration/rule.rb +4 -0
- data/lib/kameleoon/configuration/settings.rb +13 -8
- data/lib/kameleoon/configuration/variation_exposition.rb +4 -0
- data/lib/kameleoon/data/browser.rb +4 -0
- data/lib/kameleoon/data/conversion.rb +4 -0
- data/lib/kameleoon/data/cookie.rb +4 -0
- data/lib/kameleoon/data/custom_data.rb +11 -3
- data/lib/kameleoon/data/data.rb +30 -4
- data/lib/kameleoon/data/device.rb +4 -0
- data/lib/kameleoon/data/geolocation.rb +5 -0
- data/lib/kameleoon/data/kcs_heat.rb +4 -0
- data/lib/kameleoon/data/manager/assigned_variation.rb +8 -1
- data/lib/kameleoon/data/manager/data_array_storage.rb +7 -0
- data/lib/kameleoon/data/manager/data_map_storage.rb +7 -0
- data/lib/kameleoon/data/manager/page_view_visit.rb +4 -0
- data/lib/kameleoon/data/manager/visitor.rb +197 -73
- data/lib/kameleoon/data/manager/visitor_manager.rb +54 -17
- data/lib/kameleoon/data/mapping_identifier.rb +33 -0
- data/lib/kameleoon/data/operating_system.rb +4 -0
- data/lib/kameleoon/data/page_view.rb +6 -1
- data/lib/kameleoon/data/unique_identifier.rb +11 -0
- data/lib/kameleoon/data/user_agent.rb +4 -0
- data/lib/kameleoon/data/visitor_visits.rb +4 -0
- data/lib/kameleoon/hybrid/manager.rb +19 -7
- data/lib/kameleoon/kameleoon_client.rb +477 -178
- data/lib/kameleoon/kameleoon_client_config.rb +65 -18
- data/lib/kameleoon/kameleoon_client_factory.rb +15 -2
- data/lib/kameleoon/logging/default_logger.rb +20 -0
- data/lib/kameleoon/logging/kameleoon_logger.rb +77 -0
- data/lib/kameleoon/logging/logger.rb +12 -0
- data/lib/kameleoon/managers/data/data_manager.rb +36 -0
- data/lib/kameleoon/managers/remote_data/remote_data_manager.rb +32 -15
- data/lib/kameleoon/managers/tracking/tracking_builder.rb +149 -0
- data/lib/kameleoon/managers/tracking/tracking_manager.rb +98 -0
- data/lib/kameleoon/managers/tracking/visitor_tracking_registry.rb +94 -0
- data/lib/kameleoon/managers/warehouse/warehouse_manager.rb +22 -5
- data/lib/kameleoon/network/access_token_source.rb +46 -14
- data/lib/kameleoon/network/cookie/cookie_manager.rb +46 -7
- data/lib/kameleoon/network/net_provider.rb +2 -3
- data/lib/kameleoon/network/network_manager.rb +17 -21
- data/lib/kameleoon/network/request.rb +14 -3
- data/lib/kameleoon/network/response.rb +4 -0
- data/lib/kameleoon/network/url_provider.rb +3 -3
- data/lib/kameleoon/real_time/real_time_configuration_service.rb +10 -11
- data/lib/kameleoon/sdk_version.rb +31 -0
- data/lib/kameleoon/targeting/condition.rb +4 -2
- data/lib/kameleoon/targeting/conditions/browser_condition.rb +3 -3
- data/lib/kameleoon/targeting/conditions/cookie_condition.rb +10 -10
- data/lib/kameleoon/targeting/conditions/geolocation_condition.rb +0 -1
- data/lib/kameleoon/targeting/conditions/number_condition.rb +4 -4
- data/lib/kameleoon/targeting/conditions/operating_system_condition.rb +1 -2
- data/lib/kameleoon/targeting/conditions/sdk_language_condition.rb +2 -1
- data/lib/kameleoon/targeting/conditions/segment_condition.rb +3 -3
- data/lib/kameleoon/targeting/conditions/string_value_condition.rb +2 -1
- data/lib/kameleoon/targeting/models.rb +0 -14
- data/lib/kameleoon/targeting/targeting_manager.rb +35 -7
- data/lib/kameleoon/targeting/tree_builder.rb +10 -5
- data/lib/kameleoon/types/remote_visitor_data_filter.rb +13 -0
- data/lib/kameleoon/types/variable.rb +4 -0
- data/lib/kameleoon/types/variation.rb +8 -0
- data/lib/kameleoon/utils.rb +49 -0
- data/lib/kameleoon/version.rb +1 -27
- metadata +12 -2
@@ -1,26 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'kameleoon/client_readiness'
|
4
|
-
require 'kameleoon/
|
5
|
-
require 'kameleoon/
|
6
|
-
require 'kameleoon/
|
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/
|
12
|
-
require 'kameleoon/
|
13
|
-
require 'kameleoon/
|
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/
|
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
|
-
|
52
|
-
@
|
53
|
-
@
|
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
|
58
|
-
Network::UrlProvider.new(site_code)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
@
|
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 =
|
67
|
-
|
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
|
-
|
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
|
-
|
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
|
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:
|
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
|
-
|
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]
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
#
|
165
|
-
|
166
|
-
|
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
|
-
|
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
|
-
|
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
|
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:
|
196
|
-
|
197
|
-
|
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
|
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
|
-
|
222
|
-
|
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
|
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
|
-
|
244
|
-
|
245
|
-
|
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
|
-
|
270
|
-
|
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
|
-
|
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
|
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
|
-
|
312
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
394
|
-
|
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
|
-
|
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
|
-
|
713
|
+
Logging::KameleoonLogger.error('Initial configuration fetch failed') unless ok
|
451
714
|
rescue StandardError => e
|
452
|
-
|
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
|
-
|
728
|
+
Logging::KameleoonLogger.error('Error occurred during configuration fetching: %s', e)
|
466
729
|
end
|
467
|
-
|
468
|
-
|
469
|
-
|
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(
|
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 =
|
479
|
-
|
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
|
752
|
+
@fetch_configuration_update_job&.unschedule
|
488
753
|
@fetch_configuration_update_job = nil
|
489
|
-
|
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
|
763
|
+
Kameleoon::RealTime::RealTimeConfigurationService.new(url, fetch_func)
|
499
764
|
end
|
500
765
|
|
501
766
|
def stop_real_time_configuration_service_if_needed
|
502
|
-
|
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
|
-
|
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
|
-
|
539
|
-
apply_new_configuration(
|
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
|
-
|
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
|
-
|
547
|
-
|
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
|
-
|
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
|
-
|
568
|
-
|
569
|
-
|
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
|
591
|
-
|
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
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
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
|
-
|
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
|
-
|
704
|
-
|
999
|
+
Logging::KameleoonLogger.error("Unknown type '#{variable.type}' for feature variable")
|
1000
|
+
variable.value
|
705
1001
|
end
|
706
1002
|
end
|
707
1003
|
|
708
|
-
def
|
709
|
-
|
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
|