vwo-sdk 1.3.0 → 1.5.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2555f32eb2068e63dea737bdf3937708a5ef3e1e
4
- data.tar.gz: dd662a2ac80ba5dc6892375c15b3d13e2e0ed3a4
2
+ SHA256:
3
+ metadata.gz: 4e24789df43b6c0c71d71f8211c44ffe12c113e91943b91f8de581214353ccce
4
+ data.tar.gz: 95ec02ba3df3e88f91bf3f49eb5ab3ab64302b2c664d4d3caa6f569f2e618952
5
5
  SHA512:
6
- metadata.gz: 2dae59f19f9342856a343e5be3359b487069db19f4503398b577eed09c9e1e6ff98c37923c53b1fca91b5da5d66ad2d7a2414c582e0b02b3cb78f529a80a1568
7
- data.tar.gz: 1d1778ccde23e98efed73462dca543c84c12ccb2a7cf4cb18e129f63514268742afc4a0d7a394b16476dadef08eb2d0bbd47b312a13afce23f1c66c23f5a3a99
6
+ metadata.gz: 1dcc6b57a5fd35867d58d71f3f4b73b0da3ca73f01d009493f76b8981562e6d315f004a9095bcd20f230de1bf19559ac0a2ffefaa5befb72abae0e61de8fce6d
7
+ data.tar.gz: a7b154c4d9ae6c5b681c6cb27b231f3183a21c496e3eb5d33eecf81df0ca1d55922db127db37debe175aa060575f56dfe42ddbff29c0843e69839bcb57e4fc8c
data/lib/vwo.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright 2019 Wingify Software Pvt. Ltd.
1
+ # Copyright 2019-2020 Wingify Software Pvt. Ltd.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- # frozen_string_literal: true
15
+ require 'logger'
16
16
 
17
17
  require_relative 'vwo/services/settings_file_manager'
18
18
  require_relative 'vwo/services/event_dispatcher'
@@ -21,16 +21,19 @@ require_relative 'vwo/logger'
21
21
  require_relative 'vwo/enums'
22
22
  require_relative 'vwo/utils/campaign'
23
23
  require_relative 'vwo/utils/impression'
24
+ require_relative 'vwo/utils/feature'
25
+ require_relative 'vwo/utils/custom_dimensions'
24
26
  require_relative 'vwo/constants'
25
27
  require_relative 'vwo/core/variation_decider'
26
28
 
27
-
28
29
  # VWO main file
29
30
  class VWO
30
- attr_accessor :is_instance_valid
31
+ attr_accessor :is_instance_valid, :logger
31
32
 
32
33
  include Enums
33
34
  include Utils::Validations
35
+ include Utils::Feature
36
+ include Utils::CustomDimensions
34
37
  include Utils::Campaign
35
38
  include Utils::Impression
36
39
  include CONSTANTS
@@ -53,13 +56,15 @@ class VWO
53
56
  logger = nil,
54
57
  user_storage = nil,
55
58
  is_development_mode = false,
56
- settings_file = nil
59
+ settings_file = nil,
60
+ options = {}
57
61
  )
58
62
  @account_id = account_id
59
63
  @sdk_key = sdk_key
60
64
  @user_storage = user_storage
61
65
  @is_development_mode = is_development_mode
62
66
  @logger = VWO::Logger.get_instance(logger)
67
+ @logger.instance.level = options[:log_level] if (0..5).include?(options[:log_level])
63
68
 
64
69
  unless valid_settings_file?(get_settings(settings_file))
