optimizely-sdk 3.0.0 → 3.1.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 +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
|