vwo-sdk 1.16.0 → 1.23.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/vwo/constants.rb +2 -1
- data/lib/vwo/core/bucketer.rb +33 -5
- data/lib/vwo/core/variation_decider.rb +421 -132
- data/lib/vwo/enums.rb +11 -6
- data/lib/vwo/logger.rb +4 -2
- data/lib/vwo/schemas/settings_file.rb +4 -0
- data/lib/vwo/services/operand_evaluator.rb +2 -3
- data/lib/vwo/services/segment_evaluator.rb +4 -2
- data/lib/vwo/services/settings_file_manager.rb +3 -1
- data/lib/vwo/utils/campaign.rb +58 -0
- data/lib/vwo/utils/custom_dimensions.rb +3 -1
- data/lib/vwo/utils/impression.rb +4 -2
- data/lib/vwo/utils/utility.rb +46 -0
- data/lib/vwo.rb +89 -82
- metadata +3 -2
@@ -66,6 +66,8 @@ class VWO
|
|
66
66
|
|
67
67
|
return unless campaign
|
68
68
|
|
69
|
+
is_campaign_part_of_group = @settings_file && is_part_of_group(@settings_file, campaign["id"])
|
70
|
+
|
69
71
|
@has_stored_variation = false
|
70
72
|
decision = {
|
71
73
|
:campaign_id => campaign['id'],
|
@@ -93,62 +95,21 @@ class VWO
|
|
93
95
|
:vwo_user_id => generator_for(user_id, @settings_file['accountId'])
|
94
96
|
}
|
95
97
|
|
96
|
-
if campaign
|
97
|
-
|
98
|
-
|
99
|
-
campaign,
|
100
|
-
api_name,
|
101
|
-
campaign_key,
|
102
|
-
variation_targeting_variables
|
103
|
-
)
|
104
|
-
status = if variation
|
105
|
-
StatusEnum::PASSED
|
106
|
-
else
|
107
|
-
StatusEnum::FAILED
|
108
|
-
end
|
109
|
-
|
110
|
-
@logger.log(
|
111
|
-
LogLevelEnum::INFO,
|
112
|
-
format(
|
113
|
-
LogMessageEnum::InfoMessages::SEGMENTATION_STATUS,
|
114
|
-
file: FILE,
|
115
|
-
campaign_key: campaign_key,
|
116
|
-
user_id: user_id,
|
117
|
-
status: status,
|
118
|
-
custom_variables: variation_targeting_variables,
|
119
|
-
variation_name: status == StatusEnum::PASSED ? "and #{variation['name']} is Assigned" : ' ',
|
120
|
-
segmentation_type: SegmentationTypeEnum::WHITELISTING,
|
121
|
-
api_name: api_name
|
122
|
-
)
|
123
|
-
)
|
124
|
-
|
125
|
-
if variation
|
126
|
-
if campaign['type'] == CampaignTypes::VISUAL_AB || campaign['type'] == CampaignTypes::FEATURE_TEST
|
127
|
-
decision[:variation_name] = variation['name']
|
128
|
-
decision[:variation_id] = variation['id']
|
129
|
-
if campaign['type'] == CampaignTypes::FEATURE_TEST
|
130
|
-
decision[:is_feature_enabled] = variation['isFeatureEnabled']
|
131
|
-
elsif campaign['type'] == CampaignTypes::VISUAL_AB
|
132
|
-
decision[:is_user_whitelisted] = !!variation['name']
|
133
|
-
end
|
134
|
-
end
|
135
|
-
@hooks_manager.execute(decision)
|
136
|
-
end
|
98
|
+
if campaign.has_key?("name")
|
99
|
+
decision[:campaign_name] = campaign['name']
|
100
|
+
end
|
137
101
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
LogMessageEnum::InfoMessages::WHITELISTING_SKIPPED,
|
144
|
-
file: FILE,
|
145
|
-
campaign_key: campaign_key,
|
146
|
-
user_id: user_id,
|
147
|
-
api_name: api_name
|
148
|
-
)
|
149
|
-
)
|
102
|
+
if is_campaign_part_of_group
|
103
|
+
group_id = @settings_file["campaignGroups"][campaign["id"].to_s]
|
104
|
+
decision[:group_id] = group_id
|
105
|
+
group_name = @settings_file["groups"][group_id.to_s]["name"]
|
106
|
+
decision[:group_name] = group_name
|
150
107
|
end
|
151
108
|
|
109
|
+
# evaluate whitelisting
|
110
|
+
variation = get_variation_if_whitelisting_passed(user_id, campaign, variation_targeting_variables, api_name, decision, true)
|
111
|
+
return variation if variation && variation['name']
|
112
|
+
|
152
113
|
user_campaign_map = get_user_storage(user_id, campaign_key)
|
153
114
|
variation = get_stored_variation(user_id, campaign_key, user_campaign_map) if valid_hash?(user_campaign_map)
|
154
115
|
|
@@ -194,8 +155,7 @@ class VWO
|
|
194
155
|
)
|
195
156
|
)
|
196
157
|
|
197
|
-
if ([ApiMethods::TRACK, ApiMethods::GET_VARIATION_NAME, ApiMethods::GET_FEATURE_VARIABLE_VALUE].include? api_name) &&
|
198
|
-
@user_storage_service && campaign['type'] != CampaignTypes::FEATURE_ROLLOUT
|
158
|
+
if ([ApiMethods::TRACK, ApiMethods::GET_VARIATION_NAME, ApiMethods::GET_FEATURE_VARIABLE_VALUE].include? api_name) && @user_storage_service
|
199
159
|
@logger.log(
|
200
160
|
LogLevelEnum::DEBUG,
|
201
161
|
format(
|
@@ -223,82 +183,106 @@ class VWO
|
|
223
183
|
end
|
224
184
|
|
225
185
|
# Pre-segmentation
|
186
|
+
is_presegmentation = check_presegmentation(campaign, user_id, custom_variables, api_name)
|
187
|
+
is_presegmentation_and_traffic_passed = is_presegmentation && @bucketer.user_part_of_campaign?(user_id, campaign)
|
188
|
+
unless is_presegmentation_and_traffic_passed
|
189
|
+
return nil
|
190
|
+
end
|
226
191
|
|
227
|
-
|
228
|
-
|
192
|
+
if is_presegmentation_and_traffic_passed && is_campaign_part_of_group
|
193
|
+
group_campaigns = get_group_campaigns(@settings_file, group_id)
|
194
|
+
|
195
|
+
if group_campaigns
|
196
|
+
is_any_campaign_whitelisted_or_stored = check_whitelisting_or_storage_for_grouped_campaigns(user_id, campaign, group_campaigns, group_name, variation_targeting_variables, true)
|
197
|
+
|
198
|
+
if is_any_campaign_whitelisted_or_stored
|
199
|
+
@logger.log(
|
200
|
+
LogLevelEnum::INFO,
|
201
|
+
format(
|
202
|
+
LogMessageEnum::InfoMessages::CALLED_CAMPAIGN_NOT_WINNER,
|
203
|
+
file: FILE,
|
204
|
+
campaign_key: campaign_key,
|
205
|
+
user_id: user_id,
|
206
|
+
group_name: group_name
|
207
|
+
)
|
208
|
+
)
|
209
|
+
return nil
|
210
|
+
end
|
211
|
+
|
212
|
+
eligible_campaigns = get_eligible_campaigns(user_id, group_campaigns, campaign, custom_variables)
|
213
|
+
non_eligible_campaigns_key = get_non_eligible_campaigns_key(eligible_campaigns, group_campaigns)
|
214
|
+
|
215
|
+
@logger.log(
|
216
|
+
LogLevelEnum::DEBUG,
|
217
|
+
format(
|
218
|
+
LogMessageEnum::DebugMessages::GOT_ELIGIBLE_CAMPAIGNS,
|
219
|
+
file: FILE,
|
220
|
+
user_id: user_id,
|
221
|
+
eligible_campaigns_key: get_eligible_campaigns_key(eligible_campaigns).join(","),
|
222
|
+
ineligible_campaigns_log_text: non_eligible_campaigns_key ? ("campaigns:" + non_eligible_campaigns_key.join("'")) : "no campaigns",
|
223
|
+
group_name: group_name
|
224
|
+
)
|
225
|
+
)
|
229
226
|
|
230
|
-
if is_valid_segments
|
231
|
-
unless custom_variables
|
232
227
|
@logger.log(
|
233
228
|
LogLevelEnum::INFO,
|
234
229
|
format(
|
235
|
-
LogMessageEnum::InfoMessages::
|
230
|
+
LogMessageEnum::InfoMessages::GOT_ELIGIBLE_CAMPAIGNS,
|
236
231
|
file: FILE,
|
237
|
-
campaign_key: campaign_key,
|
238
232
|
user_id: user_id,
|
239
|
-
|
233
|
+
no_of_eligible_campaigns: eligible_campaigns.length,
|
234
|
+
no_of_group_campaigns: group_campaigns.length,
|
235
|
+
group_name: group_name
|
240
236
|
)
|
241
237
|
)
|
242
|
-
|
243
|
-
|
244
|
-
unless @segment_evaluator.evaluate(campaign_key, user_id, segments, custom_variables)
|
238
|
+
|
239
|
+
winner_campaign = get_winner_campaign(user_id, eligible_campaigns, group_id)
|
245
240
|
@logger.log(
|
246
241
|
LogLevelEnum::INFO,
|
247
242
|
format(
|
248
|
-
LogMessageEnum::InfoMessages::
|
249
|
-
file:
|
243
|
+
LogMessageEnum::InfoMessages::GOT_WINNER_CAMPAIGN,
|
244
|
+
file: FILE,
|
250
245
|
user_id: user_id,
|
251
|
-
campaign_key:
|
252
|
-
|
246
|
+
campaign_key: winner_campaign["key"],
|
247
|
+
group_name: group_name
|
253
248
|
)
|
254
249
|
)
|
255
|
-
|
250
|
+
|
251
|
+
if winner_campaign && winner_campaign["id"] == campaign["id"]
|
252
|
+
variation = get_variation_allotted(user_id, campaign, true)
|
253
|
+
if variation && variation['name']
|
254
|
+
save_user_storage(user_id, campaign_key, campaign['type'], variation['name'], goal_identifier, true) if variation['name']
|
255
|
+
else
|
256
|
+
return nil
|
257
|
+
end
|
258
|
+
else
|
259
|
+
@logger.log(
|
260
|
+
LogLevelEnum::INFO,
|
261
|
+
format(
|
262
|
+
LogMessageEnum::InfoMessages::CALLED_CAMPAIGN_NOT_WINNER,
|
263
|
+
file: FILE,
|
264
|
+
campaign_key: campaign_key,
|
265
|
+
user_id: user_id,
|
266
|
+
group_name: group_name
|
267
|
+
)
|
268
|
+
)
|
269
|
+
return nil
|
270
|
+
end
|
256
271
|
end
|
257
|
-
@logger.log(
|
258
|
-
LogLevelEnum::INFO,
|
259
|
-
format(
|
260
|
-
LogMessageEnum::InfoMessages::USER_PASSED_SEGMENTATION,
|
261
|
-
file: FileNameEnum::SegmentEvaluator,
|
262
|
-
user_id: user_id,
|
263
|
-
campaign_key: campaign_key,
|
264
|
-
custom_variables: custom_variables
|
265
|
-
)
|
266
|
-
)
|
267
|
-
else
|
268
|
-
@logger.log(
|
269
|
-
LogLevelEnum::INFO,
|
270
|
-
format(
|
271
|
-
LogMessageEnum::InfoMessages::SKIPPING_SEGMENTATION,
|
272
|
-
file: FILE,
|
273
|
-
campaign_key: campaign_key,
|
274
|
-
user_id: user_id,
|
275
|
-
api_name: api_name,
|
276
|
-
variation: ''
|
277
|
-
)
|
278
|
-
)
|
279
272
|
end
|
280
273
|
|
281
|
-
variation
|
274
|
+
if variation.nil?
|
275
|
+
variation = get_variation_allotted(user_id, campaign)
|
282
276
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
LogMessageEnum::InfoMessages::VARIATION_ALLOCATED,
|
290
|
-
file: FILE,
|
291
|
-
campaign_key: campaign_key,
|
292
|
-
user_id: user_id,
|
293
|
-
variation_name: variation['name'],
|
294
|
-
campaign_type: campaign['type']
|
277
|
+
if variation && variation['name']
|
278
|
+
save_user_storage(user_id, campaign_key, campaign['type'], variation['name'], goal_identifier) if variation['name']
|
279
|
+
else
|
280
|
+
@logger.log(
|
281
|
+
LogLevelEnum::INFO,
|
282
|
+
format(LogMessageEnum::InfoMessages::NO_VARIATION_ALLOCATED, file: FILE, campaign_key: campaign_key, user_id: user_id)
|
295
283
|
)
|
296
|
-
|
297
|
-
|
298
|
-
@logger.log(
|
299
|
-
LogLevelEnum::INFO,
|
300
|
-
format(LogMessageEnum::InfoMessages::NO_VARIATION_ALLOCATED, file: FILE, campaign_key: campaign_key, user_id: user_id)
|
301
|
-
)
|
284
|
+
end
|
285
|
+
|
302
286
|
end
|
303
287
|
|
304
288
|
if variation
|
@@ -321,7 +305,7 @@ class VWO
|
|
321
305
|
#
|
322
306
|
# @return[Hash]
|
323
307
|
|
324
|
-
def get_variation_allotted(user_id, campaign)
|
308
|
+
def get_variation_allotted(user_id, campaign, disable_logs = false)
|
325
309
|
unless valid_value?(user_id)
|
326
310
|
@logger.log(
|
327
311
|
LogLevelEnum::ERROR,
|
@@ -341,7 +325,8 @@ class VWO
|
|
341
325
|
user_id: user_id,
|
342
326
|
campaign_key: campaign['key'],
|
343
327
|
method: 'get_variation_allotted'
|
344
|
-
)
|
328
|
+
),
|
329
|
+
disable_logs
|
345
330
|
)
|
346
331
|
variation
|
347
332
|
else
|
@@ -354,7 +339,8 @@ class VWO
|
|
354
339
|
user_id: user_id,
|
355
340
|
campaign_key: nil,
|
356
341
|
method: 'get_variation_allotted'
|
357
|
-
)
|
342
|
+
),
|
343
|
+
disable_logs
|
358
344
|
)
|
359
345
|
nil
|
360
346
|
end
|
@@ -413,13 +399,15 @@ class VWO
|
|
413
399
|
# @param[String] :campaign_key Unique campaign identifier
|
414
400
|
# @param[String] :variation_name Variation identifier
|
415
401
|
# @param[String] :goal_identifier The unique campaign's goal identifier
|
402
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
416
403
|
# @return[Boolean] true if found otherwise false
|
417
404
|
|
418
|
-
def save_user_storage(user_id, campaign_key, variation_name, goal_identifier)
|
405
|
+
def save_user_storage(user_id, campaign_key, campaign_type, variation_name, goal_identifier, disable_logs = false)
|
419
406
|
unless @user_storage_service
|
420
407
|
@logger.log(
|
421
408
|
LogLevelEnum::DEBUG,
|
422
|
-
format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_SAVE, file: FILE)
|
409
|
+
format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_SAVE, file: FILE),
|
410
|
+
disable_logs
|
423
411
|
)
|
424
412
|
return false
|
425
413
|
end
|
@@ -435,13 +423,28 @@ class VWO
|
|
435
423
|
|
436
424
|
@logger.log(
|
437
425
|
LogLevelEnum::INFO,
|
438
|
-
format(LogMessageEnum::InfoMessages::SAVING_DATA_USER_STORAGE_SERVICE, file: FILE, user_id: user_id)
|
426
|
+
format(LogMessageEnum::InfoMessages::SAVING_DATA_USER_STORAGE_SERVICE, file: FILE, user_id: user_id),
|
427
|
+
disable_logs
|
428
|
+
)
|
429
|
+
|
430
|
+
@logger.log(
|
431
|
+
LogLevelEnum::INFO,
|
432
|
+
format(
|
433
|
+
LogMessageEnum::InfoMessages::VARIATION_ALLOCATED,
|
434
|
+
file: FILE,
|
435
|
+
campaign_key: campaign_key,
|
436
|
+
user_id: user_id,
|
437
|
+
variation_name: variation_name,
|
438
|
+
campaign_type: campaign_type
|
439
|
+
),
|
440
|
+
disable_logs
|
439
441
|
)
|
440
442
|
true
|
441
443
|
rescue StandardError
|
442
444
|
@logger.log(
|
443
445
|
LogLevelEnum::ERROR,
|
444
|
-
format(LogMessageEnum::ErrorMessages::SAVE_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id)
|
446
|
+
format(LogMessageEnum::ErrorMessages::SAVE_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id),
|
447
|
+
disable_logs
|
445
448
|
)
|
446
449
|
false
|
447
450
|
end
|
@@ -455,14 +458,15 @@ class VWO
|
|
455
458
|
# @param[String] :api_name The key Passed to identify the calling API
|
456
459
|
# @param[String] :campaign_key Unique campaign key
|
457
460
|
# @param[Hash] :variation_targeting_variables Key/value pair of Whitelisting Custom Attributes
|
461
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
458
462
|
#
|
459
463
|
# @return[Hash]
|
460
464
|
|
461
|
-
def evaluate_whitelisting(user_id, campaign, api_name, campaign_key, variation_targeting_variables = {})
|
465
|
+
def evaluate_whitelisting(user_id, campaign, api_name, campaign_key, variation_targeting_variables = {}, disable_logs = false)
|
462
466
|
if variation_targeting_variables.nil?
|
463
|
-
variation_targeting_variables = {
|
467
|
+
variation_targeting_variables = { _vwo_user_id: user_id }
|
464
468
|
else
|
465
|
-
variation_targeting_variables[
|
469
|
+
variation_targeting_variables[:_vwo_user_id] = user_id
|
466
470
|
end
|
467
471
|
targeted_variations = []
|
468
472
|
|
@@ -470,7 +474,7 @@ class VWO
|
|
470
474
|
segments = get_segments(variation)
|
471
475
|
is_valid_segments = valid_value?(segments)
|
472
476
|
if is_valid_segments
|
473
|
-
if @segment_evaluator.evaluate(campaign_key, user_id, segments, variation_targeting_variables)
|
477
|
+
if @segment_evaluator.evaluate(campaign_key, user_id, segments, variation_targeting_variables, disable_logs)
|
474
478
|
targeted_variations.push(variation)
|
475
479
|
status = StatusEnum::PASSED
|
476
480
|
else
|
@@ -485,10 +489,11 @@ class VWO
|
|
485
489
|
user_id: user_id,
|
486
490
|
status: status,
|
487
491
|
custom_variables: variation_targeting_variables,
|
488
|
-
variation_name: variation['name'],
|
492
|
+
variation_name: status == StatusEnum::PASSED ? (campaign['type'] == CampaignTypes::FEATURE_ROLLOUT ? 'and hence becomes part of the rollout' : "for " + variation['name']) : '',
|
489
493
|
segmentation_type: SegmentationTypeEnum::WHITELISTING,
|
490
494
|
api_name: api_name
|
491
|
-
)
|
495
|
+
),
|
496
|
+
disable_logs
|
492
497
|
)
|
493
498
|
else
|
494
499
|
@logger.log(
|
@@ -500,7 +505,8 @@ class VWO
|
|
500
505
|
user_id: user_id,
|
501
506
|
api_name: api_name,
|
502
507
|
variation: variation['name']
|
503
|
-
)
|
508
|
+
),
|
509
|
+
disable_logs
|
504
510
|
)
|
505
511
|
end
|
506
512
|
end
|
@@ -525,7 +531,8 @@ class VWO
|
|
525
531
|
whitelisted_variation = @bucketer.get_variation(
|
526
532
|
targeted_variations_deep_clone,
|
527
533
|
@bucketer.get_bucket_value_for_user(
|
528
|
-
user_id
|
534
|
+
user_id,
|
535
|
+
campaign
|
529
536
|
)
|
530
537
|
)
|
531
538
|
else
|
@@ -553,18 +560,26 @@ class VWO
|
|
553
560
|
end
|
554
561
|
end
|
555
562
|
|
563
|
+
def scale_campaigns_weight(campaigns)
|
564
|
+
normalize_weight = 100/campaigns.length
|
565
|
+
campaigns.each do |campaign|
|
566
|
+
campaign['weight'] = normalize_weight
|
567
|
+
end
|
568
|
+
end
|
556
569
|
# Get the UserStorageData after looking up into get method
|
557
570
|
# Being provided via UserStorageService
|
558
571
|
#
|
559
572
|
# @param[String]: Unique user identifier
|
560
573
|
# @param[String]: Unique campaign key
|
574
|
+
# @param[Boolean] :disable_logs if True
|
561
575
|
# @return[Hash|Boolean]: user_storage data
|
562
576
|
|
563
|
-
def get_user_storage(user_id, campaign_key)
|
577
|
+
def get_user_storage(user_id, campaign_key, disable_logs = false)
|
564
578
|
unless @user_storage_service
|
565
579
|
@logger.log(
|
566
580
|
LogLevelEnum::DEBUG,
|
567
|
-
format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_LOOKUP, file: FILE)
|
581
|
+
format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_LOOKUP, file: FILE),
|
582
|
+
disable_logs
|
568
583
|
)
|
569
584
|
return false
|
570
585
|
end
|
@@ -577,13 +592,15 @@ class VWO
|
|
577
592
|
file: FILE,
|
578
593
|
user_id: user_id,
|
579
594
|
status: data.nil? ? 'Not Found' : 'Found'
|
580
|
-
)
|
595
|
+
),
|
596
|
+
disable_logs
|
581
597
|
)
|
582
598
|
data
|
583
599
|
rescue StandardError
|
584
600
|
@logger.log(
|
585
601
|
LogLevelEnum::ERROR,
|
586
|
-
format(LogMessageEnum::ErrorMessages::LOOK_UP_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id)
|
602
|
+
format(LogMessageEnum::ErrorMessages::LOOK_UP_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id),
|
603
|
+
disable_logs
|
587
604
|
)
|
588
605
|
false
|
589
606
|
end
|
@@ -593,10 +610,11 @@ class VWO
|
|
593
610
|
# @param[String] :user_id
|
594
611
|
# @param[String] :campaign_key campaign identified
|
595
612
|
# @param[Hash] :user_campaign_map BucketMap consisting of stored user variation
|
613
|
+
# @param[Boolean] :disable_logs if True
|
596
614
|
#
|
597
615
|
# @return[Object, nil] if found then variation settings object otherwise None
|
598
616
|
|
599
|
-
def get_stored_variation(user_id, campaign_key, user_campaign_map)
|
617
|
+
def get_stored_variation(user_id, campaign_key, user_campaign_map, disable_logs = false)
|
600
618
|
return unless user_campaign_map['campaign_key'] == campaign_key
|
601
619
|
|
602
620
|
variation_name = user_campaign_map['variation_name']
|
@@ -608,7 +626,8 @@ class VWO
|
|
608
626
|
campaign_key: campaign_key,
|
609
627
|
user_id: user_id,
|
610
628
|
variation_name: variation_name
|
611
|
-
)
|
629
|
+
),
|
630
|
+
disable_logs
|
612
631
|
)
|
613
632
|
|
614
633
|
get_campaign_variation(
|
@@ -617,6 +636,276 @@ class VWO
|
|
617
636
|
variation_name
|
618
637
|
)
|
619
638
|
end
|
639
|
+
|
640
|
+
# this function check whether pre-segmentation is passed or not
|
641
|
+
#
|
642
|
+
# @param[String] :user_id The unique key assigned to User
|
643
|
+
# @param[Hash] :campaign Campaign hash for Unique campaign key
|
644
|
+
# @param[Hash] :custom_variables Key/value pair for segmentation
|
645
|
+
# @param[String] :api_name The key Passed to identify the calling API
|
646
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
647
|
+
#
|
648
|
+
# @return[Boolean]
|
649
|
+
def check_presegmentation(campaign, user_id, custom_variables, api_name, disable_logs = false)
|
650
|
+
campaign_key = campaign['key']
|
651
|
+
segments = get_segments(campaign)
|
652
|
+
is_valid_segments = valid_value?(segments)
|
653
|
+
|
654
|
+
if is_valid_segments
|
655
|
+
unless custom_variables
|
656
|
+
@logger.log(
|
657
|
+
LogLevelEnum::INFO,
|
658
|
+
format(
|
659
|
+
LogMessageEnum::InfoMessages::NO_CUSTOM_VARIABLES,
|
660
|
+
file: FILE,
|
661
|
+
campaign_key: campaign_key,
|
662
|
+
user_id: user_id,
|
663
|
+
api_name: api_name
|
664
|
+
),
|
665
|
+
disable_logs
|
666
|
+
)
|
667
|
+
custom_variables = {}
|
668
|
+
end
|
669
|
+
unless @segment_evaluator.evaluate(campaign_key, user_id, segments, custom_variables, disable_logs)
|
670
|
+
@logger.log(
|
671
|
+
LogLevelEnum::INFO,
|
672
|
+
format(
|
673
|
+
LogMessageEnum::InfoMessages::USER_FAILED_SEGMENTATION,
|
674
|
+
file: FileNameEnum::SegmentEvaluator,
|
675
|
+
user_id: user_id,
|
676
|
+
campaign_key: campaign_key,
|
677
|
+
custom_variables: custom_variables
|
678
|
+
),
|
679
|
+
disable_logs
|
680
|
+
)
|
681
|
+
return false
|
682
|
+
end
|
683
|
+
@logger.log(
|
684
|
+
LogLevelEnum::INFO,
|
685
|
+
format(
|
686
|
+
LogMessageEnum::InfoMessages::USER_PASSED_SEGMENTATION,
|
687
|
+
file: FileNameEnum::SegmentEvaluator,
|
688
|
+
user_id: user_id,
|
689
|
+
campaign_key: campaign_key,
|
690
|
+
custom_variables: custom_variables
|
691
|
+
),
|
692
|
+
disable_logs
|
693
|
+
)
|
694
|
+
else
|
695
|
+
@logger.log(
|
696
|
+
LogLevelEnum::INFO,
|
697
|
+
format(
|
698
|
+
LogMessageEnum::InfoMessages::SKIPPING_SEGMENTATION,
|
699
|
+
file: FILE,
|
700
|
+
campaign_key: campaign_key,
|
701
|
+
user_id: user_id,
|
702
|
+
api_name: api_name,
|
703
|
+
variation: ''
|
704
|
+
),
|
705
|
+
disable_logs
|
706
|
+
)
|
707
|
+
end
|
708
|
+
true
|
709
|
+
end
|
710
|
+
|
711
|
+
# Finds and returns eligible campaigns from group_campaigns.
|
712
|
+
#
|
713
|
+
# @param[String] :user_id The unique key assigned to User
|
714
|
+
# @param[Hash] :called_campaign campaign for which api is called
|
715
|
+
# @param[Array] :group_campaigns campaigns part of group
|
716
|
+
# @param[String] :custom_variables Key/value pair for segmentation
|
717
|
+
#
|
718
|
+
# @return[Array]
|
719
|
+
def get_eligible_campaigns(user_id, group_campaigns, called_campaign, custom_variables)
|
720
|
+
eligible_campaigns = []
|
721
|
+
|
722
|
+
group_campaigns.each do |campaign|
|
723
|
+
if called_campaign["id"] == campaign["id"] || check_presegmentation(campaign, user_id, custom_variables, '', true) && @bucketer.user_part_of_campaign?(user_id, campaign)
|
724
|
+
eligible_campaigns.push(campaign)
|
725
|
+
end
|
726
|
+
end
|
727
|
+
return eligible_campaigns
|
728
|
+
end
|
729
|
+
|
730
|
+
# Finds and returns the winner campaign from eligible_campaigns list.
|
731
|
+
#
|
732
|
+
# @param[String] :user_id The unique key assigned to User
|
733
|
+
# @param[Array] :eligible_campaigns campaigns part of group which were eligible to be winner
|
734
|
+
#
|
735
|
+
# @return[Hash]
|
736
|
+
def get_winner_campaign(user_id, eligible_campaigns, group_id)
|
737
|
+
if eligible_campaigns.length == 1
|
738
|
+
return eligible_campaigns[0]
|
739
|
+
end
|
740
|
+
|
741
|
+
eligible_campaigns = scale_campaigns_weight(eligible_campaigns)
|
742
|
+
eligible_campaigns = set_campaign_allocation(eligible_campaigns)
|
743
|
+
bucket_value = @bucketer.get_bucket_value_for_user(user_id, {}, group_id, true)
|
744
|
+
return @bucketer.get_campaign_using_range(bucket_value, eligible_campaigns)
|
745
|
+
end
|
746
|
+
|
747
|
+
# Get campaign keys of all eligible Campaigns.
|
748
|
+
#
|
749
|
+
# @param[Array] :eligible_campaigns campaigns part of group which were eligible to be winner
|
750
|
+
#
|
751
|
+
# @return[Array]
|
752
|
+
def get_eligible_campaigns_key(eligible_campaigns)
|
753
|
+
eligible_campaigns_key = []
|
754
|
+
eligible_campaigns.each do |campaign|
|
755
|
+
eligible_campaigns_key.push(campaign["key"])
|
756
|
+
end
|
757
|
+
eligible_campaigns_key
|
758
|
+
end
|
759
|
+
|
760
|
+
# Get campaign keys of all non eligible Campaigns.
|
761
|
+
#
|
762
|
+
# @param[Array] :eligible_campaigns campaigns part of group which were eligible to be winner
|
763
|
+
# @param[Array] :group_campaigns campaigns part of group
|
764
|
+
#
|
765
|
+
# @return[Array]
|
766
|
+
def get_non_eligible_campaigns_key(eligible_campaigns, group_campaigns)
|
767
|
+
non_eligible_campaigns_key = []
|
768
|
+
group_campaigns.each do |campaign|
|
769
|
+
unless eligible_campaigns.include? campaign
|
770
|
+
non_eligible_campaigns_key.push(campaign["key"])
|
771
|
+
end
|
772
|
+
end
|
773
|
+
non_eligible_campaigns_key
|
774
|
+
end
|
775
|
+
|
776
|
+
# Checks if any other campaign in groupCampaigns satisfies whitelisting or is in user storage.
|
777
|
+
#
|
778
|
+
# @param[String] :user_id the unique ID assigned to User
|
779
|
+
# @param[Hash] :called_campaign campaign for which api is called
|
780
|
+
# @param[Array] :group_campaigns campaigns part of group
|
781
|
+
# @param[String] :group_name group name
|
782
|
+
# @param[Hash] :variation_targeting_variables Key/value pair of Whitelisting Custom Attributes
|
783
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
784
|
+
# @return[Boolean]
|
785
|
+
|
786
|
+
def check_whitelisting_or_storage_for_grouped_campaigns(user_id, called_campaign, group_campaigns, group_name, variation_targeting_variables, disable_logs = false)
|
787
|
+
group_campaigns.each do |campaign|
|
788
|
+
if called_campaign["id"] != campaign["id"]
|
789
|
+
targeted_variation = evaluate_whitelisting(
|
790
|
+
user_id,
|
791
|
+
campaign,
|
792
|
+
'',
|
793
|
+
campaign["key"],
|
794
|
+
variation_targeting_variables,
|
795
|
+
true
|
796
|
+
)
|
797
|
+
if targeted_variation
|
798
|
+
@logger.log(
|
799
|
+
LogLevelEnum::INFO,
|
800
|
+
format(
|
801
|
+
LogMessageEnum::InfoMessages::OTHER_CAMPAIGN_SATISFIES_WHITELISTING_OR_STORAGE,
|
802
|
+
file: FILE,
|
803
|
+
campaign_key: campaign["key"],
|
804
|
+
user_id: user_id,
|
805
|
+
group_name: group_name,
|
806
|
+
type: "whitelisting"
|
807
|
+
),
|
808
|
+
disable_logs
|
809
|
+
)
|
810
|
+
return true
|
811
|
+
end
|
812
|
+
end
|
813
|
+
end
|
814
|
+
|
815
|
+
group_campaigns.each do |campaign|
|
816
|
+
if called_campaign["id"] != campaign["id"]
|
817
|
+
user_storage_data = get_user_storage(user_id, campaign["key"], true)
|
818
|
+
if user_storage_data
|
819
|
+
@logger.log(
|
820
|
+
LogLevelEnum::INFO,
|
821
|
+
format(
|
822
|
+
LogMessageEnum::InfoMessages::OTHER_CAMPAIGN_SATISFIES_WHITELISTING_OR_STORAGE,
|
823
|
+
file: FILE,
|
824
|
+
campaign_key: campaign["key"],
|
825
|
+
user_id: user_id,
|
826
|
+
group_name: group_name,
|
827
|
+
type: "user storage"
|
828
|
+
),
|
829
|
+
disable_logs
|
830
|
+
)
|
831
|
+
return true
|
832
|
+
end
|
833
|
+
end
|
834
|
+
end
|
835
|
+
false
|
836
|
+
end
|
837
|
+
|
838
|
+
# Get variation if whitelisting passes
|
839
|
+
#
|
840
|
+
# @param[String] :user_id the unique ID assigned to User
|
841
|
+
# @param[Hash] :campaign campaign for which checking whitelisting
|
842
|
+
# @param[Hash] :variation_targeting_variables Key/value pair of Whitelisting Custom Attributes
|
843
|
+
# @param[String] :api_name The key Passed to identify the calling API
|
844
|
+
# @param[Hash] :decision data containing campaign info passed to hooks manager
|
845
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
846
|
+
# @return[Hash]
|
847
|
+
def get_variation_if_whitelisting_passed(user_id, campaign, variation_targeting_variables, api_name, decision, disable_logs = false)
|
848
|
+
campaign_key = campaign['key']
|
849
|
+
if campaign['isForcedVariationEnabled']
|
850
|
+
variation = evaluate_whitelisting(
|
851
|
+
user_id,
|
852
|
+
campaign,
|
853
|
+
api_name,
|
854
|
+
campaign_key,
|
855
|
+
variation_targeting_variables,
|
856
|
+
disable_logs
|
857
|
+
)
|
858
|
+
status = if variation
|
859
|
+
StatusEnum::PASSED
|
860
|
+
else
|
861
|
+
StatusEnum::FAILED
|
862
|
+
end
|
863
|
+
|
864
|
+
@logger.log(
|
865
|
+
LogLevelEnum::INFO,
|
866
|
+
format(
|
867
|
+
LogMessageEnum::InfoMessages::SEGMENTATION_STATUS,
|
868
|
+
file: FILE,
|
869
|
+
campaign_key: campaign_key,
|
870
|
+
user_id: user_id,
|
871
|
+
status: status,
|
872
|
+
custom_variables: variation_targeting_variables ? variation_targeting_variables : {},
|
873
|
+
variation_name: (status == StatusEnum::PASSED && campaign['type'] != CampaignTypes::FEATURE_ROLLOUT) ? "and #{variation['name']} is Assigned" : ' ',
|
874
|
+
segmentation_type: SegmentationTypeEnum::WHITELISTING,
|
875
|
+
api_name: api_name
|
876
|
+
),
|
877
|
+
disable_logs
|
878
|
+
)
|
879
|
+
|
880
|
+
if variation
|
881
|
+
if campaign['type'] == CampaignTypes::VISUAL_AB || campaign['type'] == CampaignTypes::FEATURE_TEST
|
882
|
+
decision[:variation_name] = variation['name']
|
883
|
+
decision[:variation_id] = variation['id']
|
884
|
+
if campaign['type'] == CampaignTypes::FEATURE_TEST
|
885
|
+
decision[:is_feature_enabled] = variation['isFeatureEnabled']
|
886
|
+
end
|
887
|
+
end
|
888
|
+
decision[:is_user_whitelisted] = true
|
889
|
+
@hooks_manager.execute(decision)
|
890
|
+
end
|
891
|
+
|
892
|
+
return variation if variation && variation['name']
|
893
|
+
else
|
894
|
+
@logger.log(
|
895
|
+
LogLevelEnum::INFO,
|
896
|
+
format(
|
897
|
+
LogMessageEnum::InfoMessages::WHITELISTING_SKIPPED,
|
898
|
+
file: FILE,
|
899
|
+
campaign_key: campaign_key,
|
900
|
+
user_id: user_id,
|
901
|
+
api_name: api_name
|
902
|
+
),
|
903
|
+
disable_logs
|
904
|
+
)
|
905
|
+
end
|
906
|
+
nil
|
907
|
+
end
|
908
|
+
|
620
909
|
end
|
621
910
|
end
|
622
911
|
end
|