65
70
  @logger.log(
@@ -74,7 +79,10 @@ class VWO
74
79
 
75
80
  @logger.log(
76
81
  LogLevelEnum::DEBUG,
77
- format(LogMessageEnum::DebugMessages::VALID_CONFIGURATION, file: FILE)
82
+ format(
83
+ LogMessageEnum::DebugMessages::VALID_CONFIGURATION,
84
+ file: FILE
85
+ )
78
86
  )
79
87
 
80
88
  # Process the settings file
@@ -87,7 +95,10 @@ class VWO
87
95
  if is_development_mode
88
96
  @logger.log(
89
97
  LogLevelEnum::DEBUG,
90
- format(LogMessageEnum::DebugMessages::SET_DEVELOPMENT_MODE, file: FILE)
98
+ format(
99
+ LogMessageEnum::DebugMessages::SET_DEVELOPMENT_MODE,
100
+ file: FILE
101
+ )
91
102
  )
92
103
  end
93
104
  # Assign event dispatcher
@@ -96,7 +107,10 @@ class VWO
96
107
  # Successfully initialized VWO SDK
97
108
  @logger.log(
98
109
  LogLevelEnum::DEBUG,
99
- format(LogMessageEnum::DebugMessages::SDK_INITIALIZED, file: FILE)
110
+ format(
111
+ LogMessageEnum::DebugMessages::SDK_INITIALIZED,
112
+ file: FILE
113
+ )
100
114
  )
101
115
  end
102
116
 
@@ -122,15 +136,23 @@ class VWO
122
136
  #
123
137
  # @param[String] :campaign_key Unique campaign key
124
138
  # @param[String] :user_id ID assigned to a user
139
+ # @param[Hash] :options Options for custom variables required for segmentation
125
140
  # @return[String|None] If variation is assigned then variation-name
126
141
  # otherwise null in case of user not becoming part
127
142
 
128
- def activate(campaign_key, user_id)
143
+ def activate(campaign_key, user_id, options = {})
144
+ # Retrieve custom variables
145
+ custom_variables = options['custom_variables'] || options[:custom_variables]
146
+
129
147
  # Validate input parameters
130
- unless valid_string?(campaign_key) && valid_string?(user_id)
148
+ unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables))
131
149
  @logger.log(
132
150
  LogLevelEnum::ERROR,
133
- format(LogMessageEnum::ErrorMessages::ACTIVATE_API_MISSING_PARAMS, file: FILE)
151
+ format(
152
+ LogMessageEnum::ErrorMessages::ACTIVATE_API_MISSING_PARAMS,
153
+ api_name: ApiMethods::ACTIVATE,
154
+ file: FILE
155
+ )
134
156
  )
135
157
  return
136
158
  end
@@ -138,7 +160,11 @@ class VWO
138
160
  unless @is_instance_valid
139
161
  @logger.log(
140
162
  LogLevelEnum::ERROR,
141
- format(LogMessageEnum::ErrorMessages::ACTIVATE_API_CONFIG_CORRUPTED, file: FILE)
163
+ format(
164
+ LogMessageEnum::ErrorMessages::API_CONFIG_CORRUPTED,
165
+ file: FILE,
166
+ api_name: ApiMethods::ACTIVATE
167
+ )
142
168
  )
143
169
  return
144
170
  end
@@ -151,23 +177,54 @@ class VWO
151
177
  # Log Campaign as invalid
152
178
  @logger.log(
153
179
  LogLevelEnum::ERROR,
154
- format(LogMessageEnum::ErrorMessages::CAMPAIGN_NOT_RUNNING, file: FILE, campaign_key: campaign_key, api: 'activate')
180
+ format(
181
+ LogMessageEnum::ErrorMessages::CAMPAIGN_NOT_RUNNING,
182
+ file: FILE,
183
+ campaign_key: campaign_key,
184
+ api_name: ApiMethods::ACTIVATE
185
+ )
186
+ )
187
+ return
188
+ end
189
+
190
+ # Get campaign type
191
+ campaign_type = campaign['type']
192
+
193
+ # Validate valid api call
194
+ if campaign_type != CampaignTypes::VISUAL_AB
195
+ @logger.log(
196
+ LogLevelEnum::ERROR,
197
+ format(
198
+ LogMessageEnum::ErrorMessages::INVALID_API,
199
+ file: FILE,
200
+ api_name: ApiMethods::ACTIVATE,
201
+ user_id: user_id,
202
+ campaign_key: campaign_key,
203
+ campaign_type: campaign_type
204
+ )
155
205
  )
156
206
  return
157
207
  end
158
208
 
159
209
  # Once the matching RUNNING campaign is found, assign the
160
210
  # deterministic variation to the user_id provided
