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
data/lib/vwo.rb
CHANGED
@@ -25,6 +25,7 @@ require_relative 'vwo/utils/feature'
|
|
25
25
|
require_relative 'vwo/utils/custom_dimensions'
|
26
26
|
require_relative 'vwo/utils/utility'
|
27
27
|
require_relative 'vwo/utils/data_location_manager'
|
28
|
+
require_relative 'vwo/utils/log_message'
|
28
29
|
require_relative 'vwo/constants'
|
29
30
|
require_relative 'vwo/core/variation_decider'
|
30
31
|
require_relative 'vwo/services/batch_events_dispatcher'
|
@@ -33,8 +34,9 @@ require_relative 'vwo/services/usage_stats'
|
|
33
34
|
|
34
35
|
# VWO main file
|
35
36
|
class VWO
|
36
|
-
attr_accessor :is_instance_valid, :
|
37
|
+
attr_accessor :is_instance_valid, :logging, :settings_file_manager, :variation_decider
|
37
38
|
attr_reader :usage_stats
|
39
|
+
|
38
40
|
include Enums
|
39
41
|
include Utils::Validations
|
40
42
|
include Utils::Feature
|
@@ -66,14 +68,16 @@ class VWO
|
|
66
68
|
settings_file = nil,
|
67
69
|
options = {}
|
68
70
|
)
|
71
|
+
@logger = Utils::Logger
|
72
|
+
@logger.set_api_name(ApiMethods::LAUNCH)
|
69
73
|
options = convert_to_symbol_hash(options)
|
70
74
|
@is_opted_out = false
|
71
75
|
@account_id = account_id
|
72
76
|
@sdk_key = sdk_key
|
73
77
|
@user_storage = user_storage
|
74
78
|
@is_development_mode = is_development_mode
|
75
|
-
@
|
76
|
-
@
|
79
|
+
@logging = VWO::Logger.get_instance(logger)
|
80
|
+
@logging.instance.level = options[:log_level] if (0..5).include?(options[:log_level])
|
77
81
|
usage_stats = {}
|
78
82
|
|
79
83
|
usage_stats[:cl] = 1 if logger
|
@@ -82,11 +86,19 @@ class VWO
|
|
82
86
|
usage_stats[:ig] = 1 if options.key?(:integrations)
|
83
87
|
usage_stats[:eb] = 1 if options.key?(:batch_events)
|
84
88
|
|
89
|
+
unless validate_sdk_config?(@user_storage, is_development_mode, ApiMethods::LAUNCH)
|
90
|
+
@is_instance_valid = false
|
91
|
+
return
|
92
|
+
end
|
93
|
+
|
85
94
|
@settings_file_manager = VWO::Services::SettingsFileManager.new(@account_id, @sdk_key)
|
86
95
|
unless valid_settings_file?(get_settings(settings_file))
|
87
96
|
@logger.log(
|
88
97
|
LogLevelEnum::ERROR,
|
89
|
-
|
98
|
+
'SETTINGS_FILE_CORRUPTED',
|
99
|
+
{
|
100
|
+
'{file}' => FILE
|
101
|
+
}
|
90
102
|
)
|
91
103
|
@is_instance_valid = false
|
92
104
|
return
|
@@ -99,10 +111,13 @@ class VWO
|
|
99
111
|
else
|
100
112
|
@logger.log(
|
101
113
|
LogLevelEnum::ERROR,
|
102
|
-
|
103
|
-
|
104
|
-
file
|
105
|
-
|
114
|
+
'CONFIG_PARAMETER_INVALID',
|
115
|
+
{
|
116
|
+
'{file}' => FILE,
|
117
|
+
'{parameter}' => 'goal_type_to_track',
|
118
|
+
'{type}' => 'string(REVENUE, CUSTOM, ALL)',
|
119
|
+
'{api}' => 'init'
|
120
|
+
}
|
106
121
|
)
|
107
122
|
@is_instance_valid = false
|
108
123
|
return
|
@@ -114,42 +129,21 @@ class VWO
|
|
114
129
|
@is_instance_valid = true
|
115
130
|
@config = VWO::Services::SettingsFileProcessor.new(get_settings)
|
116
131
|
|
117
|
-
@logger.log(
|
118
|
-
LogLevelEnum::DEBUG,
|
119
|
-
format(
|
120
|
-
LogMessageEnum::DebugMessages::VALID_CONFIGURATION,
|
121
|
-
file: FILE
|
122
|
-
)
|
123
|
-
)
|
124
|
-
|
125
132
|
# Process the settings file
|
126
133
|
@config.process_settings_file
|
127
134
|
@settings_file = @config.get_settings_file
|
128
|
-
DataLocationManager.get_instance
|
135
|
+
DataLocationManager.get_instance.set_settings(@settings_file)
|
129
136
|
|
130
137
|
@usage_stats = VWO::Services::UsageStats.new(usage_stats, @is_development_mode)
|
131
138
|
|
132
139
|
if options.key?(:batch_events)
|
133
140
|
if options[:batch_events].is_a?(Hash)
|
134
|
-
unless
|
141
|
+
unless valid_batch_event_settings(options[:batch_events], ApiMethods::LAUNCH)
|
135
142
|
@is_instance_valid = false
|
136
143
|
return
|
137
144
|
end
|
138
|
-
@batch_event_dispatcher = VWO::Services::BatchEventsDispatcher.new
|
139
|
-
|
140
|
-
@batch_event_dispatcher.dispatch(
|
141
|
-
{
|
142
|
-
ev: events
|
143
|
-
},
|
144
|
-
callback,
|
145
|
-
{
|
146
|
-
a: @account_id,
|
147
|
-
sd: SDK_NAME,
|
148
|
-
sv: SDK_VERSION,
|
149
|
-
env: @sdk_key
|
150
|
-
}.merge(@usage_stats.usage_stats)
|
151
|
-
)
|
152
|
-
end
|
145
|
+
@batch_event_dispatcher = VWO::Services::BatchEventsDispatcher.new(@is_development_mode)
|
146
|
+
|
153
147
|
@batch_events_queue = VWO::Services::BatchEventsQueue.new(
|
154
148
|
options[:batch_events].merge(
|
155
149
|
{
|
@@ -163,10 +157,13 @@ class VWO
|
|
163
157
|
else
|
164
158
|
@logger.log(
|
165
159
|
LogLevelEnum::ERROR,
|
166
|
-
|
167
|
-
|
168
|
-
file
|
169
|
-
|
160
|
+
'CONFIG_PARAMETER_INVALID',
|
161
|
+
{
|
162
|
+
'{file}' => FILE,
|
163
|
+
'{parameter}' => 'batch_events',
|
164
|
+
'{type}' => 'hash',
|
165
|
+
'{api}' => 'init'
|
166
|
+
}
|
170
167
|
)
|
171
168
|
@is_instance_valid = false
|
172
169
|
return
|
@@ -176,25 +173,29 @@ class VWO
|
|
176
173
|
# Assign VariationDecider to VWO
|
177
174
|
@variation_decider = VWO::Core::VariationDecider.new(@settings_file, user_storage, options)
|
178
175
|
|
179
|
-
if is_development_mode
|
180
|
-
@logger.log(
|
181
|
-
LogLevelEnum::DEBUG,
|
182
|
-
format(
|
183
|
-
LogMessageEnum::DebugMessages::SET_DEVELOPMENT_MODE,
|
184
|
-
file: FILE
|
185
|
-
)
|
186
|
-
)
|
187
|
-
end
|
188
176
|
# Assign event dispatcher
|
189
177
|
@event_dispatcher = VWO::Services::EventDispatcher.new(is_development_mode)
|
190
178
|
|
191
179
|
# Successfully initialized VWO SDK
|
192
180
|
@logger.log(
|
193
|
-
LogLevelEnum::
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
181
|
+
LogLevelEnum::INFO,
|
182
|
+
'SDK_INITIALIZED',
|
183
|
+
{ '{file}' => FILE }
|
184
|
+
)
|
185
|
+
end
|
186
|
+
|
187
|
+
def dispatcher(events, callback)
|
188
|
+
@batch_event_dispatcher.dispatch(
|
189
|
+
{
|
190
|
+
ev: events
|
191
|
+
},
|
192
|
+
callback,
|
193
|
+
{
|
194
|
+
a: @account_id,
|
195
|
+
sd: SDK_NAME,
|
196
|
+
sv: SDK_VERSION,
|
197
|
+
env: @sdk_key
|
198
|
+
}.merge(@usage_stats.usage_stats)
|
198
199
|
)
|
199
200
|
end
|
200
201
|
|
@@ -211,19 +212,17 @@ class VWO
|
|
211
212
|
|
212
213
|
# VWO get_settings method to get settings for a particular account_id
|
213
214
|
def get_and_update_settings_file
|
214
|
-
|
215
|
-
if
|
216
|
-
return false
|
217
|
-
end
|
215
|
+
@logger.set_api_name(ApiMethods::GET_AND_UPDATE_SETTINGS_FILE)
|
216
|
+
return false if opted_out?(ApiMethods::GET_AND_UPDATE_SETTINGS_FILE)
|
218
217
|
|
219
218
|
unless @is_instance_valid
|
220
219
|
@logger.log(
|
221
220
|
LogLevelEnum::ERROR,
|
222
|
-
|
223
|
-
|
224
|
-
file
|
225
|
-
|
226
|
-
|
221
|
+
'CONFIG_CORRUPTED',
|
222
|
+
{
|
223
|
+
'{file}' => FILE,
|
224
|
+
'{api}' => ApiMethods::GET_AND_UPDATE_SETTINGS_FILE
|
225
|
+
}
|
227
226
|
)
|
228
227
|
return false
|
229
228
|
end
|
@@ -232,12 +231,12 @@ class VWO
|
|
232
231
|
latest_settings = JSON.parse(latest_settings)
|
233
232
|
if latest_settings == @settings_file
|
234
233
|
@logger.log(
|
235
|
-
LogLevelEnum::
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
234
|
+
LogLevelEnum::DEBUG,
|
235
|
+
'SETTINGS_FILE_PROCESSED',
|
236
|
+
{
|
237
|
+
'{file}' => FILE,
|
238
|
+
'{accountId}' => @settings_file['accountId']
|
239
|
+
}
|
241
240
|
)
|
242
241
|
end
|
243
242
|
|
@@ -247,12 +246,11 @@ class VWO
|
|
247
246
|
rescue StandardError => e
|
248
247
|
@logger.log(
|
249
248
|
LogLevelEnum::ERROR,
|
250
|
-
|
251
|
-
|
252
|
-
file
|
253
|
-
|
254
|
-
|
255
|
-
)
|
249
|
+
"({file}): {api} API error: #{e.message}",
|
250
|
+
{
|
251
|
+
'{file}' => FILE,
|
252
|
+
'{api}' => ApiMethods::GET_AND_UPDATE_SETTINGS_FILE
|
253
|
+
}
|
256
254
|
)
|
257
255
|
nil
|
258
256
|
end
|
@@ -275,18 +273,17 @@ class VWO
|
|
275
273
|
# otherwise null in case of user not becoming part
|
276
274
|
|
277
275
|
def activate(campaign_key, user_id, options = {})
|
278
|
-
|
279
|
-
|
280
|
-
end
|
276
|
+
@logger.set_api_name(ApiMethods::ACTIVATE)
|
277
|
+
return nil if opted_out?(ApiMethods::ACTIVATE)
|
281
278
|
|
282
279
|
unless @is_instance_valid
|
283
280
|
@logger.log(
|
284
281
|
LogLevelEnum::ERROR,
|
285
|
-
|
286
|
-
|
287
|
-
file
|
288
|
-
|
289
|
-
|
282
|
+
'CONFIG_CORRUPTED',
|
283
|
+
{
|
284
|
+
'{file}' => FILE,
|
285
|
+
'{api}' => ApiMethods::ACTIVATE
|
286
|
+
}
|
290
287
|
)
|
291
288
|
return
|
292
289
|
end
|
@@ -298,14 +295,14 @@ class VWO
|
|
298
295
|
|
299
296
|
# Validate input parameters
|
300
297
|
unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables)) &&
|
301
|
-
|
298
|
+
(variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables))
|
302
299
|
@logger.log(
|
303
300
|
LogLevelEnum::ERROR,
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
301
|
+
'API_BAD_PARAMETERS',
|
302
|
+
{
|
303
|
+
'{file}' => FILE,
|
304
|
+
'{api}' => ApiMethods::ACTIVATE
|
305
|
+
}
|
309
306
|
)
|
310
307
|
return
|
311
308
|
end
|
@@ -317,13 +314,13 @@ class VWO
|
|
317
314
|
unless campaign && campaign['status'] == STATUS_RUNNING
|
318
315
|
# Log Campaign as invalid
|
319
316
|
@logger.log(
|
320
|
-
LogLevelEnum::
|
321
|
-
|
322
|
-
|
323
|
-
file
|
324
|
-
|
325
|
-
|
326
|
-
|
317
|
+
LogLevelEnum::WARNING,
|
318
|
+
'CAMPAIGN_NOT_RUNNING',
|
319
|
+
{
|
320
|
+
'{file}' => FILE,
|
321
|
+
'{campaignKey}' => campaign_key,
|
322
|
+
'{api}' => ApiMethods::ACTIVATE
|
323
|
+
}
|
327
324
|
)
|
328
325
|
return
|
329
326
|
end
|
@@ -335,14 +332,14 @@ class VWO
|
|
335
332
|
if campaign_type != CampaignTypes::VISUAL_AB
|
336
333
|
@logger.log(
|
337
334
|
LogLevelEnum::ERROR,
|
338
|
-
|
339
|
-
|
340
|
-
file
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
335
|
+
'API_NOT_APPLICABLE',
|
336
|
+
{
|
337
|
+
'{file}' => FILE,
|
338
|
+
'{api}' => ApiMethods::ACTIVATE,
|
339
|
+
'{userId}' => user_id,
|
340
|
+
'{campaignKey}' => campaign_key,
|
341
|
+
'{campaignType}' => campaign_type
|
342
|
+
}
|
346
343
|
)
|
347
344
|
return
|
348
345
|
end
|
@@ -360,20 +357,9 @@ class VWO
|
|
360
357
|
)
|
361
358
|
|
362
359
|
# Check if variation_name has been assigned
|
363
|
-
if variation.nil?
|
364
|
-
@logger.log(
|
365
|
-
LogLevelEnum::INFO,
|
366
|
-
format(
|
367
|
-
LogMessageEnum::InfoMessages::INVALID_VARIATION_KEY,
|
368
|
-
file: FILE,
|
369
|
-
user_id: user_id,
|
370
|
-
campaign_key: campaign_key
|
371
|
-
)
|
372
|
-
)
|
373
|
-
return
|
374
|
-
end
|
360
|
+
return if variation.nil?
|
375
361
|
|
376
|
-
if
|
362
|
+
if eligible_to_send_impression?
|
377
363
|
if defined?(@batch_events)
|
378
364
|
impression = create_bulk_event_impression(
|
379
365
|
@settings_file,
|
@@ -382,7 +368,7 @@ class VWO
|
|
382
368
|
user_id
|
383
369
|
)
|
384
370
|
@batch_events_queue.enqueue(impression)
|
385
|
-
elsif
|
371
|
+
elsif event_arch_enabled?
|
386
372
|
properties = get_events_base_properties(@settings_file, EventEnum::VWO_VARIATION_SHOWN, @usage_stats.usage_stats)
|
387
373
|
payload = get_track_user_payload_data(@settings_file, user_id, EventEnum::VWO_VARIATION_SHOWN, campaign['id'], variation['id'])
|
388
374
|
@event_dispatcher.dispatch_event_arch_post(properties, payload)
|
@@ -398,42 +384,30 @@ class VWO
|
|
398
384
|
nil, # revenue
|
399
385
|
usage_stats: @usage_stats.usage_stats
|
400
386
|
)
|
401
|
-
|
402
|
-
|
403
|
-
LogLevelEnum::INFO,
|
404
|
-
format(
|
405
|
-
LogMessageEnum::InfoMessages::IMPRESSION_SUCCESS,
|
406
|
-
file: FILE,
|
407
|
-
account_id: @account_id,
|
408
|
-
campaign_id: campaign['id'],
|
409
|
-
variation_id: variation['id'],
|
410
|
-
end_point: EVENTS::TRACK_USER
|
411
|
-
)
|
412
|
-
)
|
413
|
-
end
|
387
|
+
main_keys = { 'campaignId' => campaign['id'], 'variationId' => variation['id'] }
|
388
|
+
@event_dispatcher.dispatch(impression, main_keys, EVENTS::TRACK_USER)
|
414
389
|
end
|
415
390
|
else
|
416
391
|
@logger.log(
|
417
392
|
LogLevelEnum::INFO,
|
418
|
-
|
419
|
-
|
420
|
-
file
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
393
|
+
'CAMPAIGN_USER_ALREADY_TRACKED',
|
394
|
+
{
|
395
|
+
'{file}' => FILE,
|
396
|
+
'{userId}' => user_id,
|
397
|
+
'{campaignKey}' => campaign_key,
|
398
|
+
'{api}' => ApiMethods::ACTIVATE
|
399
|
+
}
|
425
400
|
)
|
426
401
|
end
|
427
402
|
variation['name']
|
428
403
|
rescue StandardError => e
|
429
404
|
@logger.log(
|
430
405
|
LogLevelEnum::ERROR,
|
431
|
-
|
432
|
-
|
433
|
-
file
|
434
|
-
|
435
|
-
|
436
|
-
)
|
406
|
+
"({file}): {api} API error: #{e.message}",
|
407
|
+
{
|
408
|
+
'{file}' => FILE,
|
409
|
+
'{api}' => ApiMethods::ACTIVATE
|
410
|
+
}
|
437
411
|
)
|
438
412
|
e
|
439
413
|
end
|
@@ -456,18 +430,17 @@ class VWO
|
|
456
430
|
# Otherwise null in case of user not becoming part
|
457
431
|
#
|
458
432
|
def get_variation_name(campaign_key, user_id, options = {})
|
459
|
-
|
460
|
-
|
461
|
-
end
|
433
|
+
@logger.set_api_name(ApiMethods::GET_VARIATION_NAME)
|
434
|
+
return nil if opted_out?(ApiMethods::GET_VARIATION_NAME)
|
462
435
|
|
463
436
|
unless @is_instance_valid
|
464
437
|
@logger.log(
|
465
438
|
LogLevelEnum::ERROR,
|
466
|
-
|
467
|
-
|
468
|
-
file
|
469
|
-
|
470
|
-
|
439
|
+
'CONFIG_CORRUPTED',
|
440
|
+
{
|
441
|
+
'{file}' => FILE,
|
442
|
+
'{api}' => ApiMethods::GET_VARIATION_NAME
|
443
|
+
}
|
471
444
|
)
|
472
445
|
return
|
473
446
|
end
|
@@ -478,14 +451,14 @@ class VWO
|
|
478
451
|
|
479
452
|
# Validate input parameters
|
480
453
|
unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables)) &&
|
481
|
-
|
454
|
+
(variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables))
|
482
455
|
@logger.log(
|
483
456
|
LogLevelEnum::ERROR,
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
457
|
+
'API_BAD_PARAMETERS',
|
458
|
+
{
|
459
|
+
'{file}' => FILE,
|
460
|
+
'{api}' => ApiMethods::GET_VARIATION_NAME
|
461
|
+
}
|
489
462
|
)
|
490
463
|
return
|
491
464
|
end
|
@@ -496,13 +469,13 @@ class VWO
|
|
496
469
|
# Validate campaign
|
497
470
|
if campaign.nil? || campaign['status'] != STATUS_RUNNING
|
498
471
|
@logger.log(
|
499
|
-
LogLevelEnum::
|
500
|
-
|
501
|
-
|
502
|
-
file
|
503
|
-
|
504
|
-
|
505
|
-
|
472
|
+
LogLevelEnum::WARNING,
|
473
|
+
'CAMPAIGN_NOT_RUNNING',
|
474
|
+
{
|
475
|
+
'{file}' => FILE,
|
476
|
+
'{campaignKey}' => campaign_key,
|
477
|
+
'{api}' => ApiMethods::GET_VARIATION_NAME
|
478
|
+
}
|
506
479
|
)
|
507
480
|
return
|
508
481
|
end
|
@@ -512,45 +485,48 @@ class VWO
|
|
512
485
|
if campaign_type == CampaignTypes::FEATURE_ROLLOUT
|
513
486
|
@logger.log(
|
514
487
|
LogLevelEnum::ERROR,
|
515
|
-
|
516
|
-
|
517
|
-
file
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
488
|
+
'API_NOT_APPLICABLE',
|
489
|
+
{
|
490
|
+
'{file}' => FILE,
|
491
|
+
'{api}' => ApiMethods::GET_VARIATION_NAME,
|
492
|
+
'{userId}' => user_id,
|
493
|
+
'{campaignKey}' => campaign_key,
|
494
|
+
'{campaignType}' => campaign_type
|
495
|
+
}
|
523
496
|
)
|
524
497
|
return
|
525
498
|
end
|
526
499
|
|
527
|
-
|
528
|
-
|
529
|
-
# Check if variation_name has been assigned
|
530
|
-
unless valid_value?(variation)
|
531
|
-
# log invalid variation key
|
500
|
+
case campaign_type
|
501
|
+
when CampaignTypes::FEATURE_ROLLOUT
|
532
502
|
@logger.log(
|
533
|
-
LogLevelEnum::
|
534
|
-
|
535
|
-
|
536
|
-
file
|
537
|
-
|
538
|
-
|
539
|
-
|
503
|
+
LogLevelEnum::ERROR,
|
504
|
+
'API_NOT_APPLICABLE',
|
505
|
+
{
|
506
|
+
'{file}' => FILE,
|
507
|
+
'{api}' => ApiMethods::GET_VARIATION_NAME,
|
508
|
+
'{userId}' => user_id,
|
509
|
+
'{campaignKey}' => campaign_key,
|
510
|
+
'{campaignType}' => campaign_type
|
511
|
+
}
|
540
512
|
)
|
541
513
|
return
|
542
514
|
end
|
543
515
|
|
516
|
+
variation = @variation_decider.get_variation(user_id, campaign, ApiMethods::GET_VARIATION_NAME, campaign_key, custom_variables, variation_targeting_variables)
|
517
|
+
|
518
|
+
# Check if variation_name has been assigned
|
519
|
+
return unless valid_value?(variation)
|
520
|
+
|
544
521
|
variation['name']
|
545
522
|
rescue StandardError => e
|
546
523
|
@logger.log(
|
547
524
|
LogLevelEnum::ERROR,
|
548
|
-
|
549
|
-
|
550
|
-
file
|
551
|
-
|
552
|
-
|
553
|
-
)
|
525
|
+
"({file}): {api} API error: #{e.message}",
|
526
|
+
{
|
527
|
+
'{file}' => FILE,
|
528
|
+
'{api}' => ApiMethods::GET_VARIATION_NAME
|
529
|
+
}
|
554
530
|
)
|
555
531
|
nil
|
556
532
|
end
|
@@ -566,23 +542,21 @@ class VWO
|
|
566
542
|
# @param[String] :campaign_key Unique campaign key
|
567
543
|
# @param[String] :user_id ID assigned to a user
|
568
544
|
# @param[String] :goal_identifier Unique campaign's goal identifier
|
569
|
-
# @param[Hash] :options
|
570
|
-
# @param[Numeric|String] :revenue_value It is the revenue generated on triggering the goal
|
545
|
+
# @param[Hash] :options Contains revenue value and custom variables
|
571
546
|
#
|
572
547
|
|
573
548
|
def track(campaign_key, user_id, goal_identifier, options = {})
|
574
|
-
|
575
|
-
|
576
|
-
end
|
549
|
+
@logger.set_api_name(ApiMethods::TRACK)
|
550
|
+
return false if opted_out?(ApiMethods::TRACK)
|
577
551
|
|
578
552
|
unless @is_instance_valid
|
579
553
|
@logger.log(
|
580
554
|
LogLevelEnum::ERROR,
|
581
|
-
|
582
|
-
|
583
|
-
file
|
584
|
-
|
585
|
-
|
555
|
+
'CONFIG_CORRUPTED',
|
556
|
+
{
|
557
|
+
'{file}' => FILE,
|
558
|
+
'{api}' => ApiMethods::TRACK
|
559
|
+
}
|
586
560
|
)
|
587
561
|
return false
|
588
562
|
end
|
@@ -594,204 +568,91 @@ class VWO
|
|
594
568
|
goal_type_to_track = get_goal_type_to_track(options)
|
595
569
|
|
596
570
|
# Check for valid args
|
597
|
-
|
598
|
-
(variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables)) && (GOAL_TYPES.key? (goal_type_to_track))
|
599
|
-
# log invalid params
|
600
|
-
@logger.log(
|
601
|
-
LogLevelEnum::ERROR,
|
602
|
-
format(
|
603
|
-
LogMessageEnum::ErrorMessages::TRACK_API_INVALID_PARAMS,
|
604
|
-
file: FILE,
|
605
|
-
api_name: ApiMethods::TRACK
|
606
|
-
)
|
607
|
-
)
|
608
|
-
return false
|
609
|
-
end
|
571
|
+
return false unless valid_track_api_params?(user_id, campaign_key, custom_variables, variation_targeting_variables, goal_type_to_track, goal_identifier)
|
610
572
|
|
611
573
|
# Get campaigns settings
|
612
574
|
campaigns = get_campaigns(@settings_file, campaign_key, goal_identifier, goal_type_to_track)
|
613
575
|
|
614
576
|
# Validate campaign
|
615
|
-
if campaigns.nil?
|
616
|
-
return nil
|
617
|
-
end
|
577
|
+
return nil if campaigns.nil?
|
618
578
|
|
619
579
|
metric_map = {}
|
620
580
|
revenue_props = []
|
621
581
|
result = {}
|
582
|
+
batch_event_data = { 'ev' => [] }
|
622
583
|
campaigns.each do |campaign|
|
623
584
|
begin
|
624
585
|
campaign_type = campaign['type']
|
586
|
+
result[campaign['key']] = false
|
625
587
|
|
626
|
-
|
627
|
-
@logger.log(
|
628
|
-
LogLevelEnum::ERROR,
|
629
|
-
format(
|
630
|
-
LogMessageEnum::ErrorMessages::INVALID_API,
|
631
|
-
file: FILE,
|
632
|
-
api_name: ApiMethods::TRACK,
|
633
|
-
user_id: user_id,
|
634
|
-
campaign_key: campaign['key'],
|
635
|
-
campaign_type: campaign_type
|
636
|
-
)
|
637
|
-
)
|
638
|
-
result[campaign['key']] = false
|
639
|
-
next
|
640
|
-
end
|
588
|
+
next unless valid_campaign_for_track_api?(user_id, campaign_key, campaign_type)
|
641
589
|
|
642
590
|
variation = @variation_decider.get_variation(user_id, campaign, ApiMethods::TRACK, campaign['key'], custom_variables, variation_targeting_variables, goal_identifier)
|
643
591
|
|
644
592
|
if variation
|
645
593
|
goal = get_campaign_goal(campaign, goal_identifier)
|
646
|
-
|
647
|
-
@logger.log(
|
648
|
-
LogLevelEnum::ERROR,
|
649
|
-
format(
|
650
|
-
LogMessageEnum::ErrorMessages::TRACK_API_GOAL_NOT_FOUND,
|
651
|
-
file: FILE,
|
652
|
-
goal_identifier: goal_identifier,
|
653
|
-
user_id: user_id,
|
654
|
-
campaign_key: campaign['key'],
|
655
|
-
api_name: ApiMethods::TRACK
|
656
|
-
)
|
657
|
-
)
|
658
|
-
result[campaign['key']] = false
|
659
|
-
next
|
660
|
-
elsif goal['type'] == GoalTypes::REVENUE && !valid_value?(revenue_value)
|
661
|
-
@logger.log(
|
662
|
-
LogLevelEnum::ERROR,
|
663
|
-
format(
|
664
|
-
LogMessageEnum::ErrorMessages::TRACK_API_REVENUE_NOT_PASSED_FOR_REVENUE_GOAL,
|
665
|
-
file: FILE,
|
666
|
-
user_id: user_id,
|
667
|
-
goal_identifier: goal_identifier,
|
668
|
-
campaign_key: campaign['key'],
|
669
|
-
api_name: ApiMethods::TRACK
|
670
|
-
)
|
671
|
-
)
|
672
|
-
result[campaign['key']] = false
|
673
|
-
next
|
674
|
-
elsif goal['type'] == GoalTypes::CUSTOM
|
675
|
-
revenue_value = nil
|
676
|
-
end
|
594
|
+
next unless valid_goal?(goal, campaign, user_id, goal_identifier, revenue_value)
|
677
595
|
|
678
|
-
if
|
679
|
-
|
680
|
-
else
|
681
|
-
variation['goal_identifier'] = ''
|
682
|
-
identifiers = []
|
683
|
-
end
|
596
|
+
revenue_value = nil if goal['type'] == GoalTypes::CUSTOM
|
597
|
+
identifiers = get_variation_identifiers(variation)
|
684
598
|
|
685
|
-
if
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
# set variation at user storage
|
690
|
-
else
|
691
|
-
@logger.log(
|
692
|
-
LogLevelEnum::INFO,
|
693
|
-
format(
|
694
|
-
LogMessageEnum::InfoMessages::GOAL_ALREADY_TRACKED,
|
695
|
-
file: FILE,
|
696
|
-
user_id: user_id,
|
697
|
-
campaign_key: campaign['key'],
|
698
|
-
goal_identifier: goal_identifier,
|
699
|
-
api_name: ApiMethods::TRACK
|
700
|
-
)
|
701
|
-
)
|
702
|
-
result[campaign['key']] = false
|
703
|
-
next
|
704
|
-
end
|
599
|
+
next if campaign_goal_already_tracked?(user_id, campaign, identifiers, goal_identifier)
|
600
|
+
|
601
|
+
@variation_decider.update_goal_identifier(user_id, campaign, variation, goal_identifier)
|
602
|
+
# set variation at user storage
|
705
603
|
|
706
604
|
if defined?(@batch_events)
|
707
|
-
impression = create_bulk_event_impression(
|
708
|
-
@settings_file,
|
709
|
-
campaign['id'],
|
710
|
-
variation['id'],
|
711
|
-
user_id,
|
712
|
-
goal['id'],
|
713
|
-
revenue_value
|
714
|
-
)
|
605
|
+
impression = create_bulk_event_impression(@settings_file, campaign['id'], variation['id'], user_id, goal['id'], revenue_value)
|
715
606
|
@batch_events_queue.enqueue(impression)
|
716
|
-
elsif
|
607
|
+
elsif event_arch_enabled?
|
717
608
|
metric_map[campaign['id']] = goal['id']
|
718
|
-
if goal['type'] == GoalTypes::REVENUE && !(revenue_props.include? goal['revenueProp'])
|
719
|
-
|
720
|
-
|
609
|
+
revenue_props << goal['revenueProp'] if goal['type'] == GoalTypes::REVENUE && !(revenue_props.include? goal['revenueProp'])
|
610
|
+
elsif campaigns.count == 1
|
611
|
+
impression = create_impression(@settings_file, campaign['id'], variation['id'], user_id, @sdk_key, goal['id'], revenue_value)
|
612
|
+
main_keys = { 'campaignId' => campaign['id'], 'variationId' => variation['id'], 'goalId' => goal['id'] }
|
613
|
+
@event_dispatcher.dispatch(impression, main_keys, EVENTS::TRACK_GOAL)
|
721
614
|
else
|
722
|
-
|
723
|
-
@settings_file,
|
724
|
-
campaign['id'],
|
725
|
-
variation['id'],
|
726
|
-
user_id,
|
727
|
-
@sdk_key,
|
728
|
-
goal['id'],
|
729
|
-
revenue_value
|
730
|
-
)
|
731
|
-
if @event_dispatcher.dispatch(impression)
|
732
|
-
@logger.log(
|
733
|
-
LogLevelEnum::INFO,
|
734
|
-
format(
|
735
|
-
LogMessageEnum::InfoMessages::IMPRESSION_SUCCESS,
|
736
|
-
file: FILE,
|
737
|
-
account_id: @account_id,
|
738
|
-
campaign_id: campaign['id'],
|
739
|
-
variation_id: variation['id'],
|
740
|
-
end_point: EVENTS::TRACK_GOAL
|
741
|
-
)
|
742
|
-
)
|
743
|
-
@logger.log(
|
744
|
-
LogLevelEnum::INFO,
|
745
|
-
format(
|
746
|
-
LogMessageEnum::InfoMessages::MAIN_KEYS_FOR_IMPRESSION,
|
747
|
-
file: FILE,
|
748
|
-
campaign_id: impression[:experiment_id],
|
749
|
-
account_id: impression[:account_id],
|
750
|
-
variation_id: impression[:combination]
|
751
|
-
)
|
752
|
-
)
|
753
|
-
end
|
615
|
+
batch_event_data['ev'] << create_bulk_event_impression(@settings_file, campaign['id'], variation['id'], user_id, goal['id'], revenue_value)
|
754
616
|
end
|
755
617
|
result[campaign['key']] = true
|
756
618
|
next
|
757
619
|
end
|
758
|
-
result[campaign['key']] = false
|
759
620
|
rescue StandardError => e
|
760
621
|
@logger.log(
|
761
622
|
LogLevelEnum::ERROR,
|
762
|
-
|
763
|
-
|
764
|
-
file
|
765
|
-
|
766
|
-
|
623
|
+
"({file}): {api} API error: #{e.message}",
|
624
|
+
{
|
625
|
+
'{file}' => FILE,
|
626
|
+
'{api}' => ApiMethods::TRACK
|
627
|
+
}
|
767
628
|
)
|
768
629
|
end
|
769
630
|
end
|
770
631
|
|
771
|
-
if
|
632
|
+
if event_arch_enabled?
|
772
633
|
properties = get_events_base_properties(@settings_file, goal_identifier)
|
773
634
|
payload = get_track_goal_payload_data(@settings_file, user_id, goal_identifier, revenue_value, metric_map, revenue_props)
|
774
635
|
@event_dispatcher.dispatch_event_arch_post(properties, payload)
|
636
|
+
elsif batch_event_data['ev'].count != 0
|
637
|
+
paramters = get_batch_event_query_params(@settings_file['accountId'], @sdk_key, @usage_stats.usage_stats)
|
638
|
+
batch_events_dispatcher = VWO::Services::BatchEventsDispatcher.new(@is_development_mode)
|
639
|
+
return nil unless batch_events_dispatcher.dispatch(batch_event_data, nil, paramters)
|
775
640
|
end
|
776
641
|
|
777
|
-
if result.length
|
778
|
-
return nil
|
779
|
-
end
|
642
|
+
return nil if result.length == 0
|
780
643
|
|
781
644
|
result
|
782
645
|
rescue StandardError => e
|
783
646
|
@logger.log(
|
784
647
|
LogLevelEnum::ERROR,
|
785
|
-
|
786
|
-
|
787
|
-
file
|
788
|
-
|
789
|
-
|
790
|
-
)
|
648
|
+
"({file}): {api} API error: #{e.message}",
|
649
|
+
{
|
650
|
+
'{file}' => FILE,
|
651
|
+
'{api}' => ApiMethods::TRACK
|
652
|
+
}
|
791
653
|
)
|
792
654
|
false
|
793
655
|
end
|
794
|
-
|
795
656
|
# This API method: Identifies whether the user becomes a part of feature rollout/test or not.
|
796
657
|
# 1. Validates the arguments being passed
|
797
658
|
# 2. Checks if user is eligible to get bucketed into the feature test/rollout,
|
@@ -806,18 +667,17 @@ class VWO
|
|
806
667
|
# @return[Boolean] true if user becomes part of feature test/rollout, otherwise false.
|
807
668
|
|
808
669
|
def feature_enabled?(campaign_key, user_id, options = {})
|
809
|
-
|
810
|
-
|
811
|
-
end
|
670
|
+
@logger.set_api_name(ApiMethods::IS_FEATURE_ENABLED)
|
671
|
+
return false if opted_out?(ApiMethods::IS_FEATURE_ENABLED)
|
812
672
|
|
813
673
|
unless @is_instance_valid
|
814
674
|
@logger.log(
|
815
675
|
LogLevelEnum::ERROR,
|
816
|
-
|
817
|
-
|
818
|
-
file
|
819
|
-
|
820
|
-
|
676
|
+
'CONFIG_CORRUPTED',
|
677
|
+
{
|
678
|
+
'{file}' => FILE,
|
679
|
+
'{api}' => ApiMethods::IS_FEATURE_ENABLED
|
680
|
+
}
|
821
681
|
)
|
822
682
|
return false
|
823
683
|
end
|
@@ -826,25 +686,17 @@ class VWO
|
|
826
686
|
# Retrieve custom variables
|
827
687
|
custom_variables = options[:custom_variables]
|
828
688
|
variation_targeting_variables = options[:variation_targeting_variables]
|
829
|
-
|
830
|
-
LogLevelEnum::INFO,
|
831
|
-
format(
|
832
|
-
LogMessageEnum::InfoMessages::API_CALLED,
|
833
|
-
file: FILE,
|
834
|
-
api_name: ApiMethods::IS_FEATURE_ENABLED,
|
835
|
-
user_id: user_id
|
836
|
-
)
|
837
|
-
)
|
689
|
+
|
838
690
|
# Validate input parameters
|
839
691
|
unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables)) &&
|
840
|
-
|
692
|
+
(variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables))
|
841
693
|
@logger.log(
|
842
694
|
LogLevelEnum::ERROR,
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
695
|
+
'API_BAD_PARAMETERS',
|
696
|
+
{
|
697
|
+
'{file}' => FILE,
|
698
|
+
'{api}' => ApiMethods::IS_FEATURE_ENABLED
|
699
|
+
}
|
848
700
|
)
|
849
701
|
return false
|
850
702
|
end
|
@@ -856,13 +708,13 @@ class VWO
|
|
856
708
|
unless campaign && campaign['status'] == STATUS_RUNNING
|
857
709
|
# log error
|
858
710
|
@logger.log(
|
859
|
-
LogLevelEnum::
|
860
|
-
|
861
|
-
|
862
|
-
file
|
863
|
-
|
864
|
-
|
865
|
-
|
711
|
+
LogLevelEnum::WARNING,
|
712
|
+
'CAMPAIGN_NOT_RUNNING',
|
713
|
+
{
|
714
|
+
'{file}' => FILE,
|
715
|
+
'{campaignKey}' => campaign_key,
|
716
|
+
'{api}' => ApiMethods::IS_FEATURE_ENABLED
|
717
|
+
}
|
866
718
|
)
|
867
719
|
return false
|
868
720
|
end
|
@@ -873,14 +725,14 @@ class VWO
|
|
873
725
|
if campaign_type == CampaignTypes::VISUAL_AB
|
874
726
|
@logger.log(
|
875
727
|
LogLevelEnum::ERROR,
|
876
|
-
|
877
|
-
|
878
|
-
file
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
728
|
+
'API_NOT_APPLICABLE',
|
729
|
+
{
|
730
|
+
'{file}' => FILE,
|
731
|
+
'{api}' => ApiMethods::IS_FEATURE_ENABLED,
|
732
|
+
'{userId}' => user_id,
|
733
|
+
'{campaignKey}' => campaign_key,
|
734
|
+
'{campaignType}' => campaign_type
|
735
|
+
}
|
884
736
|
)
|
885
737
|
return false
|
886
738
|
end
|
@@ -893,7 +745,7 @@ class VWO
|
|
893
745
|
|
894
746
|
# if campaign type is feature_test Send track call to server
|
895
747
|
|
896
|
-
if
|
748
|
+
if eligible_to_send_impression?
|
897
749
|
if defined?(@batch_events)
|
898
750
|
impression = create_bulk_event_impression(
|
899
751
|
@settings_file,
|
@@ -902,7 +754,7 @@ class VWO
|
|
902
754
|
user_id
|
903
755
|
)
|
904
756
|
@batch_events_queue.enqueue(impression)
|
905
|
-
elsif
|
757
|
+
elsif event_arch_enabled?
|
906
758
|
properties = get_events_base_properties(@settings_file, EventEnum::VWO_VARIATION_SHOWN, @usage_stats.usage_stats)
|
907
759
|
payload = get_track_user_payload_data(@settings_file, user_id, EventEnum::VWO_VARIATION_SHOWN, campaign['id'], variation['id'])
|
908
760
|
@event_dispatcher.dispatch_event_arch_post(properties, payload)
|
@@ -918,58 +770,49 @@ class VWO
|
|
918
770
|
usage_stats: @usage_stats.usage_stats
|
919
771
|
)
|
920
772
|
|
921
|
-
|
922
|
-
@
|
923
|
-
LogLevelEnum::INFO,
|
924
|
-
format(
|
925
|
-
LogMessageEnum::InfoMessages::MAIN_KEYS_FOR_IMPRESSION,
|
926
|
-
file: FILE,
|
927
|
-
campaign_id: impression[:experiment_id],
|
928
|
-
account_id: impression[:account_id],
|
929
|
-
variation_id: impression[:combination]
|
930
|
-
)
|
931
|
-
)
|
773
|
+
main_keys = { 'campaignId' => impression[:experiment_id] }
|
774
|
+
@event_dispatcher.dispatch(impression, main_keys, EVENTS::TRACK_USER)
|
932
775
|
end
|
933
776
|
|
934
777
|
else
|
935
778
|
@logger.log(
|
936
779
|
LogLevelEnum::INFO,
|
937
|
-
|
938
|
-
|
939
|
-
file
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
780
|
+
'CAMPAIGN_USER_ALREADY_TRACKED',
|
781
|
+
{
|
782
|
+
'{file}' => FILE,
|
783
|
+
'{userId}' => user_id,
|
784
|
+
'{campaignKey}' => campaign_key,
|
785
|
+
'{api}' => ApiMethods::IS_FEATURE_ENABLED
|
786
|
+
}
|
944
787
|
)
|
945
788
|
end
|
946
|
-
if campaign_type == CampaignTypes::FEATURE_ROLLOUT
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
789
|
+
result = if campaign_type == CampaignTypes::FEATURE_ROLLOUT
|
790
|
+
true
|
791
|
+
else
|
792
|
+
variation['isFeatureEnabled']
|
793
|
+
end
|
951
794
|
|
952
795
|
if result
|
953
796
|
@logger.log(
|
954
797
|
LogLevelEnum::INFO,
|
955
|
-
|
956
|
-
|
957
|
-
file
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
798
|
+
'FEATURE_STATUS',
|
799
|
+
{
|
800
|
+
'{file}' => FILE,
|
801
|
+
'{userId}' => user_id,
|
802
|
+
'{campaignKey}' => campaign_key,
|
803
|
+
'{status}' => 'enabled'
|
804
|
+
}
|
962
805
|
)
|
963
806
|
else
|
964
807
|
@logger.log(
|
965
808
|
LogLevelEnum::INFO,
|
966
|
-
|
967
|
-
|
968
|
-
file
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
809
|
+
'FEATURE_STATUS',
|
810
|
+
{
|
811
|
+
'{file}' => FILE,
|
812
|
+
'{userId}' => user_id,
|
813
|
+
'{campaignKey}' => campaign_key,
|
814
|
+
'{status}' => 'disabled'
|
815
|
+
}
|
973
816
|
)
|
974
817
|
end
|
975
818
|
|
@@ -977,12 +820,11 @@ class VWO
|
|
977
820
|
rescue StandardError => e
|
978
821
|
@logger.log(
|
979
822
|
LogLevelEnum::ERROR,
|
980
|
-
|
981
|
-
|
982
|
-
file
|
983
|
-
|
984
|
-
|
985
|
-
)
|
823
|
+
"({file}): {api} API error: #{e.message}",
|
824
|
+
{
|
825
|
+
'{file}' => FILE,
|
826
|
+
'{api}' => ApiMethods::IS_FEATURE_ENABLED
|
827
|
+
}
|
986
828
|
)
|
987
829
|
false
|
988
830
|
end
|
@@ -1007,18 +849,17 @@ class VWO
|
|
1007
849
|
#
|
1008
850
|
|
1009
851
|
def get_feature_variable_value(campaign_key, variable_key, user_id, options = {})
|
1010
|
-
|
1011
|
-
|
1012
|
-
end
|
852
|
+
@logger.set_api_name(ApiMethods::GET_FEATURE_VARIABLE_VALUE)
|
853
|
+
return nil if opted_out?(ApiMethods::GET_FEATURE_VARIABLE_VALUE)
|
1013
854
|
|
1014
855
|
unless @is_instance_valid
|
1015
856
|
@logger.log(
|
1016
857
|
LogLevelEnum::ERROR,
|
1017
|
-
|
1018
|
-
|
1019
|
-
file
|
1020
|
-
|
1021
|
-
|
858
|
+
'CONFIG_CORRUPTED',
|
859
|
+
{
|
860
|
+
'{file}' => FILE,
|
861
|
+
'{api}' => ApiMethods::GET_FEATURE_VARIABLE_VALUE
|
862
|
+
}
|
1022
863
|
)
|
1023
864
|
return
|
1024
865
|
end
|
@@ -1029,14 +870,14 @@ class VWO
|
|
1029
870
|
variation_targeting_variables = options[:variation_targeting_variables]
|
1030
871
|
|
1031
872
|
unless valid_string?(campaign_key) && valid_string?(variable_key) && valid_string?(user_id) &&
|
1032
|
-
|
873
|
+
(custom_variables.nil? || valid_hash?(custom_variables)) && (variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables))
|
1033
874
|
@logger.log(
|
1034
875
|
LogLevelEnum::ERROR,
|
1035
|
-
|
1036
|
-
|
1037
|
-
file
|
1038
|
-
|
1039
|
-
|
876
|
+
'API_BAD_PARAMETERS',
|
877
|
+
{
|
878
|
+
'{file}' => FILE,
|
879
|
+
'{api}' => ApiMethods::GET_FEATURE_VARIABLE_VALUE
|
880
|
+
}
|
1040
881
|
)
|
1041
882
|
return
|
1042
883
|
end
|
@@ -1048,13 +889,13 @@ class VWO
|
|
1048
889
|
unless campaign && campaign['status'] == STATUS_RUNNING
|
1049
890
|
# log error
|
1050
891
|
@logger.log(
|
1051
|
-
LogLevelEnum::
|
1052
|
-
|
1053
|
-
|
1054
|
-
file
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
892
|
+
LogLevelEnum::WARNING,
|
893
|
+
'CAMPAIGN_NOT_RUNNING',
|
894
|
+
{
|
895
|
+
'{file}' => FILE,
|
896
|
+
'{campaignKey}' => campaign_key,
|
897
|
+
'{api}' => ApiMethods::GET_FEATURE_VARIABLE_VALUE
|
898
|
+
}
|
1058
899
|
)
|
1059
900
|
return
|
1060
901
|
end
|
@@ -1064,14 +905,14 @@ class VWO
|
|
1064
905
|
if campaign_type == CampaignTypes::VISUAL_AB
|
1065
906
|
@logger.log(
|
1066
907
|
LogLevelEnum::ERROR,
|
1067
|
-
|
1068
|
-
|
1069
|
-
file
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
908
|
+
'API_NOT_APPLICABLE',
|
909
|
+
{
|
910
|
+
'{file}' => FILE,
|
911
|
+
'{api}' => ApiMethods::GET_FEATURE_VARIABLE_VALUE,
|
912
|
+
'{userId}' => user_id,
|
913
|
+
'{campaignKey}' => campaign_key,
|
914
|
+
'{campaignType}' => campaign_type
|
915
|
+
}
|
1075
916
|
)
|
1076
917
|
return
|
1077
918
|
end
|
@@ -1081,31 +922,32 @@ class VWO
|
|
1081
922
|
# Check if variation has been assigned to user
|
1082
923
|
return unless variation
|
1083
924
|
|
1084
|
-
|
925
|
+
case campaign_type
|
926
|
+
when CampaignTypes::FEATURE_ROLLOUT
|
1085
927
|
variables = campaign['variables']
|
1086
|
-
|
928
|
+
when CampaignTypes::FEATURE_TEST
|
1087
929
|
if !variation['isFeatureEnabled']
|
1088
930
|
@logger.log(
|
1089
931
|
LogLevelEnum::INFO,
|
1090
|
-
|
1091
|
-
|
1092
|
-
file
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
932
|
+
'FEATURE_STATUS',
|
933
|
+
{
|
934
|
+
'{file}' => FILE,
|
935
|
+
'{userId}' => user_id,
|
936
|
+
'{campaignKey}' => campaign_key,
|
937
|
+
'{status}' => 'disabled'
|
938
|
+
}
|
1097
939
|
)
|
1098
940
|
variation = get_control_variation(campaign)
|
1099
941
|
else
|
1100
942
|
@logger.log(
|
1101
943
|
LogLevelEnum::INFO,
|
1102
|
-
|
1103
|
-
|
1104
|
-
file
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
944
|
+
'FEATURE_STATUS',
|
945
|
+
{
|
946
|
+
'{file}' => FILE,
|
947
|
+
'{userId}' => user_id,
|
948
|
+
'{campaignKey}' => campaign_key,
|
949
|
+
'{status}' => 'enabled'
|
950
|
+
}
|
1109
951
|
)
|
1110
952
|
end
|
1111
953
|
variables = variation['variables']
|
@@ -1115,43 +957,37 @@ class VWO
|
|
1115
957
|
unless variable
|
1116
958
|
# Log variable not found
|
1117
959
|
@logger.log(
|
1118
|
-
LogLevelEnum::
|
1119
|
-
|
1120
|
-
|
1121
|
-
file
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
user_id: user_id,
|
1126
|
-
api_name: ApiMethods::GET_FEATURE_VARIABLE_VALUE
|
1127
|
-
)
|
960
|
+
LogLevelEnum::INFO,
|
961
|
+
'FEATURE_VARIABLE_DEFAULT_VALUE',
|
962
|
+
{
|
963
|
+
'{file}' => FILE,
|
964
|
+
'{variableKey}' => variable_key,
|
965
|
+
'{variationName}' => variation['name']
|
966
|
+
}
|
1128
967
|
)
|
1129
968
|
return
|
1130
969
|
end
|
1131
970
|
|
1132
971
|
@logger.log(
|
1133
972
|
LogLevelEnum::INFO,
|
1134
|
-
|
1135
|
-
|
1136
|
-
file
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
api_name: ApiMethods::GET_FEATURE_VARIABLE_VALUE
|
1143
|
-
)
|
973
|
+
'FEATURE_VARIABLE_VALUE',
|
974
|
+
{
|
975
|
+
'{file}' => FILE,
|
976
|
+
'{variableKey}' => variable_key,
|
977
|
+
'{variableValue}' => variable['value'],
|
978
|
+
'{campaignKey}' => campaign_key,
|
979
|
+
'{userId}' => user_id
|
980
|
+
}
|
1144
981
|
)
|
1145
982
|
get_type_casted_feature_value(variable['value'], variable['type'])
|
1146
983
|
rescue StandardError => e
|
1147
984
|
@logger.log(
|
1148
985
|
LogLevelEnum::ERROR,
|
1149
|
-
|
1150
|
-
|
1151
|
-
file
|
1152
|
-
|
1153
|
-
|
1154
|
-
)
|
986
|
+
"({file}): {api} API error: #{e.message}",
|
987
|
+
{
|
988
|
+
'{file}' => FILE,
|
989
|
+
'{api}' => ApiMethods::GET_FEATURE_VARIABLE_VALUE
|
990
|
+
}
|
1155
991
|
)
|
1156
992
|
nil
|
1157
993
|
end
|
@@ -1165,20 +1001,19 @@ class VWO
|
|
1165
1001
|
# @return true if call is made successfully, else false
|
1166
1002
|
|
1167
1003
|
def push(tag_key, tag_value, user_id = nil)
|
1168
|
-
|
1169
|
-
|
1170
|
-
end
|
1004
|
+
@logger.set_api_name(ApiMethods::PUSH)
|
1005
|
+
return {} if opted_out?(ApiMethods::PUSH)
|
1171
1006
|
|
1172
1007
|
unless @is_instance_valid
|
1173
1008
|
@logger.log(
|
1174
1009
|
LogLevelEnum::ERROR,
|
1175
|
-
|
1176
|
-
|
1177
|
-
file
|
1178
|
-
|
1179
|
-
|
1010
|
+
'CONFIG_CORRUPTED',
|
1011
|
+
{
|
1012
|
+
'{file}' => FILE,
|
1013
|
+
'{api}' => ApiMethods::PUSH
|
1014
|
+
}
|
1180
1015
|
)
|
1181
|
-
return
|
1016
|
+
return {}
|
1182
1017
|
end
|
1183
1018
|
|
1184
1019
|
# Argument reshuffling.
|
@@ -1190,105 +1025,124 @@ class VWO
|
|
1190
1025
|
custom_dimension_map[tag_key.to_sym] = tag_value
|
1191
1026
|
end
|
1192
1027
|
|
1193
|
-
unless (valid_string?(tag_key) || valid_hash?(tag_key)) && valid_string?(
|
1028
|
+
unless (valid_string?(tag_key) || valid_hash?(tag_key)) && valid_string?(user_id)
|
1194
1029
|
@logger.log(
|
1195
1030
|
LogLevelEnum::ERROR,
|
1196
|
-
|
1197
|
-
|
1198
|
-
file
|
1199
|
-
|
1200
|
-
|
1031
|
+
'API_BAD_PARAMETERS',
|
1032
|
+
{
|
1033
|
+
'{file}' => FILE,
|
1034
|
+
'{api}' => ApiMethods::PUSH
|
1035
|
+
}
|
1201
1036
|
)
|
1202
|
-
return
|
1037
|
+
return {}
|
1203
1038
|
end
|
1204
1039
|
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
file: FILE,
|
1212
|
-
user_id: user_id,
|
1213
|
-
tag_key: tag_key,
|
1214
|
-
api_name: ApiMethods::PUSH
|
1215
|
-
)
|
1216
|
-
)
|
1217
|
-
return false
|
1040
|
+
result = {}
|
1041
|
+
custom_dimension_map.each do |tagkey, tagvalue|
|
1042
|
+
if !tagkey.is_a?(Symbol) || !tagvalue.is_a?(String)
|
1043
|
+
custom_dimension_map.delete(tagkey)
|
1044
|
+
result[tagkey] = false
|
1045
|
+
next
|
1218
1046
|
end
|
1219
1047
|
|
1220
|
-
if
|
1048
|
+
if tagkey.length > PushApi::TAG_KEY_LENGTH || tagkey.length == 0
|
1221
1049
|
@logger.log(
|
1222
1050
|
LogLevelEnum::ERROR,
|
1223
|
-
|
1224
|
-
|
1225
|
-
file
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
)
|
1051
|
+
'TAG_KEY_LENGTH_EXCEEDED',
|
1052
|
+
{
|
1053
|
+
'{file}' => FILE,
|
1054
|
+
'{userId}' => user_id,
|
1055
|
+
'{tagKey}' => tagkey
|
1056
|
+
}
|
1230
1057
|
)
|
1231
|
-
|
1058
|
+
custom_dimension_map.delete(tagkey)
|
1059
|
+
result[tagkey] = false
|
1060
|
+
next
|
1232
1061
|
end
|
1062
|
+
|
1063
|
+
next unless tagvalue.length > PushApi::TAG_VALUE_LENGTH || tagvalue.length == 0
|
1064
|
+
|
1065
|
+
@logger.log(
|
1066
|
+
LogLevelEnum::ERROR,
|
1067
|
+
'TAG_VALUE_LENGTH_EXCEEDED',
|
1068
|
+
{
|
1069
|
+
'{file}' => FILE,
|
1070
|
+
'{userId}' => user_id,
|
1071
|
+
'{tagKey}' => tagkey,
|
1072
|
+
'{tagValue}' => tagvalue
|
1073
|
+
}
|
1074
|
+
)
|
1075
|
+
custom_dimension_map.delete(tagkey)
|
1076
|
+
result[tagkey] = false
|
1077
|
+
end
|
1078
|
+
|
1079
|
+
if custom_dimension_map.count == 0
|
1080
|
+
@logger.log(
|
1081
|
+
LogLevelEnum::ERROR,
|
1082
|
+
'API_BAD_PARAMETERS',
|
1083
|
+
{
|
1084
|
+
'{file}' => FILE,
|
1085
|
+
'{api}' => ApiMethods::PUSH
|
1086
|
+
}
|
1087
|
+
)
|
1088
|
+
return result
|
1233
1089
|
end
|
1234
1090
|
|
1235
1091
|
if defined?(@batch_events)
|
1236
|
-
custom_dimension_map.each do |
|
1237
|
-
impression = get_batch_event_url_params(@settings_file,
|
1092
|
+
custom_dimension_map.each do |tagkey, tagvalue|
|
1093
|
+
impression = get_batch_event_url_params(@settings_file, tagkey, tagvalue, user_id)
|
1238
1094
|
@batch_events_queue.enqueue(impression)
|
1239
1095
|
end
|
1240
|
-
|
1096
|
+
resp = true
|
1097
|
+
elsif event_arch_enabled?
|
1241
1098
|
properties = get_events_base_properties(@settings_file, EventEnum::VWO_SYNC_VISITOR_PROP)
|
1242
1099
|
payload = get_push_payload_data(@settings_file, user_id, EventEnum::VWO_SYNC_VISITOR_PROP, custom_dimension_map)
|
1243
|
-
@event_dispatcher.dispatch_event_arch_post(properties, payload)
|
1100
|
+
resp = @event_dispatcher.dispatch_event_arch_post(properties, payload)
|
1101
|
+
elsif custom_dimension_map.count == 1
|
1102
|
+
custom_dimension_map.each do |tagkey, tagvalue|
|
1103
|
+
impression = get_url_params(@settings_file, tagkey, tagvalue, user_id, @sdk_key)
|
1104
|
+
main_keys = { 'tags' => impression['tags'] }
|
1105
|
+
result[tagkey] = @event_dispatcher.dispatch(impression, main_keys, EVENTS::PUSH)
|
1106
|
+
end
|
1107
|
+
resp = true
|
1244
1108
|
else
|
1245
|
-
|
1246
|
-
|
1247
|
-
@
|
1248
|
-
|
1249
|
-
@logger.log(
|
1250
|
-
LogLevelEnum::INFO,
|
1251
|
-
format(
|
1252
|
-
LogMessageEnum::InfoMessages::MAIN_KEYS_FOR_PUSH_API,
|
1253
|
-
file: FILE,
|
1254
|
-
u: impression['u'],
|
1255
|
-
account_id: impression['account_id'],
|
1256
|
-
tags: impression['tags']
|
1257
|
-
)
|
1258
|
-
)
|
1109
|
+
batch_event_data = { 'ev' => [] }
|
1110
|
+
custom_dimension_map.each do |tagkey, tagvalue|
|
1111
|
+
batch_event_data['ev'] << get_batch_event_url_params(@settings_file, tagkey, tagvalue, user_id)
|
1259
1112
|
end
|
1113
|
+
paramters = get_batch_event_query_params(@settings_file['accountId'], @sdk_key, @usage_stats.usage_stats)
|
1114
|
+
batch_events_dispatcher = VWO::Services::BatchEventsDispatcher.new(@is_development_mode)
|
1115
|
+
resp = batch_events_dispatcher.dispatch(batch_event_data, nil, paramters)
|
1260
1116
|
end
|
1261
|
-
|
1117
|
+
|
1118
|
+
prepare_push_response(custom_dimension_map, resp, result)
|
1262
1119
|
rescue StandardError => e
|
1263
1120
|
@logger.log(
|
1264
1121
|
LogLevelEnum::ERROR,
|
1265
|
-
|
1266
|
-
|
1267
|
-
file: FILE,
|
1268
|
-
api_name: ApiMethods::PUSH,
|
1269
|
-
exception: e
|
1270
|
-
)
|
1122
|
+
"({file}): push API error: #{e.message}",
|
1123
|
+
{ '{file}' => FILE }
|
1271
1124
|
)
|
1272
1125
|
false
|
1273
1126
|
end
|
1274
1127
|
|
1275
|
-
def
|
1128
|
+
def eligible_to_send_impression?
|
1276
1129
|
!@user_storage || !@variation_decider.has_stored_variation
|
1277
1130
|
end
|
1278
1131
|
|
1132
|
+
# Manually flush impression events to VWO which are queued in batch queue as per batchEvents config
|
1133
|
+
# @return[bool]
|
1279
1134
|
def flush_events
|
1280
|
-
|
1281
|
-
|
1282
|
-
end
|
1135
|
+
@logger.set_api_name(ApiMethods::FLUSH_EVENTS)
|
1136
|
+
return false if opted_out?(ApiMethods::FLUSH_EVENTS)
|
1283
1137
|
|
1284
1138
|
unless @is_instance_valid
|
1285
1139
|
@logger.log(
|
1286
1140
|
LogLevelEnum::ERROR,
|
1287
|
-
|
1288
|
-
|
1289
|
-
file
|
1290
|
-
|
1291
|
-
|
1141
|
+
'CONFIG_CORRUPTED',
|
1142
|
+
{
|
1143
|
+
'{file}' => FILE,
|
1144
|
+
'{api}' => ApiMethods::FLUSH_EVENTS
|
1145
|
+
}
|
1292
1146
|
)
|
1293
1147
|
return false
|
1294
1148
|
end
|
@@ -1301,12 +1155,11 @@ class VWO
|
|
1301
1155
|
rescue StandardError => e
|
1302
1156
|
@logger.log(
|
1303
1157
|
LogLevelEnum::ERROR,
|
1304
|
-
|
1305
|
-
|
1306
|
-
file
|
1307
|
-
|
1308
|
-
|
1309
|
-
)
|
1158
|
+
"({file}): {api} API error: #{e.message}",
|
1159
|
+
{
|
1160
|
+
'{file}' => FILE,
|
1161
|
+
'{api}' => ApiMethods::FLUSH_EVENTS
|
1162
|
+
}
|
1310
1163
|
)
|
1311
1164
|
false
|
1312
1165
|
end
|
@@ -1314,20 +1167,19 @@ class VWO
|
|
1314
1167
|
def get_goal_type_to_track(options)
|
1315
1168
|
goal_type_to_track = nil
|
1316
1169
|
if !options.key?(:goal_type_to_track)
|
1317
|
-
|
1318
|
-
goal_type_to_track = @goal_type_to_track
|
1319
|
-
else
|
1320
|
-
goal_type_to_track = GOAL_TYPES['ALL']
|
1321
|
-
end
|
1170
|
+
goal_type_to_track = @goal_type_to_track || GOAL_TYPES['ALL']
|
1322
1171
|
elsif GOAL_TYPES.key? options[:goal_type_to_track]
|
1323
1172
|
goal_type_to_track = options[:goal_type_to_track]
|
1324
1173
|
else
|
1325
1174
|
@logger.log(
|
1326
1175
|
LogLevelEnum::ERROR,
|
1327
|
-
|
1328
|
-
|
1329
|
-
file
|
1330
|
-
|
1176
|
+
'CONFIG_PARAMETER_INVALID',
|
1177
|
+
{
|
1178
|
+
'{file}' => FILE,
|
1179
|
+
'{parameter}' => 'goal_type_to_track',
|
1180
|
+
'{type}' => 'string(REVENUE, CUSTOM, ALL)',
|
1181
|
+
'{api}' => 'init'
|
1182
|
+
}
|
1331
1183
|
)
|
1332
1184
|
end
|
1333
1185
|
goal_type_to_track
|
@@ -1338,51 +1190,51 @@ class VWO
|
|
1338
1190
|
# return[bool]
|
1339
1191
|
#
|
1340
1192
|
def set_opt_out
|
1193
|
+
@logger.set_api_name(ApiMethods::OPT_OUT)
|
1341
1194
|
@logger.log(
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1195
|
+
LogLevelEnum::INFO,
|
1196
|
+
'OPT_OUT_API_CALLED',
|
1197
|
+
{
|
1198
|
+
'{file}' => FILE
|
1199
|
+
}
|
1200
|
+
)
|
1201
|
+
if defined?(@batch_events) && !@batch_events_queue.nil?
|
1202
|
+
@batch_events_queue.flush(manual: true)
|
1203
|
+
@batch_events_queue.kill_thread
|
1204
|
+
end
|
1352
1205
|
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1206
|
+
@is_opted_out = true
|
1207
|
+
@settings_file = nil
|
1208
|
+
@user_storage = nil
|
1209
|
+
@event_dispatcher = nil
|
1210
|
+
@variation_decider = nil
|
1211
|
+
@config = nil
|
1212
|
+
@usage_stats = nil
|
1213
|
+
@batch_event_dispatcher = nil
|
1214
|
+
@batch_events_queue = nil
|
1215
|
+
@batch_events = nil
|
1216
|
+
|
1217
|
+
@is_opted_out
|
1365
1218
|
end
|
1366
1219
|
|
1367
|
-
|
1368
1220
|
# Check if VWO SDK is manually opted out
|
1369
1221
|
# @param[String] :api_name api_name is used in logging
|
1370
1222
|
# @return[bool]
|
1371
|
-
def
|
1223
|
+
def opted_out?(api_name)
|
1372
1224
|
if @is_opted_out
|
1373
1225
|
@logger.log(
|
1374
1226
|
LogLevelEnum::INFO,
|
1375
|
-
|
1376
|
-
|
1377
|
-
file
|
1378
|
-
api
|
1379
|
-
|
1227
|
+
'API_NOT_ENABLED',
|
1228
|
+
{
|
1229
|
+
'{file}' => FILE,
|
1230
|
+
'{api}' => api_name
|
1231
|
+
}
|
1380
1232
|
)
|
1381
1233
|
end
|
1382
|
-
|
1234
|
+
@is_opted_out
|
1383
1235
|
end
|
1384
1236
|
|
1385
|
-
def
|
1386
|
-
|
1237
|
+
def event_arch_enabled?
|
1238
|
+
@settings_file.key?('isEventArchEnabled') && @settings_file['isEventArchEnabled']
|
1387
1239
|
end
|
1388
1240
|
end
|