vwo-sdk 1.30.0 → 1.37.1
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 +3 -2
- data/lib/vwo/core/bucketer.rb +50 -48
- data/lib/vwo/core/variation_decider.rb +427 -428
- data/lib/vwo/enums.rb +17 -154
- data/lib/vwo/logger.rb +8 -5
- data/lib/vwo/schemas/settings_file.rb +7 -6
- data/lib/vwo/services/batch_events_dispatcher.rb +45 -38
- data/lib/vwo/services/batch_events_queue.rb +52 -68
- data/lib/vwo/services/event_dispatcher.rb +46 -16
- data/lib/vwo/services/hooks_manager.rb +8 -12
- data/lib/vwo/services/segment_evaluator.rb +17 -15
- data/lib/vwo/services/settings_file_manager.rb +5 -5
- data/lib/vwo/services/settings_file_processor.rb +7 -4
- data/lib/vwo/services/usage_stats.rb +5 -4
- data/lib/vwo/utils/campaign.rb +61 -64
- data/lib/vwo/utils/custom_dimensions.rb +14 -14
- data/lib/vwo/utils/data_location_manager.rb +2 -9
- data/lib/vwo/utils/feature.rb +7 -10
- data/lib/vwo/utils/impression.rb +80 -79
- data/lib/vwo/utils/log_message.rb +69 -0
- data/lib/vwo/utils/request.rb +7 -9
- data/lib/vwo/utils/utility.rb +45 -28
- data/lib/vwo/utils/uuid.rb +12 -10
- data/lib/vwo/utils/validations.rb +124 -49
- data/lib/vwo.rb +472 -620
- metadata +11 -10
@@ -12,11 +12,11 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
require_relative '../logger'
|
16
15
|
require_relative '../enums'
|
17
16
|
require_relative '../utils/campaign'
|
18
17
|
require_relative '../services/segment_evaluator'
|
19
18
|
require_relative '../utils/validations'
|
19
|
+
require_relative '../utils/log_message'
|
20
20
|
require_relative 'bucketer'
|
21
21
|
require_relative '../constants'
|
22
22
|
require_relative '../services/hooks_manager'
|
@@ -33,14 +33,14 @@ class VWO
|
|
33
33
|
include VWO::CONSTANTS
|
34
34
|
include VWO::Utils::UUID
|
35
35
|
|
36
|
-
FILE = FileNameEnum::
|
36
|
+
FILE = FileNameEnum::VARIATION_DECIDER
|
37
37
|
|
38
38
|
# Initializes various services
|
39
39
|
# @param[Hash] - Settings file
|
40
40
|
# @param[Class] - Class instance having the capability of
|
41
41
|
# get and save.
|
42
42
|
def initialize(settings_file, user_storage_service = nil, options = {})
|
43
|
-
@logger = VWO::Logger
|
43
|
+
@logger = VWO::Utils::Logger
|
44
44
|
@user_storage_service = user_storage_service
|
45
45
|
@bucketer = VWO::Core::Bucketer.new
|
46
46
|
@settings_file = settings_file
|
@@ -66,43 +66,17 @@ class VWO
|
|
66
66
|
|
67
67
|
return unless campaign
|
68
68
|
|
69
|
-
is_campaign_part_of_group = @settings_file &&
|
69
|
+
is_campaign_part_of_group = @settings_file && part_of_group?(@settings_file, campaign['id'])
|
70
70
|
|
71
71
|
@has_stored_variation = false
|
72
|
-
decision =
|
73
|
-
:campaign_id => campaign['id'],
|
74
|
-
:campaign_key => campaign_key,
|
75
|
-
:campaign_type => campaign['type'],
|
76
|
-
# campaign segmentation conditions
|
77
|
-
:custom_variables => custom_variables,
|
78
|
-
# event name
|
79
|
-
:event => Hooks::DECISION_TYPES['CAMPAIGN_DECISION'],
|
80
|
-
# goal tracked in case of track API
|
81
|
-
:goal_identifier => goal_identifier,
|
82
|
-
# campaign whitelisting flag
|
83
|
-
:is_forced_variation_enabled => campaign['isForcedVariationEnabled'] ? campaign['isForcedVariationEnabled'] : false,
|
84
|
-
:sdk_version => SDK_VERSION,
|
85
|
-
# API name which triggered the event
|
86
|
-
:source => api_name,
|
87
|
-
# Passed in API
|
88
|
-
:user_id => user_id,
|
89
|
-
# Campaign Whitelisting conditions
|
90
|
-
:variation_targeting_variables => variation_targeting_variables,
|
91
|
-
:is_user_whitelisted => false,
|
92
|
-
:from_user_storage_service => false,
|
93
|
-
:is_feature_enabled => true,
|
94
|
-
# VWO generated UUID based on passed UserId and Account ID
|
95
|
-
:vwo_user_id => generator_for(user_id, @settings_file['accountId'])
|
96
|
-
}
|
72
|
+
decision = initialize_decision_properties(user_id, campaign, api_name, custom_variables, variation_targeting_variables, goal_identifier)
|
97
73
|
|
98
|
-
if campaign.
|
99
|
-
decision[:campaign_name] = campaign['name']
|
100
|
-
end
|
74
|
+
decision[:campaign_name] = campaign['name'] if campaign.key?('name')
|
101
75
|
|
102
76
|
if is_campaign_part_of_group
|
103
|
-
group_id = @settings_file[
|
77
|
+
group_id = @settings_file['campaignGroups'][campaign['id'].to_s]
|
104
78
|
decision[:group_id] = group_id
|
105
|
-
group_name = @settings_file[
|
79
|
+
group_name = @settings_file['groups'][group_id.to_s]['name']
|
106
80
|
decision[:group_name] = group_name
|
107
81
|
end
|
108
82
|
|
@@ -110,189 +84,250 @@ class VWO
|
|
110
84
|
variation = get_variation_if_whitelisting_passed(user_id, campaign, variation_targeting_variables, api_name, decision, true)
|
111
85
|
return variation if variation && variation['name']
|
112
86
|
|
113
|
-
|
114
|
-
|
87
|
+
if campaign.key?('isAlwaysCheckSegment')
|
88
|
+
is_presegmentation = presegmentation?(campaign, user_id, custom_variables, api_name)
|
89
|
+
return get_variation_if_presegmentation_applied(is_presegmentation, campaign, user_id, goal_identifier, decision)
|
90
|
+
else
|
91
|
+
user_campaign_map = get_user_storage(user_id, campaign_key)
|
92
|
+
variation = get_stored_variation(user_id, campaign_key, user_campaign_map) if valid_hash?(user_campaign_map)
|
115
93
|
|
116
|
-
|
117
|
-
variation = variation.dup # deep copy
|
118
|
-
end
|
94
|
+
variation = variation.dup if variation # deep copy
|
119
95
|
|
120
|
-
if variation
|
121
|
-
if valid_string?(user_campaign_map['goal_identifier']) && api_name == ApiMethods::TRACK
|
122
|
-
variation['goal_identifier'] = user_campaign_map['goal_identifier']
|
123
|
-
end
|
124
|
-
@has_stored_variation = true
|
125
|
-
@logger.log(
|
126
|
-
LogLevelEnum::INFO,
|
127
|
-
format(
|
128
|
-
LogMessageEnum::InfoMessages::GOT_STORED_VARIATION,
|
129
|
-
file: FILE,
|
130
|
-
campaign_key: campaign_key,
|
131
|
-
user_id: user_id,
|
132
|
-
variation_name: variation['name']
|
133
|
-
)
|
134
|
-
)
|
135
|
-
decision[:from_user_storage_service] = !!variation['name']
|
136
96
|
if variation
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
@logger.log(
|
149
|
-
LogLevelEnum::DEBUG,
|
150
|
-
format(
|
151
|
-
LogMessageEnum::DebugMessages::NO_STORED_VARIATION,
|
152
|
-
file: FILE,
|
153
|
-
campaign_key: campaign_key,
|
154
|
-
user_id: user_id
|
97
|
+
variation['goal_identifier'] = user_campaign_map['goal_identifier'] if valid_string?(user_campaign_map['goal_identifier']) && api_name == ApiMethods::TRACK
|
98
|
+
@has_stored_variation = true
|
99
|
+
@logger.log(
|
100
|
+
LogLevelEnum::INFO,
|
101
|
+
'GOT_STORED_VARIATION',
|
102
|
+
{
|
103
|
+
'{file}' => FILE,
|
104
|
+
'{campaignKey}' => campaign_key,
|
105
|
+
'{userId}' => user_id,
|
106
|
+
'{variationName}' => variation['name']
|
107
|
+
}
|
155
108
|
)
|
156
|
-
|
157
|
-
|
158
|
-
|
109
|
+
decision[:from_user_storage_service] = !!variation['name']
|
110
|
+
decision = add_variation_to_decision_properties(decision, campaign, variation)
|
111
|
+
@hooks_manager.execute(decision)
|
112
|
+
return variation
|
113
|
+
else
|
159
114
|
@logger.log(
|
160
115
|
LogLevelEnum::DEBUG,
|
161
|
-
|
162
|
-
|
163
|
-
file
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
)
|
116
|
+
'USER_STORAGE_SERVICE_NO_STORED_DATA',
|
117
|
+
{
|
118
|
+
'{file}' => FILE,
|
119
|
+
'{campaignKey}' => campaign_key,
|
120
|
+
'{userId}' => user_id
|
121
|
+
}
|
168
122
|
)
|
169
123
|
|
170
|
-
|
171
|
-
LogLevelEnum::INFO,
|
172
|
-
format(
|
173
|
-
LogMessageEnum::InfoMessages::CAMPAIGN_NOT_ACTIVATED,
|
174
|
-
file: FILE,
|
175
|
-
campaign_key: campaign_key,
|
176
|
-
user_id: user_id,
|
177
|
-
api_name: api_name,
|
178
|
-
reason: api_name == ApiMethods::TRACK ? 'track it' : 'get the decision/value'
|
179
|
-
)
|
180
|
-
)
|
181
|
-
return
|
124
|
+
return if campaign_not_activated?(user_id, campaign_key, api_name)
|
182
125
|
end
|
183
126
|
end
|
184
127
|
|
185
128
|
# Pre-segmentation
|
186
|
-
is_presegmentation =
|
129
|
+
is_presegmentation = presegmentation?(campaign, user_id, custom_variables, api_name)
|
187
130
|
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
|
131
|
+
return nil unless is_presegmentation_and_traffic_passed
|
191
132
|
|
192
133
|
if is_presegmentation_and_traffic_passed && is_campaign_part_of_group
|
193
134
|
group_campaigns = get_group_campaigns(@settings_file, group_id)
|
194
|
-
|
195
135
|
if group_campaigns
|
196
|
-
|
197
|
-
|
198
|
-
if is_any_campaign_whitelisted_or_stored
|
136
|
+
if whitelisting_or_storage_for_grouped_campaigns?(user_id, campaign, group_campaigns, group_name, variation_targeting_variables, true)
|
199
137
|
@logger.log(
|
200
138
|
LogLevelEnum::INFO,
|
201
|
-
|
202
|
-
|
203
|
-
file
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
139
|
+
'MEG_CALLED_CAMPAIGN_NOT_WINNER',
|
140
|
+
{
|
141
|
+
'{file}' => FILE,
|
142
|
+
'{campaignKey}' => campaign_key,
|
143
|
+
'{userId}' => user_id,
|
144
|
+
'{groupName}' => group_name
|
145
|
+
}
|
208
146
|
)
|
209
147
|
return nil
|
210
148
|
end
|
211
|
-
|
212
149
|
eligible_campaigns = get_eligible_campaigns(user_id, group_campaigns, campaign, custom_variables)
|
213
150
|
non_eligible_campaigns_key = get_non_eligible_campaigns_key(eligible_campaigns, group_campaigns)
|
214
|
-
|
215
151
|
@logger.log(
|
216
152
|
LogLevelEnum::DEBUG,
|
217
|
-
|
218
|
-
|
219
|
-
file
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
153
|
+
'MEG_ELIGIBLE_CAMPAIGNS',
|
154
|
+
{
|
155
|
+
'{file}' => FILE,
|
156
|
+
'{userId}' => user_id,
|
157
|
+
'{eligibleCampaignKeys}' => get_eligible_campaigns_key(eligible_campaigns).join(','),
|
158
|
+
'{inEligibleText}' => non_eligible_campaigns_key ? "campaigns: + #{non_eligible_campaigns_key.join("'")}" : 'no campaigns',
|
159
|
+
'{groupName}' => group_name
|
160
|
+
}
|
225
161
|
)
|
226
162
|
|
227
163
|
@logger.log(
|
228
164
|
LogLevelEnum::INFO,
|
229
|
-
|
230
|
-
|
231
|
-
file
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
165
|
+
'MEG_ELIGIBLE_CAMPAIGNS',
|
166
|
+
{
|
167
|
+
'{file}' => FILE,
|
168
|
+
'{userId}' => user_id,
|
169
|
+
'{noOfEligibleCampaigns}' => eligible_campaigns.length,
|
170
|
+
'{noOfGroupCampaigns}' => group_campaigns.length,
|
171
|
+
'{groupName}' => group_name
|
172
|
+
}
|
237
173
|
)
|
238
174
|
|
239
175
|
winner_campaign = get_winner_campaign(user_id, eligible_campaigns, group_id)
|
240
176
|
@logger.log(
|
241
177
|
LogLevelEnum::INFO,
|
242
|
-
|
243
|
-
|
244
|
-
file
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
178
|
+
'MEG_GOT_WINNER_CAMPAIGN',
|
179
|
+
{
|
180
|
+
'{file}' => FILE,
|
181
|
+
'{userId}' => user_id,
|
182
|
+
'{campaignKey}' => winner_campaign['key'],
|
183
|
+
'{groupName}' => group_name
|
184
|
+
}
|
249
185
|
)
|
250
186
|
|
251
|
-
if
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
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
|
187
|
+
return if meg_called_campaign_not_winner?(user_id, group_name, campaign, winner_campaign)
|
188
|
+
|
189
|
+
variation = get_variation_allotted(user_id, campaign, true)
|
190
|
+
return nil unless variation && variation['name']
|
191
|
+
|
192
|
+
save_user_storage(user_id, campaign_key, campaign['type'], variation['name'], goal_identifier, true) if variation['name']
|
271
193
|
end
|
272
194
|
end
|
273
195
|
|
274
|
-
|
275
|
-
|
196
|
+
variation ||= get_variation_if_presegmentation_applied(is_presegmentation, campaign, user_id, goal_identifier, decision)
|
197
|
+
return unless variation
|
276
198
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
199
|
+
decision = add_variation_to_decision_properties(decision, campaign, variation)
|
200
|
+
@hooks_manager.execute(decision)
|
201
|
+
variation
|
202
|
+
end
|
203
|
+
|
204
|
+
def campaign_not_activated?(user_id, campaign_key, api_name)
|
205
|
+
if ([ApiMethods::TRACK, ApiMethods::GET_VARIATION_NAME, ApiMethods::GET_FEATURE_VARIABLE_VALUE].include? api_name) && @user_storage_service
|
206
|
+
@logger.log(
|
207
|
+
LogLevelEnum::WARNING,
|
208
|
+
'CAMPAIGN_NOT_ACTIVATED',
|
209
|
+
{
|
210
|
+
'{file}' => FILE,
|
211
|
+
'{campaignKey}' => campaign_key,
|
212
|
+
'{userId}' => user_id,
|
213
|
+
'{api}' => api_name
|
214
|
+
}
|
215
|
+
)
|
216
|
+
|
217
|
+
@logger.log(
|
218
|
+
LogLevelEnum::INFO,
|
219
|
+
'CAMPAIGN_NOT_ACTIVATED',
|
220
|
+
{
|
221
|
+
'{file}' => FILE,
|
222
|
+
'{campaignKey}' => campaign_key,
|
223
|
+
'{userId}' => user_id,
|
224
|
+
'{reason}' => api_name == ApiMethods::TRACK ? 'track it' : 'get the decision/value'
|
225
|
+
}
|
226
|
+
)
|
227
|
+
return true
|
228
|
+
end
|
229
|
+
false
|
230
|
+
end
|
231
|
+
|
232
|
+
def meg_called_campaign_not_winner?(user_id, group_name, campaign, winner_campaign)
|
233
|
+
unless winner_campaign && winner_campaign['id'] == campaign['id']
|
234
|
+
@logger.log(
|
235
|
+
LogLevelEnum::INFO,
|
236
|
+
'MEG_CALLED_CAMPAIGN_NOT_WINNER',
|
237
|
+
{
|
238
|
+
'{file}' => FILE,
|
239
|
+
'{campaignKey}' => campaign['key'],
|
240
|
+
'{userId}' => user_id,
|
241
|
+
'{groupName}' => group_name
|
242
|
+
}
|
243
|
+
)
|
244
|
+
return true
|
245
|
+
end
|
246
|
+
false
|
247
|
+
end
|
248
|
+
|
249
|
+
# Intitialize decision properties for hook manager
|
250
|
+
#
|
251
|
+
# @param[String] :user_id The unique ID assigned to User
|
252
|
+
# @param[Hash] :campaign Campaign hash itself
|
253
|
+
# @param[String] :api_name Name of the current api call
|
254
|
+
# @param[String] :goal_identifier The unique campaign's goal identifier
|
255
|
+
# @param[Hash] :custom_variables Key/value pair for segmentation
|
256
|
+
# @param[Hash] :variation_targeting_variables Key/value pair for whitelisting
|
257
|
+
# @return[Hash] Decision properties for the callback by hook manager
|
258
|
+
def initialize_decision_properties(user_id, campaign, api_name, custom_variables = {}, variation_targeting_variables = {}, goal_identifier = '')
|
259
|
+
{
|
260
|
+
campaign_id: campaign['id'],
|
261
|
+
campaign_key: campaign['key'],
|
262
|
+
campaign_type: campaign['type'],
|
263
|
+
# campaign segmentation conditions
|
264
|
+
custom_variables: custom_variables,
|
265
|
+
# event name
|
266
|
+
event: Hooks::DECISION_TYPES['CAMPAIGN_DECISION'],
|
267
|
+
# goal tracked in case of track API
|
268
|
+
goal_identifier: goal_identifier,
|
269
|
+
# campaign whitelisting flag
|
270
|
+
is_forced_variation_enabled: campaign['isForcedVariationEnabled'] || false,
|
271
|
+
sdk_version: SDK_VERSION,
|
272
|
+
# API name which triggered the event
|
273
|
+
source: api_name,
|
274
|
+
# Passed in API
|
275
|
+
user_id: user_id,
|
276
|
+
# Campaign Whitelisting conditions
|
277
|
+
variation_targeting_variables: variation_targeting_variables,
|
278
|
+
is_user_whitelisted: false,
|
279
|
+
from_user_storage_service: false,
|
280
|
+
is_feature_enabled: true,
|
281
|
+
# VWO generated UUID based on passed UserId and Account ID
|
282
|
+
vwo_user_id: generator_for(user_id, @settings_file['accountId'])
|
283
|
+
}
|
284
|
+
end
|
285
|
+
|
286
|
+
# Add variation details to decision properties for hook manager
|
287
|
+
#
|
288
|
+
# @param[Hash] :campaign Campaign details
|
289
|
+
# @param[Hash] :variation Variation assigned to user
|
290
|
+
# @param[Hash] :decision Decision properties
|
291
|
+
# @return[Hash] :decision Decision properties
|
292
|
+
def add_variation_to_decision_properties(decision, campaign, variation)
|
293
|
+
if campaign['type'] == CampaignTypes::VISUAL_AB || campaign['type'] == CampaignTypes::FEATURE_TEST
|
294
|
+
decision[:variation_name] = variation['name']
|
295
|
+
decision[:variation_id] = variation['id']
|
296
|
+
end
|
297
|
+
decision[:is_feature_enabled] = variation['isFeatureEnabled'] if campaign['type'] == CampaignTypes::FEATURE_TEST
|
298
|
+
decision
|
299
|
+
end
|
300
|
+
|
301
|
+
# Get variation by murmur logic if pre segmentation pass
|
302
|
+
#
|
303
|
+
# @param[Boolean] :is_presegmentation The unique key assigned to User
|
304
|
+
# @param[Hash] :campaign Campaign hash for Unique campaign key
|
305
|
+
# @param[String] :user_id the unique ID assigned to User
|
306
|
+
# @param[String] :goal_identifier goal Identifier used in track API
|
307
|
+
# @param[Hash] :decision data containing campaign info passed to hooks manager
|
308
|
+
#
|
309
|
+
# @return[Hash]
|
310
|
+
def get_variation_if_presegmentation_applied(is_presegmentation, campaign, user_id, goal_identifier, decision)
|
311
|
+
return nil unless is_presegmentation
|
285
312
|
|
313
|
+
campaign_key = campaign['key']
|
314
|
+
variation = get_variation_allotted(user_id, campaign)
|
315
|
+
if variation && variation['name']
|
316
|
+
save_user_storage(user_id, campaign_key, campaign['type'], variation['name'], goal_identifier) if variation['name']
|
317
|
+
else
|
318
|
+
@logger.log(
|
319
|
+
LogLevelEnum::INFO,
|
320
|
+
'DECISION_NO_VARIATION_ALLOTED',
|
321
|
+
{
|
322
|
+
'{file}' => FILE,
|
323
|
+
'{campaignKey}' => campaign_key,
|
324
|
+
'{userId}' => user_id
|
325
|
+
}
|
326
|
+
)
|
286
327
|
end
|
287
328
|
|
288
329
|
if variation
|
289
|
-
|
290
|
-
decision[:variation_name] = variation['name']
|
291
|
-
decision[:variation_id] = variation['id']
|
292
|
-
if campaign['type'] == CampaignTypes::FEATURE_TEST
|
293
|
-
decision[:is_feature_enabled] = variation['isFeatureEnabled']
|
294
|
-
end
|
295
|
-
end
|
330
|
+
decision = add_variation_to_decision_properties(decision, campaign, variation)
|
296
331
|
@hooks_manager.execute(decision)
|
297
332
|
end
|
298
333
|
variation
|
@@ -309,37 +344,29 @@ class VWO
|
|
309
344
|
unless valid_value?(user_id)
|
310
345
|
@logger.log(
|
311
346
|
LogLevelEnum::ERROR,
|
312
|
-
|
347
|
+
'USER_ID_INVALID',
|
348
|
+
{
|
349
|
+
'{file}' => FILE,
|
350
|
+
'{userId}' => user_id
|
351
|
+
},
|
352
|
+
disable_logs
|
313
353
|
)
|
314
354
|
return
|
315
355
|
end
|
316
356
|
|
317
|
-
if @bucketer.user_part_of_campaign?(user_id, campaign)
|
318
|
-
|
319
|
-
|
320
|
-
LogLevelEnum::DEBUG,
|
321
|
-
format(
|
322
|
-
LogMessageEnum::DebugMessages::GOT_VARIATION_FOR_USER,
|
323
|
-
file: FILE,
|
324
|
-
variation_name: variation['name'],
|
325
|
-
user_id: user_id,
|
326
|
-
campaign_key: campaign['key'],
|
327
|
-
method: 'get_variation_allotted'
|
328
|
-
),
|
329
|
-
disable_logs
|
330
|
-
)
|
331
|
-
variation
|
357
|
+
if @bucketer.user_part_of_campaign?(user_id, campaign, true)
|
358
|
+
get_variation_of_campaign_for_user(user_id, campaign, disable_logs)
|
359
|
+
|
332
360
|
else
|
333
361
|
# not part of campaign
|
334
362
|
@logger.log(
|
335
|
-
LogLevelEnum::
|
336
|
-
|
337
|
-
|
338
|
-
file
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
),
|
363
|
+
LogLevelEnum::INFO,
|
364
|
+
'USER_NOT_PART_OF_CAMPAIGN',
|
365
|
+
{
|
366
|
+
'{file}' => FILE,
|
367
|
+
'{campaignKey}' => nil,
|
368
|
+
'{userId}' => user_id
|
369
|
+
},
|
343
370
|
disable_logs
|
344
371
|
)
|
345
372
|
nil
|
@@ -352,44 +379,36 @@ class VWO
|
|
352
379
|
# @param[Hash] :campaign The Campaign of which user is to be made a part of
|
353
380
|
# @return[Hash] Variation allotted to User
|
354
381
|
|
355
|
-
def get_variation_of_campaign_for_user(user_id, campaign)
|
356
|
-
|
357
|
-
@logger.log(
|
358
|
-
LogLevelEnum::ERROR,
|
359
|
-
format(
|
360
|
-
LogMessageEnum::ErrorMessages::INVALID_CAMPAIGN,
|
361
|
-
file: FILE,
|
362
|
-
method: 'get_variation_of_campaign_for_user'
|
363
|
-
)
|
364
|
-
)
|
365
|
-
return nil
|
366
|
-
end
|
367
|
-
|
368
|
-
variation = @bucketer.bucket_user_to_variation(user_id, campaign)
|
382
|
+
def get_variation_of_campaign_for_user(user_id, campaign, disable_logs = false)
|
383
|
+
variation = @bucketer.bucket_user_to_variation(user_id, campaign, disable_logs)
|
369
384
|
|
370
385
|
if variation && variation['name']
|
371
386
|
@logger.log(
|
372
387
|
LogLevelEnum::INFO,
|
373
|
-
|
374
|
-
|
375
|
-
file
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
388
|
+
'USER_VARIATION_ALLOCATION_STATUS',
|
389
|
+
{
|
390
|
+
'{file}' => FILE,
|
391
|
+
'{status}' => variation ? "got variation: + #{variation['name']}" : 'did not get any variation',
|
392
|
+
'{userId}' => user_id,
|
393
|
+
'{campaignKey}' => campaign['key']
|
394
|
+
},
|
395
|
+
disable_logs
|
380
396
|
)
|
381
397
|
return variation
|
382
398
|
end
|
383
399
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
400
|
+
if campaign
|
401
|
+
@logger.log(
|
402
|
+
LogLevelEnum::INFO,
|
403
|
+
'DECISION_NO_VARIATION_ALLOTED',
|
404
|
+
{
|
405
|
+
'{file}' => FILE,
|
406
|
+
'{userId}' => user_id,
|
407
|
+
'{campaignKey}' => campaign['key']
|
408
|
+
},
|
409
|
+
disable_logs
|
391
410
|
)
|
392
|
-
|
411
|
+
end
|
393
412
|
nil
|
394
413
|
end
|
395
414
|
|
@@ -402,11 +421,12 @@ class VWO
|
|
402
421
|
# @param[Boolean] :disable_logs optional: disable logs if True
|
403
422
|
# @return[Boolean] true if found otherwise false
|
404
423
|
|
405
|
-
def save_user_storage(user_id, campaign_key,
|
424
|
+
def save_user_storage(user_id, campaign_key, _campaign_type, variation_name, goal_identifier, disable_logs = false)
|
406
425
|
unless @user_storage_service
|
407
426
|
@logger.log(
|
408
427
|
LogLevelEnum::DEBUG,
|
409
|
-
|
428
|
+
'USER_STORAGE_SERVICE_NOT_CONFIGURED',
|
429
|
+
{ '{file}' => FILE },
|
410
430
|
disable_logs
|
411
431
|
)
|
412
432
|
return false
|
@@ -415,40 +435,41 @@ class VWO
|
|
415
435
|
new_campaign_user_mapping['campaign_key'] = campaign_key
|
416
436
|
new_campaign_user_mapping['user_id'] = user_id
|
417
437
|
new_campaign_user_mapping['variation_name'] = variation_name
|
418
|
-
|
419
|
-
new_campaign_user_mapping['goal_identifier'] = goal_identifier
|
420
|
-
end
|
438
|
+
new_campaign_user_mapping['goal_identifier'] = goal_identifier unless goal_identifier.empty?
|
421
439
|
|
422
440
|
@user_storage_service.set(new_campaign_user_mapping)
|
423
441
|
|
424
442
|
@logger.log(
|
425
443
|
LogLevelEnum::INFO,
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
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
|
-
),
|
444
|
+
'SETTING_DATA_USER_STORAGE_SERVICE',
|
445
|
+
{
|
446
|
+
'{file}' => FILE,
|
447
|
+
'{userId}' => user_id,
|
448
|
+
'{campaignKey}' => campaign_key
|
449
|
+
},
|
440
450
|
disable_logs
|
441
451
|
)
|
442
452
|
true
|
443
|
-
rescue StandardError
|
453
|
+
rescue StandardError => e
|
444
454
|
@logger.log(
|
445
455
|
LogLevelEnum::ERROR,
|
446
|
-
|
456
|
+
'USER_STORAGE_SERVICE_SET_FAILED',
|
457
|
+
{
|
458
|
+
'{file}' => FILE,
|
459
|
+
'{userId}' => user_id,
|
460
|
+
'{error}' => e.message
|
461
|
+
},
|
447
462
|
disable_logs
|
448
463
|
)
|
449
464
|
false
|
450
465
|
end
|
451
466
|
|
467
|
+
def update_goal_identifier(user_id, campaign, variation, goal_identifier)
|
468
|
+
updated_goal_identifier = variation['goal_identifier']
|
469
|
+
updated_goal_identifier += VWO_DELIMITER + goal_identifier
|
470
|
+
save_user_storage(user_id, campaign['key'], campaign['name'], variation['name'], updated_goal_identifier) if variation['name']
|
471
|
+
end
|
472
|
+
|
452
473
|
private
|
453
474
|
|
454
475
|
# Evaluate all the variations in the campaign to find
|
@@ -462,20 +483,18 @@ class VWO
|
|
462
483
|
#
|
463
484
|
# @return[Hash]
|
464
485
|
|
465
|
-
def evaluate_whitelisting(user_id, campaign,
|
466
|
-
if campaign.key?('isUserListEnabled') && campaign[
|
467
|
-
vwo_user_id = generator_for(user_id, @settings_file['accountId'])
|
486
|
+
def evaluate_whitelisting(user_id, campaign, _api_name, campaign_key, variation_targeting_variables = {}, disable_logs = false)
|
487
|
+
if campaign.key?('isUserListEnabled') && campaign['isUserListEnabled']
|
488
|
+
vwo_user_id = generator_for(user_id, @settings_file['accountId'], true)
|
468
489
|
if variation_targeting_variables.nil?
|
469
490
|
variation_targeting_variables = { _vwo_user_id: vwo_user_id }
|
470
491
|
else
|
471
492
|
variation_targeting_variables[:_vwo_user_id] = vwo_user_id
|
472
493
|
end
|
494
|
+
elsif variation_targeting_variables.nil?
|
495
|
+
variation_targeting_variables = { _vwo_user_id: user_id }
|
473
496
|
else
|
474
|
-
|
475
|
-
variation_targeting_variables = { _vwo_user_id: user_id }
|
476
|
-
else
|
477
|
-
variation_targeting_variables[:_vwo_user_id] = user_id
|
478
|
-
end
|
497
|
+
variation_targeting_variables[:_vwo_user_id] = user_id
|
479
498
|
end
|
480
499
|
targeted_variations = []
|
481
500
|
|
@@ -490,36 +509,37 @@ class VWO
|
|
490
509
|
status = StatusEnum::FAILED
|
491
510
|
end
|
492
511
|
@logger.log(
|
493
|
-
LogLevelEnum::
|
494
|
-
|
495
|
-
|
496
|
-
file
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
512
|
+
LogLevelEnum::INFO,
|
513
|
+
'SEGMENTATION_STATUS',
|
514
|
+
{
|
515
|
+
'{file}' => FILE,
|
516
|
+
'{campaignKey}' => campaign_key,
|
517
|
+
'{userId}' => user_id,
|
518
|
+
'{customVariables}' => variation_targeting_variables,
|
519
|
+
'{status}' => status,
|
520
|
+
'{segmentationType}' => SegmentationTypeEnum::WHITELISTING,
|
521
|
+
'{variation}' => if status == StatusEnum::PASSED
|
522
|
+
campaign['type'] == CampaignTypes::FEATURE_ROLLOUT ? 'and hence becomes part of the rollout' : "#{variation['name']} and hence becomes part of the rollout"
|
523
|
+
else
|
524
|
+
''
|
525
|
+
end
|
526
|
+
},
|
505
527
|
disable_logs
|
506
528
|
)
|
507
529
|
else
|
508
530
|
@logger.log(
|
509
531
|
LogLevelEnum::DEBUG,
|
510
|
-
|
511
|
-
|
512
|
-
file
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
),
|
532
|
+
'SEGMENTATION_SKIPPED',
|
533
|
+
{
|
534
|
+
'{file}' => FILE,
|
535
|
+
'{campaignKey}' => campaign_key,
|
536
|
+
'{userId}' => user_id,
|
537
|
+
'{variation}' => campaign['type'] == CampaignTypes::FEATURE_ROLLOUT ? '' : "for variation:#{variation['name']}"
|
538
|
+
},
|
518
539
|
disable_logs
|
519
540
|
)
|
520
541
|
end
|
521
542
|
end
|
522
|
-
|
523
543
|
if targeted_variations.length > 1
|
524
544
|
targeted_variations_deep_clone = Marshal.load(Marshal.dump(targeted_variations))
|
525
545
|
scale_variation_weights(targeted_variations_deep_clone)
|
@@ -541,7 +561,8 @@ class VWO
|
|
541
561
|
targeted_variations_deep_clone,
|
542
562
|
@bucketer.get_bucket_value_for_user(
|
543
563
|
user_id,
|
544
|
-
campaign
|
564
|
+
campaign,
|
565
|
+
disable_logs
|
545
566
|
)
|
546
567
|
)
|
547
568
|
else
|
@@ -570,7 +591,7 @@ class VWO
|
|
570
591
|
end
|
571
592
|
|
572
593
|
def scale_campaigns_weight(campaigns)
|
573
|
-
normalize_weight = 100/campaigns.length
|
594
|
+
normalize_weight = 100 / campaigns.length
|
574
595
|
campaigns.each do |campaign|
|
575
596
|
campaign['weight'] = normalize_weight
|
576
597
|
end
|
@@ -587,28 +608,36 @@ class VWO
|
|
587
608
|
unless @user_storage_service
|
588
609
|
@logger.log(
|
589
610
|
LogLevelEnum::DEBUG,
|
590
|
-
|
611
|
+
'USER_STORAGE_SERVICE_NOT_CONFIGURED',
|
612
|
+
{ '{file}' => FILE },
|
591
613
|
disable_logs
|
592
614
|
)
|
593
615
|
return false
|
594
616
|
end
|
595
617
|
|
596
618
|
data = @user_storage_service.get(user_id, campaign_key)
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
619
|
+
if data
|
620
|
+
@logger.log(
|
621
|
+
LogLevelEnum::INFO,
|
622
|
+
'GETTING_DATA_USER_STORAGE_SERVICE',
|
623
|
+
{
|
624
|
+
'{file}' => FILE,
|
625
|
+
'{userId}' => user_id,
|
626
|
+
'{campaignKey}' => campaign_key
|
627
|
+
},
|
628
|
+
disable_logs
|
629
|
+
)
|
630
|
+
end
|
607
631
|
data
|
608
|
-
rescue StandardError
|
632
|
+
rescue StandardError => e
|
609
633
|
@logger.log(
|
610
634
|
LogLevelEnum::ERROR,
|
611
|
-
|
635
|
+
'USER_STORAGE_SERVICE_GET_FAILED',
|
636
|
+
{
|
637
|
+
'{file}' => FILE,
|
638
|
+
'{userId}' => user_id,
|
639
|
+
'{error}' => e.message
|
640
|
+
},
|
612
641
|
disable_logs
|
613
642
|
)
|
614
643
|
false
|
@@ -623,21 +652,10 @@ class VWO
|
|
623
652
|
#
|
624
653
|
# @return[Object, nil] if found then variation settings object otherwise None
|
625
654
|
|
626
|
-
def get_stored_variation(
|
655
|
+
def get_stored_variation(_user_id, campaign_key, user_campaign_map, _disable_logs = false)
|
627
656
|
return unless user_campaign_map['campaign_key'] == campaign_key
|
628
657
|
|
629
658
|
variation_name = user_campaign_map['variation_name']
|
630
|
-
@logger.log(
|
631
|
-
LogLevelEnum::DEBUG,
|
632
|
-
format(
|
633
|
-
LogMessageEnum::DebugMessages::GETTING_STORED_VARIATION,
|
634
|
-
file: FILE,
|
635
|
-
campaign_key: campaign_key,
|
636
|
-
user_id: user_id,
|
637
|
-
variation_name: variation_name
|
638
|
-
),
|
639
|
-
disable_logs
|
640
|
-
)
|
641
659
|
|
642
660
|
get_campaign_variation(
|
643
661
|
@settings_file,
|
@@ -655,66 +673,58 @@ class VWO
|
|
655
673
|
# @param[Boolean] :disable_logs optional: disable logs if True
|
656
674
|
#
|
657
675
|
# @return[Boolean]
|
658
|
-
def
|
676
|
+
def presegmentation?(campaign, user_id, custom_variables, _api_name, disable_logs = false)
|
659
677
|
campaign_key = campaign['key']
|
660
678
|
segments = get_segments(campaign)
|
661
679
|
is_valid_segments = valid_value?(segments)
|
662
680
|
|
663
681
|
if is_valid_segments
|
664
|
-
|
665
|
-
|
666
|
-
LogLevelEnum::INFO,
|
667
|
-
format(
|
668
|
-
LogMessageEnum::InfoMessages::NO_CUSTOM_VARIABLES,
|
669
|
-
file: FILE,
|
670
|
-
campaign_key: campaign_key,
|
671
|
-
user_id: user_id,
|
672
|
-
api_name: api_name
|
673
|
-
),
|
674
|
-
disable_logs
|
675
|
-
)
|
676
|
-
custom_variables = {}
|
677
|
-
end
|
678
|
-
unless @segment_evaluator.evaluate(campaign_key, user_id, segments, custom_variables, disable_logs)
|
679
|
-
@logger.log(
|
680
|
-
LogLevelEnum::INFO,
|
681
|
-
format(
|
682
|
-
LogMessageEnum::InfoMessages::USER_FAILED_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
|
-
return false
|
691
|
-
end
|
682
|
+
custom_variables ||= {}
|
683
|
+
response = @segment_evaluator.evaluate(campaign_key, user_id, segments, custom_variables, disable_logs)
|
692
684
|
@logger.log(
|
693
685
|
LogLevelEnum::INFO,
|
694
|
-
|
695
|
-
|
696
|
-
file
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
686
|
+
'SEGMENTATION_STATUS',
|
687
|
+
{
|
688
|
+
'{file}' => FILE,
|
689
|
+
'{userId}' => user_id,
|
690
|
+
'{status}' => response ? 'passed' : 'failed',
|
691
|
+
'{campaignKey}' => campaign_key,
|
692
|
+
'{customVariables}' => custom_variables,
|
693
|
+
'{segmentationType}' => 'pre-segmentation',
|
694
|
+
'{variation}' => ''
|
695
|
+
},
|
701
696
|
disable_logs
|
702
697
|
)
|
698
|
+
return response
|
703
699
|
else
|
704
700
|
@logger.log(
|
705
|
-
LogLevelEnum::
|
706
|
-
|
707
|
-
|
708
|
-
file
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
),
|
701
|
+
LogLevelEnum::DEBUG,
|
702
|
+
'SEGMENTATION_SKIPPED',
|
703
|
+
{
|
704
|
+
'{file}' => FILE,
|
705
|
+
'{userId}' => user_id,
|
706
|
+
'{campaignKey}' => campaign_key,
|
707
|
+
'{variation}' => ''
|
708
|
+
},
|
714
709
|
disable_logs
|
715
710
|
)
|
716
711
|
end
|
717
712
|
true
|
713
|
+
rescue StandardError => e
|
714
|
+
@logger.log(
|
715
|
+
LogLevelEnum::ERROR,
|
716
|
+
'SEGMENTATION_ERROR',
|
717
|
+
{
|
718
|
+
'{file}' => FILE,
|
719
|
+
'{userId}' => user_id,
|
720
|
+
'{campaignKey}' => campaign_key,
|
721
|
+
'{variation}' => '',
|
722
|
+
'{customVariables}' => custom_variables,
|
723
|
+
'{err}' => e.message
|
724
|
+
},
|
725
|
+
disable_logs
|
726
|
+
)
|
727
|
+
false
|
718
728
|
end
|
719
729
|
|
720
730
|
# Finds and returns eligible campaigns from group_campaigns.
|
@@ -729,11 +739,11 @@ class VWO
|
|
729
739
|
eligible_campaigns = []
|
730
740
|
|
731
741
|
group_campaigns.each do |campaign|
|
732
|
-
if called_campaign[
|
742
|
+
if called_campaign['id'] == campaign['id'] || presegmentation?(campaign, user_id, custom_variables, '', true) && @bucketer.user_part_of_campaign?(user_id, campaign, true)
|
733
743
|
eligible_campaigns.push(campaign)
|
734
744
|
end
|
735
745
|
end
|
736
|
-
|
746
|
+
eligible_campaigns
|
737
747
|
end
|
738
748
|
|
739
749
|
# Finds and returns the winner campaign from eligible_campaigns list.
|
@@ -743,14 +753,12 @@ class VWO
|
|
743
753
|
#
|
744
754
|
# @return[Hash]
|
745
755
|
def get_winner_campaign(user_id, eligible_campaigns, group_id)
|
746
|
-
if eligible_campaigns.length == 1
|
747
|
-
return eligible_campaigns[0]
|
748
|
-
end
|
756
|
+
return eligible_campaigns[0] if eligible_campaigns.length == 1
|
749
757
|
|
750
758
|
eligible_campaigns = scale_campaigns_weight(eligible_campaigns)
|
751
759
|
eligible_campaigns = set_campaign_allocation(eligible_campaigns)
|
752
760
|
bucket_value = @bucketer.get_bucket_value_for_user(user_id, {}, group_id, true)
|
753
|
-
|
761
|
+
@bucketer.get_campaign_using_range(bucket_value, eligible_campaigns)
|
754
762
|
end
|
755
763
|
|
756
764
|
# Get campaign keys of all eligible Campaigns.
|
@@ -761,7 +769,7 @@ class VWO
|
|
761
769
|
def get_eligible_campaigns_key(eligible_campaigns)
|
762
770
|
eligible_campaigns_key = []
|
763
771
|
eligible_campaigns.each do |campaign|
|
764
|
-
eligible_campaigns_key.push(campaign[
|
772
|
+
eligible_campaigns_key.push(campaign['key'])
|
765
773
|
end
|
766
774
|
eligible_campaigns_key
|
767
775
|
end
|
@@ -775,9 +783,7 @@ class VWO
|
|
775
783
|
def get_non_eligible_campaigns_key(eligible_campaigns, group_campaigns)
|
776
784
|
non_eligible_campaigns_key = []
|
777
785
|
group_campaigns.each do |campaign|
|
778
|
-
unless eligible_campaigns.include? campaign
|
779
|
-
non_eligible_campaigns_key.push(campaign["key"])
|
780
|
-
end
|
786
|
+
non_eligible_campaigns_key.push(campaign['key']) unless eligible_campaigns.include? campaign
|
781
787
|
end
|
782
788
|
non_eligible_campaigns_key
|
783
789
|
end
|
@@ -792,54 +798,54 @@ class VWO
|
|
792
798
|
# @param[Boolean] :disable_logs optional: disable logs if True
|
793
799
|
# @return[Boolean]
|
794
800
|
|
795
|
-
def
|
801
|
+
def whitelisting_or_storage_for_grouped_campaigns?(user_id, called_campaign, group_campaigns, group_name, variation_targeting_variables, disable_logs = false)
|
796
802
|
group_campaigns.each do |campaign|
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
803
|
+
next unless called_campaign['id'] != campaign['id']
|
804
|
+
|
805
|
+
targeted_variation = evaluate_whitelisting(
|
806
|
+
user_id,
|
807
|
+
campaign,
|
808
|
+
'',
|
809
|
+
campaign['key'],
|
810
|
+
variation_targeting_variables,
|
811
|
+
true
|
812
|
+
)
|
813
|
+
next unless targeted_variation
|
814
|
+
|
815
|
+
@logger.log(
|
816
|
+
LogLevelEnum::INFO,
|
817
|
+
'OTHER_CAMPAIGN_SATISFIES_WHITELISTING_STORAGE',
|
818
|
+
{
|
819
|
+
'{file}' => FILE,
|
820
|
+
'{campaignKey}' => campaign['key'],
|
821
|
+
'{userId}' => user_id,
|
822
|
+
'{groupName}' => group_name,
|
823
|
+
'{type}' => 'whitelisting'
|
824
|
+
},
|
825
|
+
disable_logs
|
826
|
+
)
|
827
|
+
return true
|
822
828
|
end
|
823
829
|
|
824
830
|
group_campaigns.each do |campaign|
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
831
|
+
next unless called_campaign['id'] != campaign['id']
|
832
|
+
|
833
|
+
user_storage_data = get_user_storage(user_id, campaign['key'], true)
|
834
|
+
next unless user_storage_data
|
835
|
+
|
836
|
+
@logger.log(
|
837
|
+
LogLevelEnum::INFO,
|
838
|
+
'OTHER_CAMPAIGN_SATISFIES_WHITELISTING_STORAGE',
|
839
|
+
{
|
840
|
+
'{file}' => FILE,
|
841
|
+
'{campaignKey}' => campaign['key'],
|
842
|
+
'{userId}' => user_id,
|
843
|
+
'{groupName}' => group_name,
|
844
|
+
'{type}' => 'user storag'
|
845
|
+
},
|
846
|
+
disable_logs
|
847
|
+
)
|
848
|
+
return true
|
843
849
|
end
|
844
850
|
false
|
845
851
|
end
|
@@ -872,28 +878,21 @@ class VWO
|
|
872
878
|
|
873
879
|
@logger.log(
|
874
880
|
LogLevelEnum::INFO,
|
875
|
-
|
876
|
-
|
877
|
-
file
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
),
|
881
|
+
'SEGMENTATION_STATUS',
|
882
|
+
{
|
883
|
+
'{file}' => FILE,
|
884
|
+
'{campaignKey}' => campaign_key,
|
885
|
+
'{userId}' => user_id,
|
886
|
+
'{customVariables}' => variation_targeting_variables || {},
|
887
|
+
'{status}' => status,
|
888
|
+
'{segmentationType}' => SegmentationTypeEnum::WHITELISTING,
|
889
|
+
'{variation}' => status == StatusEnum::PASSED && campaign['type'] != CampaignTypes::FEATURE_ROLLOUT ? "for variation:#{variation['name']}" : ' '
|
890
|
+
},
|
886
891
|
disable_logs
|
887
892
|
)
|
888
893
|
|
889
894
|
if variation
|
890
|
-
|
891
|
-
decision[:variation_name] = variation['name']
|
892
|
-
decision[:variation_id] = variation['id']
|
893
|
-
if campaign['type'] == CampaignTypes::FEATURE_TEST
|
894
|
-
decision[:is_feature_enabled] = variation['isFeatureEnabled']
|
895
|
-
end
|
896
|
-
end
|
895
|
+
decision = add_variation_to_decision_properties(decision, campaign, variation)
|
897
896
|
decision[:is_user_whitelisted] = true
|
898
897
|
@hooks_manager.execute(decision)
|
899
898
|
end
|
@@ -901,20 +900,20 @@ class VWO
|
|
901
900
|
return variation if variation && variation['name']
|
902
901
|
else
|
903
902
|
@logger.log(
|
904
|
-
LogLevelEnum::
|
905
|
-
|
906
|
-
|
907
|
-
file
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
903
|
+
LogLevelEnum::DEBUG,
|
904
|
+
'WHITELISTING_SKIPPED',
|
905
|
+
{
|
906
|
+
'{file}' => FILE,
|
907
|
+
'{campaignKey}' => campaign_key,
|
908
|
+
'{userId}' => user_id,
|
909
|
+
'{reason}' => '',
|
910
|
+
'{variation}' => ''
|
911
|
+
},
|
912
912
|
disable_logs
|
913
913
|
)
|
914
914
|
end
|
915
915
|
nil
|
916
916
|
end
|
917
|
-
|
918
917
|
end
|
919
918
|
end
|
920
919
|
end
|