161
- variation_id, variation_name = @variation_decider.get_variation(
211
+ variation = @variation_decider.get_variation(
162
212
  user_id,
163
- campaign
213
+ campaign,
214
+ campaign_key,
215
+ custom_variables
164
216
  )
165
217
 
166
218
  # Check if variation_name has been assigned
167
- unless valid_value?(variation_name)
219
+ if variation.nil?
168
220
  @logger.log(
169
221
  LogLevelEnum::INFO,
170
- format(LogMessageEnum::InfoMessages::INVALID_VARIATION_KEY, file: FILE, user_id: user_id, campaign_key: campaign_key)
222
+ format(
223
+ LogMessageEnum::InfoMessages::INVALID_VARIATION_KEY,
224
+ file: FILE,
225
+ user_id: user_id,
226
+ campaign_key: campaign_key
227
+ )
171
228
  )
172
229
  return
173
230
  end
@@ -176,11 +233,22 @@ class VWO
176
233
  impression = create_impression(
177
234
  @settings_file,
178
235
  campaign['id'],
179
- variation_id,
236
+ variation['id'],
180
237
  user_id
181
238
  )
182
239
  @event_dispatcher.dispatch(impression)
183
- variation_name
240
+ variation['name']
241
+ rescue StandardError => e
242
+ @logger.log(
243
+ LogLevelEnum::ERROR,
244
+ format(
245
+ LogMessageEnum::ErrorMessages::API_NOT_WORKING,
246
+ file: FILE,
247
+ api_name: ApiMethods::ACTIVATE,
248
+ exception: e
249
+ )
250
+ )
251
+ nil
184
252
  end
185
253
 
186
254
  # This API method: Gets the variation name assigned for the
@@ -195,25 +263,35 @@ class VWO
195
263
  #
196
264
  # @param[String] :campaign_key Unique campaign key
197
265
  # @param[String] :user_id ID assigned to a user
266
+ # @param[Hash] :options Options for custom variables required for segmentation
198
267
  #
199
268
  # @@return[String|Nil] If variation is assigned then variation-name
200
269
  # Otherwise null in case of user not becoming part
201
270
  #
202
- def get_variation_name(campaign_key, user_id)
203
- # Check for valid arguments
204
- unless valid_string?(campaign_key) && valid_string?(user_id)
205
- # log invalid params
271
+ def get_variation_name(campaign_key, user_id, options = {})
272
+ # Retrieve custom variables
273
+ custom_variables = options['custom_variables'] || options[:custom_variables]
274
+
275
+ # Validate input parameters
276
+ unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables))
206
277
  @logger.log(
207
278
  LogLevelEnum::ERROR,
208
- format(LogMessageEnum::ErrorMessages::GET_VARIATION_NAME_API_MISSING_PARAMS, file: FILE)
279
+ format(
280
+ LogMessageEnum::ErrorMessages::GET_VARIATION_NAME_API_INVALID_PARAMS,
281
+ api_name: ApiMethods::GET_VARIATION_NAME,
282
+ file: FILE
283
+ )
209
284
  )
210
285
  return
211
286
  end
212
-
213
287
  unless @is_instance_valid
214
288
  @logger.log(
215
289
  LogLevelEnum::ERROR,
216
- format(LogMessageEnum::ErrorMessages::ACTIVATE_API_CONFIG_CORRUPTED, file: FILE)
290
+ format(
291
+ LogMessageEnum::ErrorMessages::API_CONFIG_CORRUPTED,
292
+ file: FILE,
293
+ api_name: ApiMethods::GET_VARIATION_NAME
294
+ )
217
295
  )
218
296
  return
219
297
  end
@@ -225,27 +303,62 @@ class VWO
225
303
  if campaign.nil? || campaign['status'] != STATUS_RUNNING
226
304
  @logger.log(
227
305
  LogLevelEnum::ERROR,
228
- format(LogMessageEnum::ErrorMessages::CAMPAIGN_NOT_RUNNING, file: FILE, campaign_key: campaign_key, api: 'get_variation')
306
+ format(
307
+ LogMessageEnum::ErrorMessages::CAMPAIGN_NOT_RUNNING,
308
+ file: FILE,
309
+ campaign_key: campaign_key,
310
+ api_name: ApiMethods::GET_VARIATION_NAME
311
+ )
229
312
  )
230
313
  return
231
314
  end
232
315
 
233
- _variation_id, variation_name = @variation_decider.get_variation(
234
- user_id,
235
- campaign
236
- )
316
+ campaign_type = campaign['type']
317
+
318
+ if campaign_type == CampaignTypes::FEATURE_ROLLOUT
319
+ @logger.log(
320
+ LogLevelEnum::ERROR,
321
+ format(
322
+ LogMessageEnum::ErrorMessages.INVALID_API,
323
+ file: FILE,
324
+ api_name: ApiMethods::GET_VARIATION_NAME,
325
+ user_id: user_id,
326
+ campaign_key: campaign_key,
327
+ campaign_type: campaign_type
328
+ )
329
+ )
330
+ return
331
+ end
332
+
333
+ variation = @variation_decider.get_variation(user_id, campaign, campaign_key, custom_variables)
237
334
 
238
335
  # Check if variation_name has been assigned
239
- unless valid_value?(variation_name)
336
+ unless valid_value?(variation)
240
337
  # log invalid variation key
