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