vwo-sdk 1.16.0 → 1.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/abc.txt +28 -0
- data/lib/vwo/constants.rb +2 -1
- data/lib/vwo/core/bucketer.rb +33 -5
- data/lib/vwo/core/variation_decider.rb +416 -130
- data/lib/vwo/enums.rb +6 -1
- data/lib/vwo/logger.rb +4 -2
- data/lib/vwo/schemas/settings_file.rb +1 -0
- data/lib/vwo/services/segment_evaluator.rb +4 -2
- data/lib/vwo/utils/campaign.rb +58 -0
- data/lib/vwo.rb +71 -67
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84d01560f605a69e8ed011a19ba4e3aae0f67341fd653a562d817801d6a55073
|
4
|
+
data.tar.gz: b1355bef1b2b095774c702a6757c1a7141e2cf9758d0a1b8a0510111a8ee597a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc2c8a411e3c0a674ab2bc00e540b3e49a8dd943ec50aa04fba04839ef6f3e255fc275529f872aa5ca73dfe893cb43e8853a0875cc3dda9330554b6491590947
|
7
|
+
data.tar.gz: 5482e79564a365ec8fe4012b25997096352129e915daca28774c790c416a528302ea1f0bb685ef559b9ee0846b0229957a8f6ab77008f4e48222a7cae5892699
|
data/lib/abc.txt
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
2
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
3
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
4
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
5
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
6
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
7
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
8
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
9
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
10
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
11
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
12
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
13
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
14
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
15
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
16
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
17
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
18
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
19
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
20
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
21
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
22
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
23
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
24
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
25
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
26
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
27
|
+
{"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
|
28
|
+
GOT_ELIGIBLE_CAMPAIGNS
|
data/lib/vwo/constants.rb
CHANGED
@@ -19,6 +19,7 @@ class VWO
|
|
19
19
|
SEED_VALUE = 1
|
20
20
|
MAX_TRAFFIC_PERCENT = 100
|
21
21
|
MAX_TRAFFIC_VALUE = 10_000
|
22
|
+
MAX_RANGE = 10000
|
22
23
|
STATUS_RUNNING = 'RUNNING'
|
23
24
|
# rubocop:disable Style/ExpandPathArguments
|
24
25
|
LIBRARY_PATH = File.expand_path('../..', __FILE__)
|
@@ -26,7 +27,7 @@ class VWO
|
|
26
27
|
HTTP_PROTOCOL = 'http://'
|
27
28
|
HTTPS_PROTOCOL = 'https://'
|
28
29
|
URL_NAMESPACE = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'
|
29
|
-
SDK_VERSION = '1.
|
30
|
+
SDK_VERSION = '1.22.0'
|
30
31
|
SDK_NAME = 'ruby'
|
31
32
|
VWO_DELIMITER = '_vwo_'
|
32
33
|
MAX_EVENTS_PER_REQUEST = 5000
|
data/lib/vwo/core/bucketer.rb
CHANGED
@@ -60,7 +60,7 @@ class VWO
|
|
60
60
|
end
|
61
61
|
|
62
62
|
traffic_allocation = campaign['percentTraffic']
|
63
|
-
value_assigned_to_user = get_bucket_value_for_user(user_id)
|
63
|
+
value_assigned_to_user = get_bucket_value_for_user(user_id, campaign)
|
64
64
|
is_user_part = (value_assigned_to_user != 0) && value_assigned_to_user <= traffic_allocation
|
65
65
|
@logger.log(
|
66
66
|
LogLevelEnum::INFO,
|
@@ -94,7 +94,11 @@ class VWO
|
|
94
94
|
return
|
95
95
|
end
|
96
96
|
|
97
|
-
|
97
|
+
user_id_for_hash_value = user_id
|
98
|
+
if campaign[:isBucketingSeedEnabled]
|
99
|
+
user_id_for_hash_value = campaign[:id].to_s + "_" + user_id
|
100
|
+
end
|
101
|
+
hash_value = MurmurHash3::V32.str_hash(user_id_for_hash_value, SEED_VALUE) & U_MAX_32_BIT
|
98
102
|
normalize = MAX_TRAFFIC_VALUE.to_f / campaign['percentTraffic']
|
99
103
|
multiplier = normalize / 100
|
100
104
|
bucket_value = get_bucket_value(
|
@@ -136,10 +140,17 @@ class VWO
|
|
136
140
|
# User by hashing the userId by murmurHash and scaling it down.
|
137
141
|
#
|
138
142
|
# @param[String] :user_id The unique ID assigned to User
|
143
|
+
# @param[String] :campaign Campaign data
|
139
144
|
# @return[Integer] The bucket Value allotted to User
|
140
145
|
# (between 1 to $this->$MAX_TRAFFIC_PERCENT)
|
141
|
-
def get_bucket_value_for_user(user_id)
|
142
|
-
|
146
|
+
def get_bucket_value_for_user(user_id, campaign = {}, group_id = nil, disable_logs = false)
|
147
|
+
user_id_for_hash_value = user_id
|
148
|
+
if group_id
|
149
|
+
user_id_for_hash_value = group_id.to_s + "_" + user_id
|
150
|
+
elsif campaign[:isBucketingSeedEnabled]
|
151
|
+
user_id_for_hash_value = campaign[:id].to_s + "_" + user_id
|
152
|
+
end
|
153
|
+
hash_value = MurmurHash3::V32.str_hash(user_id_for_hash_value, SEED_VALUE) & U_MAX_32_BIT
|
143
154
|
bucket_value = get_bucket_value(hash_value, MAX_TRAFFIC_PERCENT)
|
144
155
|
|
145
156
|
@logger.log(
|
@@ -150,7 +161,8 @@ class VWO
|
|
150
161
|
hash_value: hash_value,
|
151
162
|
bucket_value: bucket_value,
|
152
163
|
user_id: user_id
|
153
|
-
)
|
164
|
+
),
|
165
|
+
disable_logs
|
154
166
|
)
|
155
167
|
bucket_value
|
156
168
|
end
|
@@ -168,6 +180,22 @@ class VWO
|
|
168
180
|
multiplied_value = (max_value * ratio + 1) * multiplier
|
169
181
|
multiplied_value.to_i
|
170
182
|
end
|
183
|
+
|
184
|
+
# Returns a campaign by checking the Start and End Bucket Allocations of each campaign.
|
185
|
+
#
|
186
|
+
# @param[Integer] :range_for_campaigns the bucket value of the user
|
187
|
+
# @param[Hash] :campaigns The bucket Value of the user
|
188
|
+
# @return[Hash|nil]
|
189
|
+
#
|
190
|
+
def get_campaign_using_range(range_for_campaigns, campaigns)
|
191
|
+
range_for_campaigns = range_for_campaigns * 100
|
192
|
+
campaigns.each do |campaign|
|
193
|
+
if campaign["max_range"] && campaign["max_range"] >= range_for_campaigns && campaign["min_range"] <= range_for_campaigns
|
194
|
+
return campaign
|
195
|
+
end
|
196
|
+
end
|
197
|
+
nil
|
198
|
+
end
|
171
199
|
end
|
172
200
|
end
|
173
201
|
end
|
@@ -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,17 @@ class VWO
|
|
93
95
|
:vwo_user_id => generator_for(user_id, @settings_file['accountId'])
|
94
96
|
}
|
95
97
|
|
96
|
-
if
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
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
|
137
|
-
|
138
|
-
return variation if variation && variation['name']
|
139
|
-
else
|
140
|
-
@logger.log(
|
141
|
-
LogLevelEnum::INFO,
|
142
|
-
format(
|
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
|
-
)
|
98
|
+
if is_campaign_part_of_group
|
99
|
+
group_id = @settings_file["campaignGroups"][campaign["id"].to_s]
|
100
|
+
decision[:group_id] = group_id
|
101
|
+
group_name = @settings_file["groups"][group_id.to_s]["name"]
|
102
|
+
decision[:group_name] = group_name
|
150
103
|
end
|
151
104
|
|
105
|
+
# evaluate whitelisting
|
106
|
+
variation = get_variation_if_whitelisting_passed(user_id, campaign, variation_targeting_variables, api_name, decision, true)
|
107
|
+
return variation if variation && variation['name']
|
108
|
+
|
152
109
|
user_campaign_map = get_user_storage(user_id, campaign_key)
|
153
110
|
variation = get_stored_variation(user_id, campaign_key, user_campaign_map) if valid_hash?(user_campaign_map)
|
154
111
|
|
@@ -194,8 +151,7 @@ class VWO
|
|
194
151
|
)
|
195
152
|
)
|
196
153
|
|
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
|
154
|
+
if ([ApiMethods::TRACK, ApiMethods::GET_VARIATION_NAME, ApiMethods::GET_FEATURE_VARIABLE_VALUE].include? api_name) && @user_storage_service
|
199
155
|
@logger.log(
|
200
156
|
LogLevelEnum::DEBUG,
|
201
157
|
format(
|
@@ -223,82 +179,106 @@ class VWO
|
|
223
179
|
end
|
224
180
|
|
225
181
|
# Pre-segmentation
|
182
|
+
is_presegmentation = check_presegmentation(campaign, user_id, custom_variables, api_name)
|
183
|
+
is_presegmentation_and_traffic_passed = is_presegmentation && @bucketer.user_part_of_campaign?(user_id, campaign)
|
184
|
+
unless is_presegmentation_and_traffic_passed
|
185
|
+
return nil
|
186
|
+
end
|
226
187
|
|
227
|
-
|
228
|
-
|
188
|
+
if is_presegmentation_and_traffic_passed && is_campaign_part_of_group
|
189
|
+
group_campaigns = get_group_campaigns(@settings_file, group_id)
|
190
|
+
|
191
|
+
if group_campaigns
|
192
|
+
is_any_campaign_whitelisted_or_stored = check_whitelisting_or_storage_for_grouped_campaigns(user_id, campaign, group_campaigns, group_name, variation_targeting_variables, true)
|
193
|
+
|
194
|
+
if is_any_campaign_whitelisted_or_stored
|
195
|
+
@logger.log(
|
196
|
+
LogLevelEnum::INFO,
|
197
|
+
format(
|
198
|
+
LogMessageEnum::InfoMessages::CALLED_CAMPAIGN_NOT_WINNER,
|
199
|
+
file: FILE,
|
200
|
+
campaign_key: campaign_key,
|
201
|
+
user_id: user_id,
|
202
|
+
group_name: group_name
|
203
|
+
)
|
204
|
+
)
|
205
|
+
return nil
|
206
|
+
end
|
207
|
+
|
208
|
+
eligible_campaigns = get_eligible_campaigns(user_id, group_campaigns, campaign, custom_variables)
|
209
|
+
non_eligible_campaigns_key = get_non_eligible_campaigns_key(eligible_campaigns, group_campaigns)
|
210
|
+
|
211
|
+
@logger.log(
|
212
|
+
LogLevelEnum::DEBUG,
|
213
|
+
format(
|
214
|
+
LogMessageEnum::DebugMessages::GOT_ELIGIBLE_CAMPAIGNS,
|
215
|
+
file: FILE,
|
216
|
+
user_id: user_id,
|
217
|
+
eligible_campaigns_key: get_eligible_campaigns_key(eligible_campaigns).join(","),
|
218
|
+
ineligible_campaigns_log_text: non_eligible_campaigns_key ? ("campaigns:" + non_eligible_campaigns_key.join("'")) : "no campaigns",
|
219
|
+
group_name: group_name
|
220
|
+
)
|
221
|
+
)
|
229
222
|
|
230
|
-
if is_valid_segments
|
231
|
-
unless custom_variables
|
232
223
|
@logger.log(
|
233
224
|
LogLevelEnum::INFO,
|
234
225
|
format(
|
235
|
-
LogMessageEnum::InfoMessages::
|
226
|
+
LogMessageEnum::InfoMessages::GOT_ELIGIBLE_CAMPAIGNS,
|
236
227
|
file: FILE,
|
237
|
-
campaign_key: campaign_key,
|
238
228
|
user_id: user_id,
|
239
|
-
|
229
|
+
no_of_eligible_campaigns: eligible_campaigns.length,
|
230
|
+
no_of_group_campaigns: group_campaigns.length,
|
231
|
+
group_name: group_name
|
240
232
|
)
|
241
233
|
)
|
242
|
-
|
243
|
-
|
244
|
-
unless @segment_evaluator.evaluate(campaign_key, user_id, segments, custom_variables)
|
234
|
+
|
235
|
+
winner_campaign = get_winner_campaign(user_id, eligible_campaigns, group_id)
|
245
236
|
@logger.log(
|
246
237
|
LogLevelEnum::INFO,
|
247
238
|
format(
|
248
|
-
LogMessageEnum::InfoMessages::
|
249
|
-
file:
|
239
|
+
LogMessageEnum::InfoMessages::GOT_WINNER_CAMPAIGN,
|
240
|
+
file: FILE,
|
250
241
|
user_id: user_id,
|
251
|
-
campaign_key:
|
252
|
-
|
242
|
+
campaign_key: winner_campaign["key"],
|
243
|
+
group_name: group_name
|
253
244
|
)
|
254
245
|
)
|
255
|
-
|
246
|
+
|
247
|
+
if winner_campaign && winner_campaign["id"] == campaign["id"]
|
248
|
+
variation = get_variation_allotted(user_id, campaign, true)
|
249
|
+
if variation && variation['name']
|
250
|
+
save_user_storage(user_id, campaign_key, campaign['type'], variation['name'], goal_identifier, true) if variation['name']
|
251
|
+
else
|
252
|
+
return nil
|
253
|
+
end
|
254
|
+
else
|
255
|
+
@logger.log(
|
256
|
+
LogLevelEnum::INFO,
|
257
|
+
format(
|
258
|
+
LogMessageEnum::InfoMessages::CALLED_CAMPAIGN_NOT_WINNER,
|
259
|
+
file: FILE,
|
260
|
+
campaign_key: campaign_key,
|
261
|
+
user_id: user_id,
|
262
|
+
group_name: group_name
|
263
|
+
)
|
264
|
+
)
|
265
|
+
return nil
|
266
|
+
end
|
256
267
|
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
268
|
end
|
280
269
|
|
281
|
-
variation
|
282
|
-
|
283
|
-
if variation && variation['name']
|
284
|
-
save_user_storage(user_id, campaign_key, variation['name'], goal_identifier) if variation['name']
|
270
|
+
if variation.nil?
|
271
|
+
variation = get_variation_allotted(user_id, campaign)
|
285
272
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
campaign_key: campaign_key,
|
292
|
-
user_id: user_id,
|
293
|
-
variation_name: variation['name'],
|
294
|
-
campaign_type: campaign['type']
|
273
|
+
if variation && variation['name']
|
274
|
+
save_user_storage(user_id, campaign_key, campaign['type'], variation['name'], goal_identifier) if variation['name']
|
275
|
+
else
|
276
|
+
@logger.log(
|
277
|
+
LogLevelEnum::INFO,
|
278
|
+
format(LogMessageEnum::InfoMessages::NO_VARIATION_ALLOCATED, file: FILE, campaign_key: campaign_key, user_id: user_id)
|
295
279
|
)
|
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
|
-
)
|
280
|
+
end
|
281
|
+
|
302
282
|
end
|
303
283
|
|
304
284
|
if variation
|
@@ -321,7 +301,7 @@ class VWO
|
|
321
301
|
#
|
322
302
|
# @return[Hash]
|
323
303
|
|
324
|
-
def get_variation_allotted(user_id, campaign)
|
304
|
+
def get_variation_allotted(user_id, campaign, disable_logs = false)
|
325
305
|
unless valid_value?(user_id)
|
326
306
|
@logger.log(
|
327
307
|
LogLevelEnum::ERROR,
|
@@ -341,7 +321,8 @@ class VWO
|
|
341
321
|
user_id: user_id,
|
342
322
|
campaign_key: campaign['key'],
|
343
323
|
method: 'get_variation_allotted'
|
344
|
-
)
|
324
|
+
),
|
325
|
+
disable_logs
|
345
326
|
)
|
346
327
|
variation
|
347
328
|
else
|
@@ -354,7 +335,8 @@ class VWO
|
|
354
335
|
user_id: user_id,
|
355
336
|
campaign_key: nil,
|
356
337
|
method: 'get_variation_allotted'
|
357
|
-
)
|
338
|
+
),
|
339
|
+
disable_logs
|
358
340
|
)
|
359
341
|
nil
|
360
342
|
end
|
@@ -413,13 +395,15 @@ class VWO
|
|
413
395
|
# @param[String] :campaign_key Unique campaign identifier
|
414
396
|
# @param[String] :variation_name Variation identifier
|
415
397
|
# @param[String] :goal_identifier The unique campaign's goal identifier
|
398
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
416
399
|
# @return[Boolean] true if found otherwise false
|
417
400
|
|
418
|
-
def save_user_storage(user_id, campaign_key, variation_name, goal_identifier)
|
401
|
+
def save_user_storage(user_id, campaign_key, campaign_type, variation_name, goal_identifier, disable_logs = false)
|
419
402
|
unless @user_storage_service
|
420
403
|
@logger.log(
|
421
404
|
LogLevelEnum::DEBUG,
|
422
|
-
format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_SAVE, file: FILE)
|
405
|
+
format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_SAVE, file: FILE),
|
406
|
+
disable_logs
|
423
407
|
)
|
424
408
|
return false
|
425
409
|
end
|
@@ -435,13 +419,28 @@ class VWO
|
|
435
419
|
|
436
420
|
@logger.log(
|
437
421
|
LogLevelEnum::INFO,
|
438
|
-
format(LogMessageEnum::InfoMessages::SAVING_DATA_USER_STORAGE_SERVICE, file: FILE, user_id: user_id)
|
422
|
+
format(LogMessageEnum::InfoMessages::SAVING_DATA_USER_STORAGE_SERVICE, file: FILE, user_id: user_id),
|
423
|
+
disable_logs
|
424
|
+
)
|
425
|
+
|
426
|
+
@logger.log(
|
427
|
+
LogLevelEnum::INFO,
|
428
|
+
format(
|
429
|
+
LogMessageEnum::InfoMessages::VARIATION_ALLOCATED,
|
430
|
+
file: FILE,
|
431
|
+
campaign_key: campaign_key,
|
432
|
+
user_id: user_id,
|
433
|
+
variation_name: variation_name,
|
434
|
+
campaign_type: campaign_type
|
435
|
+
),
|
436
|
+
disable_logs
|
439
437
|
)
|
440
438
|
true
|
441
439
|
rescue StandardError
|
442
440
|
@logger.log(
|
443
441
|
LogLevelEnum::ERROR,
|
444
|
-
format(LogMessageEnum::ErrorMessages::SAVE_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id)
|
442
|
+
format(LogMessageEnum::ErrorMessages::SAVE_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id),
|
443
|
+
disable_logs
|
445
444
|
)
|
446
445
|
false
|
447
446
|
end
|
@@ -455,10 +454,11 @@ class VWO
|
|
455
454
|
# @param[String] :api_name The key Passed to identify the calling API
|
456
455
|
# @param[String] :campaign_key Unique campaign key
|
457
456
|
# @param[Hash] :variation_targeting_variables Key/value pair of Whitelisting Custom Attributes
|
457
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
458
458
|
#
|
459
459
|
# @return[Hash]
|
460
460
|
|
461
|
-
def evaluate_whitelisting(user_id, campaign, api_name, campaign_key, variation_targeting_variables = {})
|
461
|
+
def evaluate_whitelisting(user_id, campaign, api_name, campaign_key, variation_targeting_variables = {}, disable_logs = false)
|
462
462
|
if variation_targeting_variables.nil?
|
463
463
|
variation_targeting_variables = { '_vwo_user_id' => user_id }
|
464
464
|
else
|
@@ -470,7 +470,7 @@ class VWO
|
|
470
470
|
segments = get_segments(variation)
|
471
471
|
is_valid_segments = valid_value?(segments)
|
472
472
|
if is_valid_segments
|
473
|
-
if @segment_evaluator.evaluate(campaign_key, user_id, segments, variation_targeting_variables)
|
473
|
+
if @segment_evaluator.evaluate(campaign_key, user_id, segments, variation_targeting_variables, disable_logs)
|
474
474
|
targeted_variations.push(variation)
|
475
475
|
status = StatusEnum::PASSED
|
476
476
|
else
|
@@ -488,7 +488,8 @@ class VWO
|
|
488
488
|
variation_name: variation['name'],
|
489
489
|
segmentation_type: SegmentationTypeEnum::WHITELISTING,
|
490
490
|
api_name: api_name
|
491
|
-
)
|
491
|
+
),
|
492
|
+
disable_logs
|
492
493
|
)
|
493
494
|
else
|
494
495
|
@logger.log(
|
@@ -500,7 +501,8 @@ class VWO
|
|
500
501
|
user_id: user_id,
|
501
502
|
api_name: api_name,
|
502
503
|
variation: variation['name']
|
503
|
-
)
|
504
|
+
),
|
505
|
+
disable_logs
|
504
506
|
)
|
505
507
|
end
|
506
508
|
end
|
@@ -525,7 +527,8 @@ class VWO
|
|
525
527
|
whitelisted_variation = @bucketer.get_variation(
|
526
528
|
targeted_variations_deep_clone,
|
527
529
|
@bucketer.get_bucket_value_for_user(
|
528
|
-
user_id
|
530
|
+
user_id,
|
531
|
+
campaign
|
529
532
|
)
|
530
533
|
)
|
531
534
|
else
|
@@ -553,18 +556,26 @@ class VWO
|
|
553
556
|
end
|
554
557
|
end
|
555
558
|
|
559
|
+
def scale_campaigns_weight(campaigns)
|
560
|
+
normalize_weight = 100/campaigns.length
|
561
|
+
campaigns.each do |campaign|
|
562
|
+
campaign['weight'] = normalize_weight
|
563
|
+
end
|
564
|
+
end
|
556
565
|
# Get the UserStorageData after looking up into get method
|
557
566
|
# Being provided via UserStorageService
|
558
567
|
#
|
559
568
|
# @param[String]: Unique user identifier
|
560
569
|
# @param[String]: Unique campaign key
|
570
|
+
# @param[Boolean] :disable_logs if True
|
561
571
|
# @return[Hash|Boolean]: user_storage data
|
562
572
|
|
563
|
-
def get_user_storage(user_id, campaign_key)
|
573
|
+
def get_user_storage(user_id, campaign_key, disable_logs = false)
|
564
574
|
unless @user_storage_service
|
565
575
|
@logger.log(
|
566
576
|
LogLevelEnum::DEBUG,
|
567
|
-
format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_LOOKUP, file: FILE)
|
577
|
+
format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_LOOKUP, file: FILE),
|
578
|
+
disable_logs
|
568
579
|
)
|
569
580
|
return false
|
570
581
|
end
|
@@ -577,13 +588,15 @@ class VWO
|
|
577
588
|
file: FILE,
|
578
589
|
user_id: user_id,
|
579
590
|
status: data.nil? ? 'Not Found' : 'Found'
|
580
|
-
)
|
591
|
+
),
|
592
|
+
disable_logs
|
581
593
|
)
|
582
594
|
data
|
583
595
|
rescue StandardError
|
584
596
|
@logger.log(
|
585
597
|
LogLevelEnum::ERROR,
|
586
|
-
format(LogMessageEnum::ErrorMessages::LOOK_UP_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id)
|
598
|
+
format(LogMessageEnum::ErrorMessages::LOOK_UP_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id),
|
599
|
+
disable_logs
|
587
600
|
)
|
588
601
|
false
|
589
602
|
end
|
@@ -593,10 +606,11 @@ class VWO
|
|
593
606
|
# @param[String] :user_id
|
594
607
|
# @param[String] :campaign_key campaign identified
|
595
608
|
# @param[Hash] :user_campaign_map BucketMap consisting of stored user variation
|
609
|
+
# @param[Boolean] :disable_logs if True
|
596
610
|
#
|
597
611
|
# @return[Object, nil] if found then variation settings object otherwise None
|
598
612
|
|
599
|
-
def get_stored_variation(user_id, campaign_key, user_campaign_map)
|
613
|
+
def get_stored_variation(user_id, campaign_key, user_campaign_map, disable_logs = false)
|
600
614
|
return unless user_campaign_map['campaign_key'] == campaign_key
|
601
615
|
|
602
616
|
variation_name = user_campaign_map['variation_name']
|
@@ -608,7 +622,8 @@ class VWO
|
|
608
622
|
campaign_key: campaign_key,
|
609
623
|
user_id: user_id,
|
610
624
|
variation_name: variation_name
|
611
|
-
)
|
625
|
+
),
|
626
|
+
disable_logs
|
612
627
|
)
|
613
628
|
|
614
629
|
get_campaign_variation(
|
@@ -617,6 +632,277 @@ class VWO
|
|
617
632
|
variation_name
|
618
633
|
)
|
619
634
|
end
|
635
|
+
|
636
|
+
# this function check whether pre-segmentation is passed or not
|
637
|
+
#
|
638
|
+
# @param[String] :user_id The unique key assigned to User
|
639
|
+
# @param[Hash] :campaign Campaign hash for Unique campaign key
|
640
|
+
# @param[Hash] :custom_variables Key/value pair for segmentation
|
641
|
+
# @param[String] :api_name The key Passed to identify the calling API
|
642
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
643
|
+
#
|
644
|
+
# @return[Boolean]
|
645
|
+
def check_presegmentation(campaign, user_id, custom_variables, api_name, disable_logs = false)
|
646
|
+
campaign_key = campaign['key']
|
647
|
+
segments = get_segments(campaign)
|
648
|
+
is_valid_segments = valid_value?(segments)
|
649
|
+
|
650
|
+
if is_valid_segments
|
651
|
+
unless custom_variables
|
652
|
+
@logger.log(
|
653
|
+
LogLevelEnum::INFO,
|
654
|
+
format(
|
655
|
+
LogMessageEnum::InfoMessages::NO_CUSTOM_VARIABLES,
|
656
|
+
file: FILE,
|
657
|
+
campaign_key: campaign_key,
|
658
|
+
user_id: user_id,
|
659
|
+
api_name: api_name
|
660
|
+
),
|
661
|
+
disable_logs
|
662
|
+
)
|
663
|
+
custom_variables = {}
|
664
|
+
end
|
665
|
+
unless @segment_evaluator.evaluate(campaign_key, user_id, segments, custom_variables, disable_logs)
|
666
|
+
@logger.log(
|
667
|
+
LogLevelEnum::INFO,
|
668
|
+
format(
|
669
|
+
LogMessageEnum::InfoMessages::USER_FAILED_SEGMENTATION,
|
670
|
+
file: FileNameEnum::SegmentEvaluator,
|
671
|
+
user_id: user_id,
|
672
|
+
campaign_key: campaign_key,
|
673
|
+
custom_variables: custom_variables
|
674
|
+
),
|
675
|
+
disable_logs
|
676
|
+
)
|
677
|
+
return false
|
678
|
+
end
|
679
|
+
@logger.log(
|
680
|
+
LogLevelEnum::INFO,
|
681
|
+
format(
|
682
|
+
LogMessageEnum::InfoMessages::USER_PASSED_SEGMENTATION,
|
683
|
+
file: FileNameEnum::SegmentEvaluator,
|
684
|
+
user_id: user_id,
|
685
|
+
campaign_key: campaign_key,
|
686
|
+
custom_variables: custom_variables
|
687
|
+
),
|
688
|
+
disable_logs
|
689
|
+
)
|
690
|
+
else
|
691
|
+
@logger.log(
|
692
|
+
LogLevelEnum::INFO,
|
693
|
+
format(
|
694
|
+
LogMessageEnum::InfoMessages::SKIPPING_SEGMENTATION,
|
695
|
+
file: FILE,
|
696
|
+
campaign_key: campaign_key,
|
697
|
+
user_id: user_id,
|
698
|
+
api_name: api_name,
|
699
|
+
variation: ''
|
700
|
+
),
|
701
|
+
disable_logs
|
702
|
+
)
|
703
|
+
end
|
704
|
+
true
|
705
|
+
end
|
706
|
+
|
707
|
+
# Finds and returns eligible campaigns from group_campaigns.
|
708
|
+
#
|
709
|
+
# @param[String] :user_id The unique key assigned to User
|
710
|
+
# @param[Hash] :called_campaign campaign for which api is called
|
711
|
+
# @param[Array] :group_campaigns campaigns part of group
|
712
|
+
# @param[String] :custom_variables Key/value pair for segmentation
|
713
|
+
#
|
714
|
+
# @return[Array]
|
715
|
+
def get_eligible_campaigns(user_id, group_campaigns, called_campaign, custom_variables)
|
716
|
+
eligible_campaigns = []
|
717
|
+
|
718
|
+
group_campaigns.each do |campaign|
|
719
|
+
if called_campaign["id"] == campaign["id"] || check_presegmentation(campaign, user_id, custom_variables, '', true) && @bucketer.user_part_of_campaign?(user_id, campaign)
|
720
|
+
eligible_campaigns.append(campaign)
|
721
|
+
end
|
722
|
+
end
|
723
|
+
return eligible_campaigns
|
724
|
+
end
|
725
|
+
|
726
|
+
# Finds and returns the winner campaign from eligible_campaigns list.
|
727
|
+
#
|
728
|
+
# @param[String] :user_id The unique key assigned to User
|
729
|
+
# @param[Array] :eligible_campaigns campaigns part of group which were eligible to be winner
|
730
|
+
#
|
731
|
+
# @return[Hash]
|
732
|
+
def get_winner_campaign(user_id, eligible_campaigns, group_id)
|
733
|
+
if eligible_campaigns.length == 1
|
734
|
+
return eligible_campaigns[0]
|
735
|
+
end
|
736
|
+
|
737
|
+
eligible_campaigns = scale_campaigns_weight(eligible_campaigns)
|
738
|
+
eligible_campaigns = set_campaign_allocation(eligible_campaigns)
|
739
|
+
bucket_value = @bucketer.get_bucket_value_for_user(user_id, {}, group_id, true)
|
740
|
+
return @bucketer.get_campaign_using_range(bucket_value, eligible_campaigns)
|
741
|
+
end
|
742
|
+
|
743
|
+
# Get campaign keys of all eligible Campaigns.
|
744
|
+
#
|
745
|
+
# @param[Array] :eligible_campaigns campaigns part of group which were eligible to be winner
|
746
|
+
#
|
747
|
+
# @return[Array]
|
748
|
+
def get_eligible_campaigns_key(eligible_campaigns)
|
749
|
+
eligible_campaigns_key = []
|
750
|
+
eligible_campaigns.each do |campaign|
|
751
|
+
eligible_campaigns_key.append(campaign["key"])
|
752
|
+
end
|
753
|
+
eligible_campaigns_key
|
754
|
+
end
|
755
|
+
|
756
|
+
# Get campaign keys of all non eligible Campaigns.
|
757
|
+
#
|
758
|
+
# @param[Array] :eligible_campaigns campaigns part of group which were eligible to be winner
|
759
|
+
# @param[Array] :group_campaigns campaigns part of group
|
760
|
+
#
|
761
|
+
# @return[Array]
|
762
|
+
def get_non_eligible_campaigns_key(eligible_campaigns, group_campaigns)
|
763
|
+
non_eligible_campaigns_key = []
|
764
|
+
group_campaigns.each do |campaign|
|
765
|
+
unless eligible_campaigns.include? campaign
|
766
|
+
non_eligible_campaigns_key.append(campaign["key"])
|
767
|
+
end
|
768
|
+
end
|
769
|
+
non_eligible_campaigns_key
|
770
|
+
end
|
771
|
+
|
772
|
+
# Checks if any other campaign in groupCampaigns satisfies whitelisting or is in user storage.
|
773
|
+
#
|
774
|
+
# @param[String] :user_id the unique ID assigned to User
|
775
|
+
# @param[Hash] :called_campaign campaign for which api is called
|
776
|
+
# @param[Array] :group_campaigns campaigns part of group
|
777
|
+
# @param[String] :group_name group name
|
778
|
+
# @param[Hash] :variation_targeting_variables Key/value pair of Whitelisting Custom Attributes
|
779
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
780
|
+
# @return[Boolean]
|
781
|
+
|
782
|
+
def check_whitelisting_or_storage_for_grouped_campaigns(user_id, called_campaign, group_campaigns, group_name, variation_targeting_variables, disable_logs = false)
|
783
|
+
group_campaigns.each do |campaign|
|
784
|
+
if called_campaign["id"] != campaign["id"]
|
785
|
+
targeted_variation = evaluate_whitelisting(
|
786
|
+
user_id,
|
787
|
+
campaign,
|
788
|
+
'',
|
789
|
+
campaign["key"],
|
790
|
+
variation_targeting_variables,
|
791
|
+
true
|
792
|
+
)
|
793
|
+
if targeted_variation
|
794
|
+
@logger.log(
|
795
|
+
LogLevelEnum::INFO,
|
796
|
+
format(
|
797
|
+
LogMessageEnum::InfoMessages::OTHER_CAMPAIGN_SATISFIES_WHITELISTING_OR_STORAGE,
|
798
|
+
file: FILE,
|
799
|
+
campaign_key: campaign["key"],
|
800
|
+
user_id: user_id,
|
801
|
+
group_name: group_name,
|
802
|
+
type: "whitelisting"
|
803
|
+
),
|
804
|
+
disable_logs
|
805
|
+
)
|
806
|
+
return true
|
807
|
+
end
|
808
|
+
end
|
809
|
+
end
|
810
|
+
|
811
|
+
group_campaigns.each do |campaign|
|
812
|
+
if called_campaign["id"] != campaign["id"]
|
813
|
+
user_storage_data = get_user_storage(user_id, campaign["key"], true)
|
814
|
+
if user_storage_data
|
815
|
+
@logger.log(
|
816
|
+
LogLevelEnum::INFO,
|
817
|
+
format(
|
818
|
+
LogMessageEnum::InfoMessages::OTHER_CAMPAIGN_SATISFIES_WHITELISTING_OR_STORAGE,
|
819
|
+
file: FILE,
|
820
|
+
campaign_key: campaign["key"],
|
821
|
+
user_id: user_id,
|
822
|
+
group_name: group_name,
|
823
|
+
type: "user storage"
|
824
|
+
),
|
825
|
+
disable_logs
|
826
|
+
)
|
827
|
+
return true
|
828
|
+
end
|
829
|
+
end
|
830
|
+
end
|
831
|
+
false
|
832
|
+
end
|
833
|
+
|
834
|
+
# Get variation if whitelisting passes
|
835
|
+
#
|
836
|
+
# @param[String] :user_id the unique ID assigned to User
|
837
|
+
# @param[Hash] :campaign campaign for which checking whitelisting
|
838
|
+
# @param[Hash] :variation_targeting_variables Key/value pair of Whitelisting Custom Attributes
|
839
|
+
# @param[String] :api_name The key Passed to identify the calling API
|
840
|
+
# @param[Hash] :decision data containing campaign info passed to hooks manager
|
841
|
+
# @param[Boolean] :disable_logs optional: disable logs if True
|
842
|
+
# @return[Hash]
|
843
|
+
def get_variation_if_whitelisting_passed(user_id, campaign, variation_targeting_variables, api_name, decision, disable_logs = false)
|
844
|
+
campaign_key = campaign['key']
|
845
|
+
if campaign['isForcedVariationEnabled']
|
846
|
+
variation = evaluate_whitelisting(
|
847
|
+
user_id,
|
848
|
+
campaign,
|
849
|
+
api_name,
|
850
|
+
campaign_key,
|
851
|
+
variation_targeting_variables,
|
852
|
+
disable_logs
|
853
|
+
)
|
854
|
+
status = if variation
|
855
|
+
StatusEnum::PASSED
|
856
|
+
else
|
857
|
+
StatusEnum::FAILED
|
858
|
+
end
|
859
|
+
|
860
|
+
@logger.log(
|
861
|
+
LogLevelEnum::INFO,
|
862
|
+
format(
|
863
|
+
LogMessageEnum::InfoMessages::SEGMENTATION_STATUS,
|
864
|
+
file: FILE,
|
865
|
+
campaign_key: campaign_key,
|
866
|
+
user_id: user_id,
|
867
|
+
status: status,
|
868
|
+
custom_variables: variation_targeting_variables,
|
869
|
+
variation_name: status == StatusEnum::PASSED ? "and #{variation['name']} is Assigned" : ' ',
|
870
|
+
segmentation_type: SegmentationTypeEnum::WHITELISTING,
|
871
|
+
api_name: api_name
|
872
|
+
),
|
873
|
+
disable_logs
|
874
|
+
)
|
875
|
+
|
876
|
+
if variation
|
877
|
+
if campaign['type'] == CampaignTypes::VISUAL_AB || campaign['type'] == CampaignTypes::FEATURE_TEST
|
878
|
+
decision[:variation_name] = variation['name']
|
879
|
+
decision[:variation_id] = variation['id']
|
880
|
+
if campaign['type'] == CampaignTypes::FEATURE_TEST
|
881
|
+
decision[:is_feature_enabled] = variation['isFeatureEnabled']
|
882
|
+
elsif campaign['type'] == CampaignTypes::VISUAL_AB
|
883
|
+
decision[:is_user_whitelisted] = !!variation['name']
|
884
|
+
end
|
885
|
+
end
|
886
|
+
@hooks_manager.execute(decision)
|
887
|
+
end
|
888
|
+
|
889
|
+
return variation if variation && variation['name']
|
890
|
+
else
|
891
|
+
@logger.log(
|
892
|
+
LogLevelEnum::INFO,
|
893
|
+
format(
|
894
|
+
LogMessageEnum::InfoMessages::WHITELISTING_SKIPPED,
|
895
|
+
file: FILE,
|
896
|
+
campaign_key: campaign_key,
|
897
|
+
user_id: user_id,
|
898
|
+
api_name: api_name
|
899
|
+
),
|
900
|
+
disable_logs
|
901
|
+
)
|
902
|
+
end
|
903
|
+
nil
|
904
|
+
end
|
905
|
+
|
620
906
|
end
|
621
907
|
end
|
622
908
|
end
|
data/lib/vwo/enums.rb
CHANGED
@@ -113,6 +113,7 @@ class VWO
|
|
113
113
|
BULK_NOT_PROCESSED = "(%<file>s): Batch events couldn't be received by VWO. Calling Flush Callback with error and data."
|
114
114
|
BEFORE_FLUSHING = '(%<file>s): Flushing events queue %<manually>s having %<length>s events %<timer>s queue summary: %<queue_metadata>s'
|
115
115
|
EVENT_BATCHING_INSUFFICIENT = '(%<file>s): %<key>s not provided, assigning default value'
|
116
|
+
GOT_ELIGIBLE_CAMPAIGNS = "(%<file>s): Campaigns:%<eligible_campaigns_key>s are eligible, %<ineligible_campaigns_log_text>s are ineligible from the Group:%<group_name>s for the User ID:%<user_id>s"
|
116
117
|
end
|
117
118
|
|
118
119
|
# Info Messages
|
@@ -152,9 +153,13 @@ class VWO
|
|
152
153
|
CAMPAIGN_NOT_ACTIVATED = '(%<file>s): Activate the campaign:%<campaign_key>s for User ID:%<user_id>s to %<reason>s.'
|
153
154
|
GOAL_ALREADY_TRACKED = '(%<file>s): Goal:%<goal_identifier>s of Campaign:%<campaign_key>s for User ID:%<user_id>s has already been tracked earlier. Skipping now'
|
154
155
|
USER_ALREADY_TRACKED = '(%<file>s): User ID:%<user_id>s for Campaign:%<campaign_key>s has already been tracked earlier for "%<api_name>s" API. Skipping now'
|
155
|
-
API_CALLED = '(%<file>s): API:
|
156
|
+
API_CALLED = '(%<file>s): API: %<api_name>s called for UserId:%<user_id>s'
|
156
157
|
BULK_IMPRESSION_SUCCESS = '(%<file>s): Impression event - %<end_point>s was successfully received by VWO having accountId:%<a>s'
|
157
158
|
AFTER_FLUSHING = '(%<file>s): Events queue having %<length>s events has been flushed %<manually>s queue summary: %<queue_metadata>s'
|
159
|
+
GOT_WINNER_CAMPAIGN = "(%<file>s): Campaign:%<campaign_key>s is selected from the mutually exclusive group:%<group_name>s for the User ID:%<user_id>s"
|
160
|
+
GOT_ELIGIBLE_CAMPAIGNS = "(%<file>s): Got %<no_of_eligible_campaigns>s eligible winners out of %<no_of_group_campaigns>s from the Group:%<group_name>s and for User ID:%<user_id>s"
|
161
|
+
CALLED_CAMPAIGN_NOT_WINNER = "(%<file>s): Campaign:%<campaign_key>s does not qualify from the mutually exclusive group:%<group_name>s for User ID:%<user_id>s"
|
162
|
+
OTHER_CAMPAIGN_SATISFIES_WHITELISTING_OR_STORAGE = "(%<file>s): Campaign:%<campaign_key>s of Group:%<group_name>s satisfies %<type>s for User ID:%<user_id>s"
|
158
163
|
end
|
159
164
|
|
160
165
|
# Warning Messages
|
data/lib/vwo/logger.rb
CHANGED
@@ -28,8 +28,10 @@ class VWO
|
|
28
28
|
end
|
29
29
|
|
30
30
|
# Override this method to handle logs in a custom manner
|
31
|
-
def log(level, message)
|
32
|
-
|
31
|
+
def log(level, message, disable_logs = false)
|
32
|
+
unless disable_logs
|
33
|
+
@@logger_instance.log(level, message)
|
34
|
+
end
|
33
35
|
end
|
34
36
|
|
35
37
|
def instance
|
@@ -63,10 +63,11 @@ class VWO
|
|
63
63
|
# @param[String] :user_id Unique user identifier
|
64
64
|
# @param[Hash] :dsl Segments provided in the settings_file
|
65
65
|
# @param[Hash] :custom_variables Custom variables provided in the apis
|
66
|
+
# @param[Boolean] :disable_logs disable logs if True
|
66
67
|
#
|
67
68
|
# @return[Boolean] true if user passed pre-segmentation, else false
|
68
69
|
#
|
69
|
-
def evaluate(campaign_key, user_id, dsl, custom_variables)
|
70
|
+
def evaluate(campaign_key, user_id, dsl, custom_variables, disable_logs = false)
|
70
71
|
result = evaluate_util(dsl, custom_variables) if valid_value?(dsl)
|
71
72
|
result
|
72
73
|
rescue StandardError => e
|
@@ -79,7 +80,8 @@ class VWO
|
|
79
80
|
campaign_key: campaign_key,
|
80
81
|
custom_variables: custom_variables,
|
81
82
|
error_message: e
|
82
|
-
)
|
83
|
+
),
|
84
|
+
disable_logs
|
83
85
|
)
|
84
86
|
false
|
85
87
|
end
|
data/lib/vwo/utils/campaign.rb
CHANGED
@@ -57,6 +57,26 @@ class VWO
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
+
# Sets campaign allocation range in the provided campaigns list
|
61
|
+
#
|
62
|
+
# @param [Array]: Array of Campaigns
|
63
|
+
def set_campaign_allocation(campaigns)
|
64
|
+
current_allocation = 0
|
65
|
+
campaigns.each do |campaign|
|
66
|
+
step_factor = get_variation_bucketing_range(campaign['weight'])
|
67
|
+
if step_factor > 0
|
68
|
+
start_range = current_allocation + 1
|
69
|
+
end_range = current_allocation + step_factor
|
70
|
+
campaign['min_range'] = start_range
|
71
|
+
campaign['max_range'] = end_range
|
72
|
+
current_allocation += step_factor
|
73
|
+
else
|
74
|
+
campaign['min_range'] = -1
|
75
|
+
campaign['max_range'] = -1
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
60
80
|
# Returns goal from given campaign_key and gaol_identifier.
|
61
81
|
# @param[String] :campaign Campaign object
|
62
82
|
# @param[String] :goal_identifier Goal identifier
|
@@ -249,6 +269,44 @@ class VWO
|
|
249
269
|
return campaign
|
250
270
|
end
|
251
271
|
|
272
|
+
# Checks whether a campaign is part of a group.
|
273
|
+
#
|
274
|
+
# @param[Hash] :settings_file Settings file for the project
|
275
|
+
# @param[Integer] :campaign_id Id of campaign which is to be checked
|
276
|
+
# @return[Boolean]
|
277
|
+
def is_part_of_group(settings_file, campaign_id)
|
278
|
+
if settings_file["campaignGroups"] && (settings_file["campaignGroups"].has_key?(campaign_id.to_s))
|
279
|
+
return true
|
280
|
+
end
|
281
|
+
false
|
282
|
+
end
|
283
|
+
|
284
|
+
# Returns campaigns which are part of given group using group_id.
|
285
|
+
#
|
286
|
+
# @param[Hash] :settings_file Settings file for the project
|
287
|
+
# @param[Integer] :group_id id of group whose campaigns are to be return
|
288
|
+
# @return[Array]
|
289
|
+
def get_group_campaigns(settings_file, group_id)
|
290
|
+
group_campaign_ids = []
|
291
|
+
group_campaigns = []
|
292
|
+
groups = settings_file["groups"]
|
293
|
+
|
294
|
+
if groups && groups.has_key?(group_id.to_s)
|
295
|
+
group_campaign_ids = groups[group_id.to_s]["campaigns"]
|
296
|
+
end
|
297
|
+
|
298
|
+
if group_campaign_ids
|
299
|
+
group_campaign_ids.each do |campaign_id|
|
300
|
+
settings_file["campaigns"].each do |campaign|
|
301
|
+
if campaign["id"] == campaign_id && campaign["status"] == STATUS_RUNNING
|
302
|
+
group_campaigns.append(campaign)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
group_campaigns
|
308
|
+
end
|
309
|
+
|
252
310
|
end
|
253
311
|
end
|
254
312
|
end
|
data/lib/vwo.rb
CHANGED
@@ -413,7 +413,6 @@ class VWO
|
|
413
413
|
)
|
414
414
|
end
|
415
415
|
end
|
416
|
-
variation['name']
|
417
416
|
else
|
418
417
|
@logger.log(
|
419
418
|
LogLevelEnum::INFO,
|
@@ -425,8 +424,8 @@ class VWO
|
|
425
424
|
api_name: ApiMethods::ACTIVATE
|
426
425
|
)
|
427
426
|
)
|
428
|
-
nil
|
429
427
|
end
|
428
|
+
variation['name']
|
430
429
|
rescue StandardError => e
|
431
430
|
@logger.log(
|
432
431
|
LogLevelEnum::ERROR,
|
@@ -676,7 +675,7 @@ class VWO
|
|
676
675
|
if !identifiers.include? goal_identifier
|
677
676
|
updated_goal_identifier = variation['goal_identifier']
|
678
677
|
updated_goal_identifier += VWO_DELIMITER + goal_identifier
|
679
|
-
@variation_decider.save_user_storage(user_id, campaign['key'], variation['name'], updated_goal_identifier) if variation['name']
|
678
|
+
@variation_decider.save_user_storage(user_id, campaign['key'], campaign['name'], variation['name'], updated_goal_identifier) if variation['name']
|
680
679
|
# set variation at user storage
|
681
680
|
elsif !should_track_returning_user
|
682
681
|
@logger.log(
|
@@ -870,80 +869,85 @@ class VWO
|
|
870
869
|
return false unless variation
|
871
870
|
|
872
871
|
# if campaign type is feature_test Send track call to server
|
873
|
-
if campaign_type == CampaignTypes::FEATURE_TEST
|
874
|
-
if is_eligible_to_send_impression(should_track_returning_user)
|
875
|
-
if defined?(@batch_events)
|
876
|
-
impression = create_bulk_event_impression(
|
877
|
-
@settings_file,
|
878
|
-
campaign['id'],
|
879
|
-
variation['id'],
|
880
|
-
user_id
|
881
|
-
)
|
882
|
-
@batch_events_queue.enqueue(impression)
|
883
|
-
else
|
884
|
-
impression = create_impression(
|
885
|
-
@settings_file,
|
886
|
-
campaign['id'],
|
887
|
-
variation['id'],
|
888
|
-
user_id,
|
889
|
-
@sdk_key,
|
890
|
-
goal_id: nil,
|
891
|
-
revenue: nil,
|
892
|
-
usage_stats: @usage_stats.usage_stats
|
893
|
-
)
|
894
872
|
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
variation_id: impression[:combination]
|
905
|
-
)
|
906
|
-
)
|
907
|
-
end
|
908
|
-
result = variation['isFeatureEnabled']
|
909
|
-
if result
|
910
|
-
@logger.log(
|
911
|
-
LogLevelEnum::INFO,
|
912
|
-
format(
|
913
|
-
LogMessageEnum::InfoMessages::FEATURE_ENABLED_FOR_USER,
|
914
|
-
file: FILE,
|
915
|
-
user_id: user_id,
|
916
|
-
feature_key: campaign_key,
|
917
|
-
api_name: ApiMethods::IS_FEATURE_ENABLED
|
918
|
-
)
|
919
|
-
)
|
920
|
-
else
|
921
|
-
@logger.log(
|
922
|
-
LogLevelEnum::INFO,
|
923
|
-
format(
|
924
|
-
LogMessageEnum::InfoMessages::FEATURE_NOT_ENABLED_FOR_USER,
|
925
|
-
file: FILE,
|
926
|
-
user_id: user_id,
|
927
|
-
feature_key: campaign_key,
|
928
|
-
api_name: ApiMethods::IS_FEATURE_ENABLED
|
929
|
-
)
|
930
|
-
)
|
931
|
-
end
|
932
|
-
return result
|
873
|
+
if is_eligible_to_send_impression(should_track_returning_user)
|
874
|
+
if defined?(@batch_events)
|
875
|
+
impression = create_bulk_event_impression(
|
876
|
+
@settings_file,
|
877
|
+
campaign['id'],
|
878
|
+
variation['id'],
|
879
|
+
user_id
|
880
|
+
)
|
881
|
+
@batch_events_queue.enqueue(impression)
|
933
882
|
else
|
883
|
+
impression = create_impression(
|
884
|
+
@settings_file,
|
885
|
+
campaign['id'],
|
886
|
+
variation['id'],
|
887
|
+
user_id,
|
888
|
+
@sdk_key,
|
889
|
+
nil,
|
890
|
+
nil,
|
891
|
+
usage_stats: @usage_stats.usage_stats
|
892
|
+
)
|
893
|
+
|
894
|
+
@event_dispatcher.dispatch(impression)
|
934
895
|
@logger.log(
|
935
896
|
LogLevelEnum::INFO,
|
936
897
|
format(
|
937
|
-
LogMessageEnum::InfoMessages::
|
898
|
+
LogMessageEnum::InfoMessages::MAIN_KEYS_FOR_IMPRESSION,
|
938
899
|
file: FILE,
|
939
|
-
|
940
|
-
|
941
|
-
|
900
|
+
campaign_id: impression[:experiment_id],
|
901
|
+
sdk_key: @sdk_key,
|
902
|
+
account_id: impression[:account_id],
|
903
|
+
variation_id: impression[:combination]
|
942
904
|
)
|
943
905
|
)
|
944
906
|
end
|
907
|
+
|
908
|
+
else
|
909
|
+
@logger.log(
|
910
|
+
LogLevelEnum::INFO,
|
911
|
+
format(
|
912
|
+
LogMessageEnum::InfoMessages::USER_ALREADY_TRACKED,
|
913
|
+
file: FILE,
|
914
|
+
user_id: user_id,
|
915
|
+
campaign_key: campaign_key,
|
916
|
+
api_name: ApiMethods::IS_FEATURE_ENABLED
|
917
|
+
)
|
918
|
+
)
|
945
919
|
end
|
946
|
-
|
920
|
+
if campaign_type == CampaignTypes::FEATURE_ROLLOUT
|
921
|
+
result = true
|
922
|
+
else
|
923
|
+
result = variation['isFeatureEnabled']
|
924
|
+
end
|
925
|
+
|
926
|
+
if result
|
927
|
+
@logger.log(
|
928
|
+
LogLevelEnum::INFO,
|
929
|
+
format(
|
930
|
+
LogMessageEnum::InfoMessages::FEATURE_ENABLED_FOR_USER,
|
931
|
+
file: FILE,
|
932
|
+
user_id: user_id,
|
933
|
+
feature_key: campaign_key,
|
934
|
+
api_name: ApiMethods::IS_FEATURE_ENABLED
|
935
|
+
)
|
936
|
+
)
|
937
|
+
else
|
938
|
+
@logger.log(
|
939
|
+
LogLevelEnum::INFO,
|
940
|
+
format(
|
941
|
+
LogMessageEnum::InfoMessages::FEATURE_NOT_ENABLED_FOR_USER,
|
942
|
+
file: FILE,
|
943
|
+
user_id: user_id,
|
944
|
+
feature_key: campaign_key,
|
945
|
+
api_name: ApiMethods::IS_FEATURE_ENABLED
|
946
|
+
)
|
947
|
+
)
|
948
|
+
end
|
949
|
+
|
950
|
+
result
|
947
951
|
rescue StandardError => e
|
948
952
|
@logger.log(
|
949
953
|
LogLevelEnum::ERROR,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vwo-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- VWO
|
@@ -87,6 +87,7 @@ executables: []
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
+
- lib/abc.txt
|
90
91
|
- lib/vwo.rb
|
91
92
|
- lib/vwo/constants.rb
|
92
93
|
- lib/vwo/core/bucketer.rb
|