241
338
  @logger.log(
242
339
  LogLevelEnum::INFO,
243
- format(LogMessageEnum::InfoMessages::INVALID_VARIATION_KEY, file: FILE, user_id: user_id, campaign_key: campaign_key)
340
+ format(
341
+ LogMessageEnum::InfoMessages::INVALID_VARIATION_KEY,
342
+ file: FILE,
343
+ user_id: user_id,
344
+ campaign_key: campaign_key
345
+ )
244
346
  )
245
347
  return
246
348
  end
247
349
 
248
- variation_name
350
+ variation['name']
351
+ rescue StandardError => e
352
+ @logger.log(
353
+ LogLevelEnum::ERROR,
354
+ format(
355
+ LogMessageEnum::ErrorMessages::API_NOT_WORKING,
356
+ file: FILE,
357
+ api_name: ApiMethods::GET_VARIATION_NAME,
358
+ exception: e
359
+ )
360
+ )
361
+ nil
249
362
  end
250
363
 
251
364
  # This API method: Marks the conversion of the campaign
@@ -258,22 +371,30 @@ class VWO
258
371
  #
259
372
  # @param[String] :campaign_key Unique campaign key
260
373
  # @param[String] :user_id ID assigned to a user
261
- # @param[String] :goal_identifier Unique campaign's goal identifier
262
- # @param[Numeric|String] :revenue_value Revenue value for revenue-type goal
374
+ # @param[String] :goal_identifier Unique campaign's goal identifier
375
+ # @param[Array|Hash] :args Contains revenue value and custom variables
376
+ # @param[Numeric|String] :revenue_value It is the revenue generated on triggering the goal
263
377
  #
264
378
  def track(campaign_key, user_id, goal_identifier, *args)
265
379
  if args[0].is_a?(Hash)
266
- revenue_value = args[0]['revenue_value']
380
+ revenue_value = args[0]['revenue_value'] || args[0][:revenue_value]
381
+ custom_variables = args[0]['custom_variables'] || args[0][:custom_variables]
267
382
  elsif args.is_a?(Array)
268
383
  revenue_value = args[0]
384
+ custom_variables = nil
269
385
  end
270
386
 
271
387
  # Check for valid args
272
- unless valid_string?(campaign_key) && valid_string?(user_id) && valid_string?(goal_identifier)
388
+ unless valid_string?(campaign_key) && valid_string?(user_id) && valid_string?(goal_identifier) &&
389
+ (custom_variables.nil? || valid_hash?(custom_variables)) || (revenue_value.nil? || valid_basic_data_type?(revenue_value))
273
390
  # log invalid params
274
391
  @logger.log(
275
392
  LogLevelEnum::ERROR,
276
- format(LogMessageEnum::ErrorMessages::TRACK_API_MISSING_PARAMS, file: FILE)
393
+ format(
394
+ LogMessageEnum::ErrorMessages::TRACK_API_INVALID_PARAMS,
395
+ file: FILE,
396
+ api_name: ApiMethods.TRACK
397
+ )
277
398
  )
278
399
  return false
279
400
  end
@@ -281,7 +402,11 @@ class VWO
281
402
  unless @is_instance_valid
282
403
  @logger.log(
283
404
  LogLevelEnum::ERROR,
284
- format(LogMessageEnum::ErrorMessages::ACTIVATE_API_CONFIG_CORRUPTED, file: FILE)
405
+ format(
406
+ LogMessageEnum::ErrorMessages::API_CONFIG_CORRUPTED,
407
+ file: FILE,
408
+ api_name: ApiMethods::TRACK
409
+ )
285
410
  )
286
411
  return false
287
412
  end
@@ -290,33 +415,55 @@ class VWO
290
415
  campaign = get_campaign(@settings_file, campaign_key)
291
416
 
292
417
  # Validate campaign
293
- if campaign.nil? || campaign['status'] != STATUS_RUNNING
418
+ if campaign.nil? || (campaign['status'] != STATUS_RUNNING)
294
419
  # log error
295
420
  @logger.log(
296
421
  LogLevelEnum::ERROR,
297
- format(LogMessageEnum::ErrorMessages::CAMPAIGN_NOT_RUNNING, file: FILE, campaign_key: campaign_key, api: 'track')
422
+ format(
423
+ LogMessageEnum::ErrorMessages::CAMPAIGN_NOT_RUNNING,
424
+ file: FILE,
425
+ campaign_key: campaign_key,
426
+ api_name: ApiMethods::TRACK
427
+ )
298
428
  )
299
429
  return false
300
430
  end
301
431
 
302
- campaign_id = campaign['id']
303
- variation_id, variation_name = @variation_decider.get_variation_allotted(user_id, campaign)
432
+ campaign_type = campaign['type']
304
433
 
