optimizely-sdk 3.0.0 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/optimizely.rb +83 -29
- data/lib/optimizely/decision_service.rb +9 -6
- data/lib/optimizely/helpers/constants.rb +7 -0
- data/lib/optimizely/notification_center.rb +3 -1
- data/lib/optimizely/project_config.rb +15 -0
- data/lib/optimizely/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5bbc06065e5e4e126182cea9c01e801f3f6c3e2
|
4
|
+
data.tar.gz: a7be551c6fabb0e6f93d85e531d3d0e360403194
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f24e739480c517e98df5cf98cb0412716683045e389fc253f7e4270226a235ade6f54c7a83647c5c0c4b645f84aa496a3edea70653fd4c2186e7c044c4da6e7
|
7
|
+
data.tar.gz: 702fb0aa34bd14ef60aaea54180b8a0b06772c85413574f3218c9e7b2729e8e41062da49cf2e9a3d78ae709fa1cc8ff1fc636a1aa98199b2b8bab7c0a46e82ec
|
data/lib/optimizely.rb
CHANGED
@@ -137,18 +137,30 @@ module Optimizely
|
|
137
137
|
}, @logger, Logger::ERROR
|
138
138
|
)
|
139
139
|
|
140
|
+
experiment = @config.get_experiment_from_key(experiment_key)
|
141
|
+
return nil if experiment.nil?
|
142
|
+
|
140
143
|
unless user_inputs_valid?(attributes)
|
141
144
|
@logger.log(Logger::INFO, "Not activating user '#{user_id}.")
|
142
145
|
return nil
|
143
146
|
end
|
144
147
|
|
145
148
|
variation_id = @decision_service.get_variation(experiment_key, user_id, attributes)
|
149
|
+
variation = @config.get_variation_from_id(experiment_key, variation_id) unless variation_id.nil?
|
150
|
+
variation_key = variation['key'] if variation
|
151
|
+
decision_notification_type = if @config.feature_experiment?(experiment['id'])
|
152
|
+
Helpers::Constants::DECISION_NOTIFICATION_TYPES['FEATURE_TEST']
|
153
|
+
else
|
154
|
+
Helpers::Constants::DECISION_NOTIFICATION_TYPES['AB_TEST']
|
155
|
+
end
|
156
|
+
@notification_center.send_notifications(
|
157
|
+
NotificationCenter::NOTIFICATION_TYPES[:DECISION],
|
158
|
+
decision_notification_type, user_id, (attributes || {}),
|
159
|
+
experiment_key: experiment_key,
|
160
|
+
variation_key: variation_key
|
161
|
+
)
|
146
162
|
|
147
|
-
|
148
|
-
variation = @config.get_variation_from_id(experiment_key, variation_id)
|
149
|
-
return variation['key'] if variation
|
150
|
-
end
|
151
|
-
nil
|
163
|
+
variation_key
|
152
164
|
end
|
153
165
|
|
154
166
|
# Force a user into a variation for a given experiment.
|
@@ -257,30 +269,45 @@ module Optimizely
|
|
257
269
|
end
|
258
270
|
|
259
271
|
decision = @decision_service.get_variation_for_feature(feature_flag, user_id, attributes)
|
260
|
-
if decision.nil?
|
261
|
-
@logger.log(Logger::INFO,
|
262
|
-
"Feature '#{feature_flag_key}' is not enabled for user '#{user_id}'.")
|
263
|
-
return false
|
264
|
-
end
|
265
272
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
+
feature_enabled = false
|
274
|
+
source_string = Optimizely::DecisionService::DECISION_SOURCES['ROLLOUT']
|
275
|
+
if decision.is_a?(Optimizely::DecisionService::Decision)
|
276
|
+
variation = decision['variation']
|
277
|
+
feature_enabled = variation['featureEnabled']
|
278
|
+
if decision.source == Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST']
|
279
|
+
source_string = Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST']
|
280
|
+
source_info = {
|
281
|
+
experiment_key: decision.experiment['key'],
|
282
|
+
variation_key: variation['key']
|
283
|
+
}
|
284
|
+
# Send event if Decision came from an experiment.
|
285
|
+
send_impression(decision.experiment, variation['key'], user_id, attributes)
|
286
|
+
else
|
287
|
+
@logger.log(Logger::DEBUG,
|
288
|
+
"The user '#{user_id}' is not being experimented on in feature '#{feature_flag_key}'.")
|
289
|
+
end
|
273
290
|
end
|
274
291
|
|
275
|
-
|
292
|
+
@notification_center.send_notifications(
|
293
|
+
NotificationCenter::NOTIFICATION_TYPES[:DECISION],
|
294
|
+
Helpers::Constants::DECISION_NOTIFICATION_TYPES['FEATURE'],
|
295
|
+
user_id, (attributes || {}),
|
296
|
+
feature_key: feature_flag_key,
|
297
|
+
feature_enabled: feature_enabled,
|
298
|
+
source: source_string,
|
299
|
+
source_info: source_info || {}
|
300
|
+
)
|
301
|
+
|
302
|
+
if feature_enabled == true
|
276
303
|
@logger.log(Logger::INFO,
|
277
304
|
"Feature '#{feature_flag_key}' is enabled for user '#{user_id}'.")
|
278
305
|
return true
|
279
|
-
else
|
280
|
-
@logger.log(Logger::INFO,
|
281
|
-
"Feature '#{feature_flag_key}' is not enabled for user '#{user_id}'.")
|
282
|
-
return false
|
283
306
|
end
|
307
|
+
|
308
|
+
@logger.log(Logger::INFO,
|
309
|
+
"Feature '#{feature_flag_key}' is not enabled for user '#{user_id}'.")
|
310
|
+
false
|
284
311
|
end
|
285
312
|
|
286
313
|
# Gets keys of all feature flags which are enabled for the user.
|
@@ -461,25 +488,40 @@ module Optimizely
|
|
461
488
|
# Error message logged in ProjectConfig- get_feature_flag_from_key
|
462
489
|
return nil if variable.nil?
|
463
490
|
|
491
|
+
feature_enabled = false
|
464
492
|
# Returns nil if type differs
|
465
493
|
if variable['type'] != variable_type
|
466
494
|
@logger.log(Logger::WARN,
|
467
495
|
"Requested variable as type '#{variable_type}' but variable '#{variable_key}' is of type '#{variable['type']}'.")
|
468
496
|
return nil
|
469
497
|
else
|
498
|
+
source_string = Optimizely::DecisionService::DECISION_SOURCES['ROLLOUT']
|
470
499
|
decision = @decision_service.get_variation_for_feature(feature_flag, user_id, attributes)
|
471
500
|
variable_value = variable['defaultValue']
|
472
501
|
if decision
|
473
502
|
variation = decision['variation']
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
503
|
+
if decision['source'] == Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST']
|
504
|
+
source_info = {
|
505
|
+
experiment_key: decision.experiment['key'],
|
506
|
+
variation_key: variation['key']
|
507
|
+
}
|
508
|
+
source_string = Optimizely::DecisionService::DECISION_SOURCES['FEATURE_TEST']
|
509
|
+
end
|
510
|
+
feature_enabled = variation['featureEnabled']
|
511
|
+
if feature_enabled == true
|
512
|
+
variation_variable_usages = @config.variation_id_to_variable_usage_map[variation['id']]
|
513
|
+
variable_id = variable['id']
|
514
|
+
if variation_variable_usages&.key?(variable_id)
|
515
|
+
variable_value = variation_variable_usages[variable_id]['value']
|
516
|
+
@logger.log(Logger::INFO,
|
517
|
+
"Got variable value '#{variable_value}' for variable '#{variable_key}' of feature flag '#{feature_flag_key}'.")
|
518
|
+
else
|
519
|
+
@logger.log(Logger::DEBUG,
|
520
|
+
"Variable '#{variable_key}' is not used in variation '#{variation['key']}'. Returning the default variable value '#{variable_value}'.")
|
521
|
+
end
|
480
522
|
else
|
481
523
|
@logger.log(Logger::DEBUG,
|
482
|
-
"
|
524
|
+
"Feature '#{feature_flag_key}' for variation '#{variation['key']}' is not enabled. Returning the default variable value '#{variable_value}'.")
|
483
525
|
end
|
484
526
|
else
|
485
527
|
@logger.log(Logger::INFO,
|
@@ -489,6 +531,18 @@ module Optimizely
|
|
489
531
|
|
490
532
|
variable_value = Helpers::VariableType.cast_value_to_type(variable_value, variable_type, @logger)
|
491
533
|
|
534
|
+
@notification_center.send_notifications(
|
535
|
+
NotificationCenter::NOTIFICATION_TYPES[:DECISION],
|
536
|
+
Helpers::Constants::DECISION_NOTIFICATION_TYPES['FEATURE_VARIABLE'], user_id, (attributes || {}),
|
537
|
+
feature_key: feature_flag_key,
|
538
|
+
feature_enabled: feature_enabled,
|
539
|
+
source: source_string,
|
540
|
+
variable_key: variable_key,
|
541
|
+
variable_type: variable_type,
|
542
|
+
variable_value: variable_value,
|
543
|
+
source_info: source_info || {}
|
544
|
+
)
|
545
|
+
|
492
546
|
variable_value
|
493
547
|
end
|
494
548
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2017-
|
4
|
+
# Copyright 2017-2019, Optimizely and contributors
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -35,8 +35,11 @@ module Optimizely
|
|
35
35
|
attr_reader :config
|
36
36
|
|
37
37
|
Decision = Struct.new(:experiment, :variation, :source)
|
38
|
-
|
39
|
-
|
38
|
+
|
39
|
+
DECISION_SOURCES = {
|
40
|
+
'FEATURE_TEST' => 'feature-test',
|
41
|
+
'ROLLOUT' => 'rollout'
|
42
|
+
}.freeze
|
40
43
|
|
41
44
|
def initialize(config, user_profile_service = nil)
|
42
45
|
@config = config
|
@@ -172,7 +175,7 @@ module Optimizely
|
|
172
175
|
Logger::INFO,
|
173
176
|
"The user '#{user_id}' is bucketed into experiment '#{experiment_key}' of feature '#{feature_flag_key}'."
|
174
177
|
)
|
175
|
-
return Decision.new(experiment, variation,
|
178
|
+
return Decision.new(experiment, variation, DECISION_SOURCES['FEATURE_TEST'])
|
176
179
|
end
|
177
180
|
|
178
181
|
@config.logger.log(
|
@@ -236,7 +239,7 @@ module Optimizely
|
|
236
239
|
|
237
240
|
# Evaluate if user satisfies the traffic allocation for this rollout rule
|
238
241
|
variation = @bucketer.bucket(rollout_rule, bucketing_id, user_id)
|
239
|
-
return Decision.new(rollout_rule, variation,
|
242
|
+
return Decision.new(rollout_rule, variation, DECISION_SOURCES['ROLLOUT']) unless variation.nil?
|
240
243
|
|
241
244
|
break
|
242
245
|
end
|
@@ -255,7 +258,7 @@ module Optimizely
|
|
255
258
|
return nil
|
256
259
|
end
|
257
260
|
variation = @bucketer.bucket(everyone_else_experiment, bucketing_id, user_id)
|
258
|
-
return Decision.new(everyone_else_experiment, variation,
|
261
|
+
return Decision.new(everyone_else_experiment, variation, DECISION_SOURCES['ROLLOUT']) unless variation.nil?
|
259
262
|
|
260
263
|
nil
|
261
264
|
end
|
@@ -352,6 +352,13 @@ module Optimizely
|
|
352
352
|
'UNKNOWN_MATCH_TYPE' => 'Audience condition %s uses an unknown match type. You may need ' \
|
353
353
|
'to upgrade to a newer release of the Optimizely SDK.'
|
354
354
|
}.freeze
|
355
|
+
|
356
|
+
DECISION_NOTIFICATION_TYPES = {
|
357
|
+
'AB_TEST' => 'ab-test',
|
358
|
+
'FEATURE' => 'feature',
|
359
|
+
'FEATURE_TEST' => 'feature-test',
|
360
|
+
'FEATURE_VARIABLE' => 'feature-variable'
|
361
|
+
}.freeze
|
355
362
|
end
|
356
363
|
end
|
357
364
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2017-
|
4
|
+
# Copyright 2017-2019, Optimizely and contributors
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -21,7 +21,9 @@ module Optimizely
|
|
21
21
|
attr_reader :notifications, :notification_id
|
22
22
|
|
23
23
|
NOTIFICATION_TYPES = {
|
24
|
+
# DEPRECATED: ACTIVATE notification type is deprecated since relase 3.1.0.
|
24
25
|
ACTIVATE: 'ACTIVATE: experiment, user_id, attributes, variation, event',
|
26
|
+
DECISION: 'DECISION: type, user_id, attributes, decision_info',
|
25
27
|
TRACK: 'TRACK: event_key, user_id, attributes, event_tags, event'
|
26
28
|
}.freeze
|
27
29
|
|
@@ -47,6 +47,7 @@ module Optimizely
|
|
47
47
|
attr_reader :attribute_key_map
|
48
48
|
attr_reader :audience_id_map
|
49
49
|
attr_reader :event_key_map
|
50
|
+
attr_reader :experiment_feature_map
|
50
51
|
attr_reader :experiment_id_map
|
51
52
|
attr_reader :experiment_key_map
|
52
53
|
attr_reader :feature_flag_key_map
|
@@ -140,9 +141,13 @@ module Optimizely
|
|
140
141
|
@variation_key_map[key] = generate_key_map(variations, 'key')
|
141
142
|
end
|
142
143
|
@feature_flag_key_map = generate_key_map(@feature_flags, 'key')
|
144
|
+
@experiment_feature_map = {}
|
143
145
|
@feature_variable_key_map = {}
|
144
146
|
@feature_flag_key_map.each do |key, feature_flag|
|
145
147
|
@feature_variable_key_map[key] = generate_key_map(feature_flag['variables'], 'key')
|
148
|
+
feature_flag['experimentIds'].each do |experiment_id|
|
149
|
+
@experiment_feature_map[experiment_id] = [feature_flag['id']]
|
150
|
+
end
|
146
151
|
end
|
147
152
|
end
|
148
153
|
|
@@ -451,6 +456,16 @@ module Optimizely
|
|
451
456
|
nil
|
452
457
|
end
|
453
458
|
|
459
|
+
def feature_experiment?(experiment_id)
|
460
|
+
# Determines if given experiment is a feature test.
|
461
|
+
#
|
462
|
+
# experiment_id - String experiment ID
|
463
|
+
#
|
464
|
+
# Returns true if experiment belongs to any feature,
|
465
|
+
# false otherwise.
|
466
|
+
@experiment_feature_map.key?(experiment_id)
|
467
|
+
end
|
468
|
+
|
454
469
|
private
|
455
470
|
|
456
471
|
def generate_key_map(array, key)
|
data/lib/optimizely/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: optimizely-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Optimizely
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-03
|
11
|
+
date: 2019-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -184,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
184
184
|
version: '0'
|
185
185
|
requirements: []
|
186
186
|
rubyforge_project:
|
187
|
-
rubygems_version: 2.
|
187
|
+
rubygems_version: 2.5.1
|
188
188
|
signing_key:
|
189
189
|
specification_version: 4
|
190
190
|
summary: Ruby SDK for Optimizely's testing framework
|