305
- if variation_name
306
- goal = get_campaign_goal(@settings_file, campaign['key'], goal_identifier)
434
+ if campaign_type == CampaignTypes::FEATURE_ROLLOUT
435
+ @logger.log(
436
+ LogLevelEnum::ERROR,
437
+ format(
438
+ LogMessageEnum::ErrorMessages::INVALID_API,
439
+ file: FILE,
440
+ api_name: ApiMethods::TRACK,
441
+ user_id: user_id,
442
+ campaign_key: campaign_key,
443
+ campaign_type: campaign_type
444
+ )
445
+ )
446
+ return false
447
+ end
307
448
 
449
+ variation = @variation_decider.get_variation(user_id, campaign, campaign_key, custom_variables)
450
+
451
+ if variation
452
+ goal = get_campaign_goal(campaign, goal_identifier)
308
453
  if goal.nil?
309
454
  @logger.log(
310
455
  LogLevelEnum::ERROR,
311
456
  format(
312
457
  LogMessageEnum::ErrorMessages::TRACK_API_GOAL_NOT_FOUND,
313
- file: FILE, goal_identifier: goal_identifier,
458
+ file: FILE,
459
+ goal_identifier: goal_identifier,
314
460
  user_id: user_id,
315
- campaign_key: campaign_key
461
+ campaign_key: campaign_key,
462
+ api_name: ApiMethods::TRACK
316
463
  )
317
464
  )
318
465
  return false
319
- elsif goal['type'] == GOALTYPES::REVENUE && !valid_value?(revenue_value)
466
+ elsif goal['type'] == GoalTypes::REVENUE && !valid_value?(revenue_value)
320
467
  @logger.log(
321
468
  LogLevelEnum::ERROR,
322
469
  format(
@@ -324,25 +471,433 @@ class VWO
324
471
  file: FILE,
325
472
  user_id: user_id,
326
473
  goal_identifier: goal_identifier,
327
- campaign_key: campaign_key
474
+ campaign_key: campaign_key,
475
+ api_name: ApiMethods::TRACK
328
476
  )
329
477
  )
330
478
  return false
479
+ elsif goal['type'] == GoalTypes::CUSTOM
480
+ revenue_value = nil
331
481
  end
332
-
333
- revenue_value = nil if goal['type'] == GOALTYPES::CUSTOM
334
-
335
482
  impression = create_impression(
336
483
  @settings_file,
337
- campaign_id,
338
- variation_id,
484
+ campaign['id'],
485
+ variation['id'],
339
486
  user_id,
340
487
  goal['id'],
341
488
  revenue_value
342
489
  )
343
490
  @event_dispatcher.dispatch(impression)
491
+
492
+ @logger.log(
493
+ LogLevelEnum::INFO,
494
+ format(
495
+ LogMessageEnum::InfoMessages::MAIN_KEYS_FOR_IMPRESSION,
496
+ file: FILE,
497
+ campaign_id: impression[:experiment_id],
498
+ user_id: impression[:uId],
499
+ account_id: impression[:account_id],
500
+ variation_id: impression[:combination]
501
+ )
502
+ )
344
503
  return true
345
504
  end
346
505
  false
506
+ rescue StandardError => e
507
+ @logger.log(
508
+ LogLevelEnum::ERROR,
509
+ format(
510
+ LogMessageEnum::ErrorMessages::API_NOT_WORKING,
511
+ file: FILE,
512
+ api_name: ApiMethods::TRACK,
513
+ exception: e
514
+ )
515
+ )
516
+ false
517
+ end
518
+
519
+ # This API method: Identifies whether the user becomes a part of feature rollout/test or not.
520
+ # 1. Validates the arguments being passed
521
+ # 2. Checks if user is eligible to get bucketed into the feature test/rollout,
522
+ # 3. Assigns the deterministic variation to the user(based on userId),
523
+ # If user becomes part of feature test/rollout
524
+ # If UserStorage is used, it will look into it for the variation and if found, no further processing is done
525
+ #
526
+ # @param[String] :campaign_key Unique campaign key
527
+ # @param[String] :user_id ID assigned to a user
528
+ # @param[Hash] :custom_variables Pass it through options as custom_variables={}
529
+ #
530
+ # @return[Boolean] true if user becomes part of feature test/rollout, otherwise false.
531
+
532
+ def feature_enabled?(campaign_key, user_id, options = {})
533
+ # Retrieve custom variables
534
+ custom_variables = options['custom_variables'] || options[:custom_variables]
535
+
536
+ # Validate input parameters
537
+ unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables))
538
+ @logger.log(
539
+ LogLevelEnum::ERROR,
540
+ format(
541
+ LogMessageEnum::ErrorMessages::IS_FEATURE_ENABLED_API_INVALID_PARAMS,
542
+ api_name: ApiMethods::IS_FEATURE_ENABLED,
543
+ file: FILE
544
+ )
545
+ )
546
+ return false
547
+ end
548
+ unless @is_instance_valid
549
+ @logger.log(
550
+ LogLevelEnum::ERROR,
551
+ format(
552
+ LogMessageEnum::ErrorMessages::API_CONFIG_CORRUPTED,
553
+ file: FILE,
554
+ api_name: ApiMethods::IS_FEATURE_ENABLED
555
+ )
556
+ )
557
+ return false
558
+ end
559
+
560
+ # Get the campaign settings
561
+ campaign = get_campaign(@settings_file, campaign_key)
562
+
563
+ # Validate campaign
564
+ unless campaign && campaign['status'] == STATUS_RUNNING
565
+ # log error
566
+ @logger.log(
567
+ LogLevelEnum::ERROR,
568
+ format(
569
+ LogMessageEnum::ErrorMessages::CAMPAIGN_NOT_RUNNING,
570
+ file: FILE,
571
+ campaign_key: campaign_key,
572
+ api_name: ApiMethods::IS_FEATURE_ENABLED
573
+ )
574
+ )
575
+ return false
576
+ end
577
+
578
+ # Validate campaign_type
579
+ campaign_type = campaign['type']
580
+
581
+ if campaign_type == CampaignTypes::VISUAL_AB
582
+ @logger.log(
583
+ LogLevelEnum::ERROR,
584
+ format(
585
+ LogMessageEnum::ErrorMessages::INVALID_API,
586
+ file: FILE,
587
+ api_name: ApiMethods::IS_FEATURE_ENABLED,
588
+ user_id: user_id,
589
+ campaign_key: campaign_key,
590
+ campaign_type: campaign_type
591
+ )
592
+ )
593
+ return false
594
+ end
595
+
596
+ # Get variation
597
+ variation = @variation_decider.get_variation(user_id, campaign, campaign_key, custom_variables)
598
+
599
+ # If no variation, did not become part of feature_test/rollout
600
+ return false unless variation
601
+
602
+ # if campaign type is feature_test Send track call to server
603
+ if campaign_type == CampaignTypes::FEATURE_TEST
604
+ impression = create_impression(
605
+ @settings_file,
606
+ campaign['id'],
607
+ variation['id'],
608
+ user_id
609
+ )
610
+
611
+ @event_dispatcher.dispatch(impression)
612
+ @logger.log(
613
+ LogLevelEnum::INFO,
614
+ format(
615
+ LogMessageEnum::InfoMessages::MAIN_KEYS_FOR_IMPRESSION,
616
+ file: FILE,
617
+ campaign_id: impression[:experiment_id],
618
+ user_id: impression[:uId],
619
+ account_id: impression[:account_id],
620
+ variation_id: impression[:combination]
621
+ )
622
+ )
623
+ result = variation['isFeatureEnabled']
624
+ if result
625
+ @logger.log(
626
+ LogLevelEnum::INFO,
627
+ format(
628
+ LogMessageEnum::InfoMessages::FEATURE_ENABLED_FOR_USER,
629
+ file: FILE,
630
+ user_id: user_id,
631
+ feature_key: campaign_key,
632
+ api_name: ApiMethods::IS_FEATURE_ENABLED
633
+ )
634
+ )
635
+ else
636
+ @logger.log(
637
+ LogLevelEnum::INFO,
638
+ format(
639
+ LogMessageEnum::InfoMessages::FEATURE_NOT_ENABLED_FOR_USER,
640
+ file: FILE,
641
+ user_id: user_id,
642
+ feature_key: campaign_key,
643
+ api_name: ApiMethods::IS_FEATURE_ENABLED
644
+ )
645
+ )
646
+ end
647
+ return result
648
+ end
649
+ true
650
+ rescue StandardError => e
651
+ @logger.log(
652
+ LogLevelEnum::ERROR,
653
+ format(
654
+ LogMessageEnum::ErrorMessages::API_NOT_WORKING,
655
+ file: FILE,
656
+ api_name: ApiMethods::IS_FEATURE_ENABLED,
657
+ exception: e
658
+ )
659
+ )
660
+ false
661
+ end
662
+
663
+ # Returns the feature variable corresponding to the variable_key
664
+ # passed. It typecasts the value to the corresponding value type
665
+ # found in settings_file
666
+ #
667
+ # 1. Validates the arguments being passed
668
+ # 2. Checks if user is eligible to get bucketed into the feature test/rollout,
669
+ # 3. Assigns the deterministic variation to the user(based on userId),
670
+ # If user becomes part of campaign
671
+ # If UserStorage is used, it will look into it for the variation and if found, no further processing is done
672
+ # 4. Retrieves the corresponding variable from variation assigned.
673
+ #
674
+ # @param[String] :campaign_key Unique campaign key
675
+ # @param[String] :variable_key Variable key
676
+ # @param[String] :user_id ID assigned to a user
677
+ # @param[Hash] :custom_variables Pass it through options as custom_variables={}
678
+ #
679
+ # @return[Boolean, String, Integer, Float, nil) If variation is assigned then variable corresponding to variation assigned else nil
680
+ #
681
+
682
+ def get_feature_variable_value(campaign_key, variable_key, user_id, options = {})
683
+ # Retrieve custom variables
684
+ custom_variables = options['custom_variables'] || options[:custom_variables]
685
+
686
+ unless valid_string?(campaign_key) && valid_string?(variable_key) && valid_string?(user_id) &&
687
+ (custom_variables.nil? || valid_hash?(custom_variables))
688
+ @logger.log(
689
+ LogLevelEnum::ERROR,
690
+ format(
691
+ LogMessageEnum::ErrorMessages::GET_FEATURE_VARIABLE_VALUE_API_INVALID_PARAMS,
692
+ file: FILE,
693
+ api_name: ApiMethods::GET_FEATURE_VARIABLE_VALUE
694
+ )
695
+ )
696
+ return
697
+ end
698
+
699
+ unless @is_instance_valid
700
+ @logger.log(
701
+ LogLevelEnum::ERROR,
702
+ format(
703
+ LogMessageEnum::ErrorMessages::API_CONFIG_CORRUPTED,
704
+ file: FILE,
705
+ api_name: ApiMethods.GET_FEATURE_VARIABLE_VALUE
706
+ )
707
+ )
708
+ return
709
+ end
710
+
711
+ # Get the campaign settings
712
+ campaign = get_campaign(@settings_file, campaign_key)
713
+
714
+ # Validate campaign
715
+ unless campaign && campaign['status'] == STATUS_RUNNING
716
+ # log error
717
+ @logger.log(
718
+ LogLevelEnum::ERROR,
719
+ format(
720
+ LogMessageEnum::ErrorMessages::CAMPAIGN_NOT_RUNNING,
721
+ file: FILE,
722
+ campaign_key: campaign_key,
723
+ api_name: ApiMethods::GET_FEATURE_VARIABLE_VALUE
724
+ )
725
+ )
726
+ return
727
+ end
728
+
729
+ campaign_type = campaign['type']
730
+
731
+ if campaign_type == CampaignTypes::VISUAL_AB
732
+ @logger.log(
733
+ LogLevelEnum::ERROR,
734
+ format(
735
+ LogMessageEnum::ErrorMessages::INVALID_API,
736
+ file: FILE,
737
+ api_name: ApiMethods::GET_FEATURE_VARIABLE_VALUE,
738
+ campaign_key: campaign_key,
739
+ campaign_type: campaign_type,
740
+ user_id: user_id
741
+ )
742
+ )
743
+ return
744
+ end
745
+
746
+ variation = @variation_decider.get_variation(user_id, campaign, campaign_key, custom_variables)
747
+
748
+ # Check if variation has been assigned to user
749
+ return unless variation
750
+
751
+ if campaign_type == CampaignTypes::FEATURE_ROLLOUT
752
+ variables = campaign['variables']
753
+ elsif campaign_type == CampaignTypes::FEATURE_TEST
754
+ if !variation['isFeatureEnabled']
755
+ @logger.log(
756
+ LogLevelEnum::INFO,
757
+ format(
758
+ LogMessageEnum::InfoMessages::FEATURE_NOT_ENABLED_FOR_USER,
759
+ file: FILE,
760
+ feature_key: campaign_key,
761
+ user_id: user_id,
762
+ api_name: ApiMethods::GET_FEATURE_VARIABLE_VALUE
763
+ )
764
+ )
765
+ variation = get_control_variation(campaign)
766
+ else
767
+ @logger.log(
768
+ LogLevelEnum::INFO,
769
+ format(
770
+ LogMessageEnum::InfoMessages::FEATURE_ENABLED_FOR_USER,
771
+ file: FILE,
772
+ feature_key: campaign_key,
773
+ user_id: user_id,
774
+ api_name: ApiMethods::GET_FEATURE_VARIABLE_VALUE
775
+ )
776
+ )
777
+ end
778
+ variables = variation['variables']
779
+ end
780
+ variable = get_variable(variables, variable_key)
781
+
782
+ unless variable
783
+ # Log variable not found
784
+ @logger.log(
785
+ LogLevelEnum::ERROR,
786
+ format(
787
+ LogMessageEnum::ErrorMessages::VARIABLE_NOT_FOUND,
788
+ file: FILE,
789
+ variable_key: variable_key,
790
+ campaign_key: campaign_key,
791
+ campaign_type: campaign_type,
792
+ user_id: user_id,
793
+ api_name: ApiMethods::GET_FEATURE_VARIABLE_VALUE
794
+ )
795
+ )
796
+ return
797
+ end
798
+
799
+ @logger.log(
800
+ LogLevelEnum::INFO,
801
+ format(
802
+ LogMessageEnum::InfoMessages::VARIABLE_FOUND,
803
+ file: FILE,
804
+ variable_key: variable_key,
805
+ variable_value: variable['value'],
806
+ campaign_key: campaign_key,
807
+ campaign_type: campaign_type,
808
+ user_id: user_id,
809
+ api_name: ApiMethods::GET_FEATURE_VARIABLE_VALUE
810
+ )
811
+ )
812
+ get_type_casted_feature_value(variable['value'], variable['type'])
813
+ rescue StandardError => e
814
+ @logger.log(
815
+ LogLevelEnum::ERROR,
816
+ format(
817
+ LogMessageEnum::ErrorMessages::API_NOT_WORKING,
818
+ file: FILE,
819
+ api_name: ApiMethods::GET_FEATURE_VARIABLE_VALUE,
820
+ exception: e
821
+ )
822
+ )
823
+ nil
824
+ end
825
+
826
+ # This API method: Makes a call to our server to store the tag_values
827
+ # 1. Validates the arguments being passed
828
+ # 2. Send a call to our server
829
+ # @param[String] :tag_key key name of the tag
830
+ # @param[String] :tag_value Value of the tag
831
+ # @param[String] :user_id ID of the user for which value should be stored
832
+ # @return true if call is made successfully, else false
833
+
834
+ def push(tag_key, tag_value, user_id)
835
+ unless valid_string?(tag_key) && valid_string?(tag_value) && valid_string?(user_id)
836
+ @logger.log(
837
+ LogLevelEnum::ERROR,
838
+ format(
839
+ LogMessageEnum::ErrorMessages::PUSH_API_INVALID_PARAMS,
840
+ file: FILE,
841
+ api_name: ApiMethods::PUSH
842
+ )
843
+ )
844
+ return false
845
+ end
846
+
847
+ if tag_key.length > PushApi::TAG_KEY_LENGTH
848
+ @logger.log(
849
+ LogLevelEnum::ERROR,
850
+ format(
851
+ LogMessageEnum::ErrorMessages::TAG_KEY_LENGTH_EXCEEDED,
852
+ file: FILE,
853
+ user_id: user_id,
854
+ tag_key: tag_key,
855
+ api_name: ApiMethods::PUSH
856
+ )
857
+ )
858
+ return false
859
+ end
860
+
861
+ if tag_value.length > PushApi::TAG_VALUE_LENGTH
862
+ @logger.log(
863
+ LogLevelEnum::ERROR,
864
+ format(
865
+ LogMessageEnum::ErrorMessages::TAG_VALUE_LENGTH_EXCEEDED,
866
+ file: FILE,
867
+ user_id: user_id,
868
+ tag_value: tag_value,
869
+ api_name: ApiMethods::PUSH
870
+ )
871
+ )
872
+ return false
873
+ end
874
+
875
+ impression = get_url_params(@settings_file, tag_key, tag_value, user_id)
876
+
877
+ @event_dispatcher.dispatch(impression)
878
+
879
+ @logger.log(
880
+ LogLevelEnum::INFO,
881
+ format(
882
+ LogMessageEnum::InfoMessages::MAIN_KEYS_FOR_PUSH_API,
883
+ file: FILE,
884
+ u: impression['u'],
885
+ user_id: impression['uId'],
886
+ account_id: impression['account_id'],
887
+ tags: impression['tags']
888
+ )
889
+ )
890
+ true
891
+ rescue StandardError => e
892
+ @logger.log(
893
+ LogLevelEnum::ERROR,
894
+ format(
895
+ LogMessageEnum::ErrorMessages::API_NOT_WORKING,
896
+ file: FILE,
897
+ api_name: ApiMethods::PUSH,
898
+ exception: e
899
+ )
900
+ )
901
+ false
347
902
  end
348
903
  end