optimizely-sdk 2.1.1 → 3.0.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 +19 -47
- data/lib/optimizely/audience.rb +67 -13
- data/lib/optimizely/bucketer.rb +4 -1
- data/lib/optimizely/condition_tree_evaluator.rb +121 -0
- data/lib/optimizely/custom_attribute_condition_evaluator.rb +273 -0
- data/lib/optimizely/decision_service.rb +14 -9
- data/lib/optimizely/event_builder.rb +17 -26
- data/lib/optimizely/helpers/constants.rb +26 -1
- data/lib/optimizely/helpers/validator.rb +57 -4
- data/lib/optimizely/notification_center.rb +1 -0
- data/lib/optimizely/project_config.rb +30 -20
- data/lib/optimizely/version.rb +2 -2
- metadata +47 -18
- data/lib/optimizely/condition.rb +0 -135
@@ -166,6 +166,7 @@ module Optimizely
|
|
166
166
|
variation_id = get_variation(experiment_key, user_id, attributes)
|
167
167
|
|
168
168
|
next unless variation_id
|
169
|
+
|
169
170
|
variation = @config.variation_id_map[experiment_key][variation_id]
|
170
171
|
@config.logger.log(
|
171
172
|
Logger::INFO,
|
@@ -236,6 +237,7 @@ module Optimizely
|
|
236
237
|
# Evaluate if user satisfies the traffic allocation for this rollout rule
|
237
238
|
variation = @bucketer.bucket(rollout_rule, bucketing_id, user_id)
|
238
239
|
return Decision.new(rollout_rule, variation, DECISION_SOURCE_ROLLOUT) unless variation.nil?
|
240
|
+
|
239
241
|
break
|
240
242
|
end
|
241
243
|
|
@@ -254,6 +256,7 @@ module Optimizely
|
|
254
256
|
end
|
255
257
|
variation = @bucketer.bucket(everyone_else_experiment, bucketing_id, user_id)
|
256
258
|
return Decision.new(everyone_else_experiment, variation, DECISION_SOURCE_ROLLOUT) unless variation.nil?
|
259
|
+
|
257
260
|
nil
|
258
261
|
end
|
259
262
|
|
@@ -303,6 +306,7 @@ module Optimizely
|
|
303
306
|
|
304
307
|
decision = user_profile[:experiment_bucket_map][experiment_id]
|
305
308
|
return nil unless decision
|
309
|
+
|
306
310
|
variation_id = decision[:variation_id]
|
307
311
|
return variation_id if @config.variation_id_exists?(experiment_id, variation_id)
|
308
312
|
|
@@ -362,17 +366,18 @@ module Optimizely
|
|
362
366
|
#
|
363
367
|
# user_id - String user ID
|
364
368
|
# attributes - Hash user attributes
|
365
|
-
#
|
366
|
-
bucketing_id = user_id
|
369
|
+
# Returns String representing bucketing ID if it is a String type in attributes else return user ID
|
367
370
|
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
371
|
+
return user_id unless attributes
|
372
|
+
|
373
|
+
bucketing_id = attributes[Optimizely::Helpers::Constants::CONTROL_ATTRIBUTES['BUCKETING_ID']]
|
374
|
+
|
375
|
+
if bucketing_id
|
376
|
+
return bucketing_id if bucketing_id.is_a?(String)
|
377
|
+
|
378
|
+
@config.logger.log(Logger::WARN, 'Bucketing ID attribute is not a string. Defaulted to user ID.')
|
374
379
|
end
|
375
|
-
|
380
|
+
user_id
|
376
381
|
end
|
377
382
|
end
|
378
383
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2016-
|
4
|
+
# Copyright 2016-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.
|
@@ -15,10 +15,12 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
|
-
require_relative '
|
19
|
-
require_relative '
|
20
|
-
require_relative '
|
21
|
-
require_relative '
|
18
|
+
require_relative 'audience'
|
19
|
+
require_relative 'helpers/constants'
|
20
|
+
require_relative 'helpers/event_tag_utils'
|
21
|
+
require_relative 'params'
|
22
|
+
require_relative 'version'
|
23
|
+
|
22
24
|
require 'securerandom'
|
23
25
|
|
24
26
|
module Optimizely
|
@@ -74,9 +76,9 @@ module Optimizely
|
|
74
76
|
visitor_attributes = []
|
75
77
|
|
76
78
|
attributes&.keys&.each do |attribute_key|
|
77
|
-
# Omit
|
79
|
+
# Omit attribute values that are not supported by the log endpoint.
|
78
80
|
attribute_value = attributes[attribute_key]
|
79
|
-
|
81
|
+
if Helpers::Validator.attribute_valid?(attribute_key, attribute_value)
|
80
82
|
attribute_id = @config.get_attribute_id attribute_key
|
81
83
|
if attribute_id
|
82
84
|
visitor_attributes.push(
|
@@ -111,6 +113,7 @@ module Optimizely
|
|
111
113
|
anonymize_ip: @config.anonymize_ip,
|
112
114
|
revision: @config.revision,
|
113
115
|
client_name: CLIENT_ENGINE,
|
116
|
+
enrich_decisions: true,
|
114
117
|
client_version: VERSION
|
115
118
|
}
|
116
119
|
|
@@ -140,19 +143,18 @@ module Optimizely
|
|
140
143
|
Event.new(:post, ENDPOINT, event_params, POST_HEADERS)
|
141
144
|
end
|
142
145
|
|
143
|
-
def create_conversion_event(
|
146
|
+
def create_conversion_event(event, user_id, attributes, event_tags)
|
144
147
|
# Create conversion Event to be sent to the logging endpoint.
|
145
148
|
#
|
146
|
-
#
|
149
|
+
# event - +Object+ Event which needs to be recorded.
|
147
150
|
# user_id - +String+ ID for user.
|
148
151
|
# attributes - +Hash+ representing user attributes and values which need to be recorded.
|
149
152
|
# event_tags - +Hash+ representing metadata associated with the event.
|
150
|
-
# experiment_variation_map - +Map+ of experiment ID to the ID of the variation that the user is bucketed into.
|
151
153
|
#
|
152
154
|
# Returns +Event+ encapsulating the conversion event.
|
153
155
|
|
154
156
|
event_params = get_common_params(user_id, attributes)
|
155
|
-
conversion_params = get_conversion_params(
|
157
|
+
conversion_params = get_conversion_params(event, event_tags)
|
156
158
|
event_params[:visitors][0][:snapshots] = [conversion_params]
|
157
159
|
|
158
160
|
Event.new(:post, ENDPOINT, event_params, POST_HEADERS)
|
@@ -188,31 +190,20 @@ module Optimizely
|
|
188
190
|
impression_event_params
|
189
191
|
end
|
190
192
|
|
191
|
-
def get_conversion_params(
|
193
|
+
def get_conversion_params(event, event_tags)
|
192
194
|
# Creates object of params specific to conversion events
|
193
195
|
#
|
194
|
-
#
|
196
|
+
# event - +Object+ Event which needs to be recorded.
|
195
197
|
# event_tags - +Hash+ Values associated with the event.
|
196
|
-
# experiment_variation_map - +Hash+ Map of experiment IDs to bucketed variation IDs
|
197
198
|
#
|
198
199
|
# Returns +Hash+ Conversion event params
|
199
200
|
|
200
201
|
single_snapshot = {}
|
201
|
-
single_snapshot[:decisions] = []
|
202
|
-
experiment_variation_map.each do |experiment_id, variation_id|
|
203
|
-
next unless variation_id
|
204
|
-
single_snapshot[:decisions].push(
|
205
|
-
campaign_id: @config.experiment_id_map[experiment_id]['layerId'],
|
206
|
-
experiment_id: experiment_id,
|
207
|
-
variation_id: variation_id
|
208
|
-
)
|
209
|
-
end
|
210
|
-
|
211
202
|
event_object = {
|
212
|
-
entity_id:
|
203
|
+
entity_id: event['id'],
|
213
204
|
timestamp: create_timestamp,
|
214
205
|
uuid: create_uuid,
|
215
|
-
key:
|
206
|
+
key: event['key']
|
216
207
|
}
|
217
208
|
|
218
209
|
if event_tags
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2016-
|
4
|
+
# Copyright 2016-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.
|
@@ -327,6 +327,31 @@ module Optimizely
|
|
327
327
|
'v3' => '3',
|
328
328
|
'v4' => '4'
|
329
329
|
}.freeze
|
330
|
+
|
331
|
+
ATTRIBUTE_VALID_TYPES = [FalseClass, Float, Integer, String, TrueClass].freeze
|
332
|
+
|
333
|
+
FINITE_NUMBER_LIMIT = 2**53
|
334
|
+
|
335
|
+
AUDIENCE_EVALUATION_LOGS = {
|
336
|
+
'AUDIENCE_EVALUATION_RESULT' => "Audience '%s' evaluated to %s.",
|
337
|
+
'AUDIENCE_EVALUATION_RESULT_COMBINED' => "Audiences for experiment '%s' collectively evaluated to %s.",
|
338
|
+
'EVALUATING_AUDIENCE' => "Starting to evaluate audience '%s' with conditions: %s.",
|
339
|
+
'EVALUATING_AUDIENCES_COMBINED' => "Evaluating audiences for experiment '%s': %s.",
|
340
|
+
'INFINITE_ATTRIBUTE_VALUE' => 'Audience condition %s evaluated to UNKNOWN because the number value ' \
|
341
|
+
"for user attribute '%s' is not in the range [-2^53, +2^53].",
|
342
|
+
'MISSING_ATTRIBUTE_VALUE' => 'Audience condition %s evaluated as UNKNOWN because no value ' \
|
343
|
+
"was passed for user attribute '%s'.",
|
344
|
+
'NULL_ATTRIBUTE_VALUE' => 'Audience condition %s evaluated to UNKNOWN because a nil value was passed ' \
|
345
|
+
"for user attribute '%s'.",
|
346
|
+
'UNEXPECTED_TYPE' => "Audience condition %s evaluated as UNKNOWN because a value of type '%s' " \
|
347
|
+
"was passed for user attribute '%s'.",
|
348
|
+
'UNKNOWN_CONDITION_TYPE' => 'Audience condition %s uses an unknown condition type. You may need ' \
|
349
|
+
'to upgrade to a newer release of the Optimizely SDK.',
|
350
|
+
'UNKNOWN_CONDITION_VALUE' => 'Audience condition %s has an unsupported condition value. You may need ' \
|
351
|
+
'to upgrade to a newer release of the Optimizely SDK.',
|
352
|
+
'UNKNOWN_MATCH_TYPE' => 'Audience condition %s uses an unknown match type. You may need ' \
|
353
|
+
'to upgrade to a newer release of the Optimizely SDK.'
|
354
|
+
}.freeze
|
330
355
|
end
|
331
356
|
end
|
332
357
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2016-
|
4
|
+
# Copyright 2016-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.
|
@@ -34,6 +34,21 @@ module Optimizely
|
|
34
34
|
attributes.is_a?(Hash)
|
35
35
|
end
|
36
36
|
|
37
|
+
def attribute_valid?(attribute_key, attribute_value)
|
38
|
+
# Determines if provided attribute_key and attribute_value are valid.
|
39
|
+
#
|
40
|
+
# attribute_key - Variable which needs to be validated.
|
41
|
+
# attribute_value - Variable which needs to be validated.
|
42
|
+
#
|
43
|
+
# Returns boolean depending on validity of attribute_key and attribute_value.
|
44
|
+
|
45
|
+
return false unless attribute_key.is_a?(String) || attribute_key.is_a?(Symbol)
|
46
|
+
|
47
|
+
return true if (boolean? attribute_value) || (attribute_value.is_a? String)
|
48
|
+
|
49
|
+
finite_number?(attribute_value)
|
50
|
+
end
|
51
|
+
|
37
52
|
def event_tags_valid?(event_tags)
|
38
53
|
# Determines if provided event tags are valid.
|
39
54
|
#
|
@@ -106,16 +121,54 @@ module Optimizely
|
|
106
121
|
# Returns boolean True if all of the values are valid, False otherwise.
|
107
122
|
|
108
123
|
return false unless variables.respond_to?(:each) && !variables.empty?
|
124
|
+
|
109
125
|
is_valid = true
|
126
|
+
if variables.include? :user_id
|
127
|
+
# Empty str is a valid user ID.
|
128
|
+
unless variables[:user_id].is_a?(String)
|
129
|
+
is_valid = false
|
130
|
+
logger.log(level, "#{Constants::INPUT_VARIABLES['USER_ID']} is invalid")
|
131
|
+
end
|
132
|
+
variables.delete :user_id
|
133
|
+
end
|
134
|
+
|
110
135
|
variables.each do |key, value|
|
111
136
|
next if value.is_a?(String) && !value.empty?
|
137
|
+
|
112
138
|
is_valid = false
|
113
|
-
|
114
|
-
|
115
|
-
|
139
|
+
next unless logger_valid?(logger) && level
|
140
|
+
|
141
|
+
logger.log(level, "#{Constants::INPUT_VARIABLES[key.to_s.upcase]} is invalid")
|
116
142
|
end
|
117
143
|
is_valid
|
118
144
|
end
|
145
|
+
|
146
|
+
def boolean?(value)
|
147
|
+
# Returns true if given value type is boolean.
|
148
|
+
# false otherwise.
|
149
|
+
|
150
|
+
value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
151
|
+
end
|
152
|
+
|
153
|
+
def same_types?(value_1, value_2)
|
154
|
+
# Returns true if given values are of same types.
|
155
|
+
# false otherwise.
|
156
|
+
# Numeric values are considered as same type.
|
157
|
+
|
158
|
+
return true if value_1.is_a?(Numeric) && value_2.is_a?(Numeric)
|
159
|
+
|
160
|
+
return true if boolean?(value_1) && boolean?(value_2)
|
161
|
+
|
162
|
+
value_1.class == value_2.class
|
163
|
+
end
|
164
|
+
|
165
|
+
def finite_number?(value)
|
166
|
+
# Returns true if the given value is a number, enforces
|
167
|
+
# absolute limit of 2^53 and restricts NaN, Infinity, -Infinity.
|
168
|
+
# false otherwise.
|
169
|
+
|
170
|
+
value.is_a?(Numeric) && value.to_f.finite? && value.abs <= Constants::FINITE_NUMBER_LIMIT
|
171
|
+
end
|
119
172
|
end
|
120
173
|
end
|
121
174
|
end
|
@@ -42,6 +42,7 @@ module Optimizely
|
|
42
42
|
|
43
43
|
def add_notification_listener(notification_type, notification_callback)
|
44
44
|
return nil unless notification_type_valid?(notification_type)
|
45
|
+
|
45
46
|
unless notification_callback
|
46
47
|
@logger.log Logger::ERROR, 'Callback can not be empty.'
|
47
48
|
return nil
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2016-
|
3
|
+
# Copyright 2016-2019, Optimizely and contributors
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
@@ -31,6 +31,7 @@ module Optimizely
|
|
31
31
|
attr_reader :account_id
|
32
32
|
attr_reader :attributes
|
33
33
|
attr_reader :audiences
|
34
|
+
attr_reader :typed_audiences
|
34
35
|
attr_reader :events
|
35
36
|
attr_reader :experiments
|
36
37
|
attr_reader :feature_flags
|
@@ -79,6 +80,7 @@ module Optimizely
|
|
79
80
|
@account_id = config['accountId']
|
80
81
|
@attributes = config.fetch('attributes', [])
|
81
82
|
@audiences = config.fetch('audiences', [])
|
83
|
+
@typed_audiences = config.fetch('typedAudiences', [])
|
82
84
|
@events = config.fetch('events', [])
|
83
85
|
@experiments = config['experiments']
|
84
86
|
@feature_flags = config.fetch('featureFlags', [])
|
@@ -102,6 +104,7 @@ module Optimizely
|
|
102
104
|
@experiment_key_map = generate_key_map(@experiments, 'key')
|
103
105
|
@experiment_id_map = generate_key_map(@experiments, 'id')
|
104
106
|
@audience_id_map = generate_key_map(@audiences, 'id')
|
107
|
+
@audience_id_map = @audience_id_map.merge(generate_key_map(@typed_audiences, 'id')) unless @typed_audiences.empty?
|
105
108
|
@variation_id_map = {}
|
106
109
|
@variation_key_map = {}
|
107
110
|
@forced_variation_map = {}
|
@@ -129,9 +132,9 @@ module Optimizely
|
|
129
132
|
variation_id = variation['id']
|
130
133
|
variation['featureEnabled'] = variation['featureEnabled'] == true
|
131
134
|
variation_variables = variation['variables']
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
+
next if variation_variables.nil?
|
136
|
+
|
137
|
+
@variation_id_to_variable_usage_map[variation_id] = generate_key_map(variation_variables, 'id')
|
135
138
|
end
|
136
139
|
@variation_id_map[key] = generate_key_map(variations, 'id')
|
137
140
|
@variation_key_map[key] = generate_key_map(variations, 'key')
|
@@ -161,6 +164,7 @@ module Optimizely
|
|
161
164
|
|
162
165
|
experiment = @experiment_key_map[experiment_key]
|
163
166
|
return experiment if experiment
|
167
|
+
|
164
168
|
@logger.log Logger::ERROR, "Experiment key '#{experiment_key}' is not in datafile."
|
165
169
|
@error_handler.handle_error InvalidExperimentError
|
166
170
|
nil
|
@@ -175,23 +179,25 @@ module Optimizely
|
|
175
179
|
|
176
180
|
experiment = @experiment_id_map[experiment_id]
|
177
181
|
return experiment['key'] unless experiment.nil?
|
182
|
+
|
178
183
|
@logger.log Logger::ERROR, "Experiment id '#{experiment_id}' is not in datafile."
|
179
184
|
@error_handler.handle_error InvalidExperimentError
|
180
185
|
nil
|
181
186
|
end
|
182
187
|
|
183
|
-
def
|
184
|
-
# Get
|
188
|
+
def get_event_from_key(event_key)
|
189
|
+
# Get event for the provided event key.
|
185
190
|
#
|
186
|
-
# event_key - Event key for which
|
191
|
+
# event_key - Event key for which event is to be determined.
|
187
192
|
#
|
188
|
-
# Returns
|
193
|
+
# Returns Event corresponding to the provided event key.
|
189
194
|
|
190
195
|
event = @event_key_map[event_key]
|
191
|
-
return event
|
196
|
+
return event if event
|
197
|
+
|
192
198
|
@logger.log Logger::ERROR, "Event '#{event_key}' is not in datafile."
|
193
199
|
@error_handler.handle_error InvalidEventError
|
194
|
-
|
200
|
+
nil
|
195
201
|
end
|
196
202
|
|
197
203
|
def get_audience_from_id(audience_id)
|
@@ -203,6 +209,7 @@ module Optimizely
|
|
203
209
|
|
204
210
|
audience = @audience_id_map[audience_id]
|
205
211
|
return audience if audience
|
212
|
+
|
206
213
|
@logger.log Logger::ERROR, "Audience '#{audience_id}' is not in datafile."
|
207
214
|
@error_handler.handle_error InvalidAudienceError
|
208
215
|
nil
|
@@ -220,6 +227,7 @@ module Optimizely
|
|
220
227
|
if variation_id_map
|
221
228
|
variation = variation_id_map[variation_id]
|
222
229
|
return variation if variation
|
230
|
+
|
223
231
|
@logger.log Logger::ERROR, "Variation id '#{variation_id}' is not in datafile."
|
224
232
|
@error_handler.handle_error InvalidVariationError
|
225
233
|
return nil
|
@@ -242,6 +250,7 @@ module Optimizely
|
|
242
250
|
if variation_key_map
|
243
251
|
variation = variation_key_map[variation_key]
|
244
252
|
return variation['id'] if variation
|
253
|
+
|
245
254
|
@logger.log Logger::ERROR, "Variation key '#{variation_key}' is not in datafile."
|
246
255
|
@error_handler.handle_error InvalidVariationError
|
247
256
|
return nil
|
@@ -261,6 +270,7 @@ module Optimizely
|
|
261
270
|
|
262
271
|
experiment = @experiment_key_map[experiment_key]
|
263
272
|
return experiment['forcedVariations'] if experiment
|
273
|
+
|
264
274
|
@logger.log Logger::ERROR, "Experiment key '#{experiment_key}' is not in datafile."
|
265
275
|
@error_handler.handle_error InvalidExperimentError
|
266
276
|
end
|
@@ -322,12 +332,9 @@ module Optimizely
|
|
322
332
|
#
|
323
333
|
# Returns a boolean value that indicates if the set completed successfully.
|
324
334
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
experiment_key: experiment_key
|
329
|
-
}, @logger, Logger::DEBUG
|
330
|
-
)
|
335
|
+
input_values = {experiment_key: experiment_key, user_id: user_id}
|
336
|
+
input_values[:variation_key] = variation_key unless variation_key.nil?
|
337
|
+
return false unless Optimizely::Helpers::Validator.inputs_valid?(input_values, @logger, Logger::DEBUG)
|
331
338
|
|
332
339
|
experiment = get_experiment_from_key(experiment_key)
|
333
340
|
experiment_id = experiment['id'] if experiment
|
@@ -335,7 +342,7 @@ module Optimizely
|
|
335
342
|
return false if experiment_id.nil? || experiment_id.empty?
|
336
343
|
|
337
344
|
# clear the forced variation if the variation key is null
|
338
|
-
if variation_key.nil?
|
345
|
+
if variation_key.nil?
|
339
346
|
@forced_variation_map[user_id].delete(experiment_id) if @forced_variation_map.key? user_id
|
340
347
|
@logger.log(Logger::DEBUG, "Variation mapped to experiment '#{experiment_key}' has been removed for user "\
|
341
348
|
"'#{user_id}'.")
|
@@ -350,9 +357,7 @@ module Optimizely
|
|
350
357
|
return false
|
351
358
|
end
|
352
359
|
|
353
|
-
unless @forced_variation_map.key? user_id
|
354
|
-
@forced_variation_map[user_id] = {}
|
355
|
-
end
|
360
|
+
@forced_variation_map[user_id] = {} unless @forced_variation_map.key? user_id
|
356
361
|
@forced_variation_map[user_id][experiment_id] = variation_id
|
357
362
|
@logger.log(Logger::DEBUG, "Set variation '#{variation_id}' for experiment '#{experiment_id}' and "\
|
358
363
|
"user '#{user_id}' in the forced variation map.")
|
@@ -377,6 +382,7 @@ module Optimizely
|
|
377
382
|
return attribute['id']
|
378
383
|
end
|
379
384
|
return attribute_key if has_reserved_prefix
|
385
|
+
|
380
386
|
@logger.log Logger::ERROR, "Attribute key '#{attribute_key}' is not in datafile."
|
381
387
|
@error_handler.handle_error InvalidAttributeError
|
382
388
|
nil
|
@@ -395,6 +401,7 @@ module Optimizely
|
|
395
401
|
if variation_id_map
|
396
402
|
variation = variation_id_map[variation_id]
|
397
403
|
return true if variation
|
404
|
+
|
398
405
|
@logger.log Logger::ERROR, "Variation ID '#{variation_id}' is not in datafile."
|
399
406
|
@error_handler.handle_error InvalidVariationError
|
400
407
|
end
|
@@ -410,6 +417,7 @@ module Optimizely
|
|
410
417
|
# Returns feature flag if found, otherwise nil
|
411
418
|
feature_flag = @feature_flag_key_map[feature_flag_key]
|
412
419
|
return feature_flag if feature_flag
|
420
|
+
|
413
421
|
@logger.log Logger::ERROR, "Feature flag key '#{feature_flag_key}' is not in datafile."
|
414
422
|
nil
|
415
423
|
end
|
@@ -424,6 +432,7 @@ module Optimizely
|
|
424
432
|
feature_flag_key = feature_flag['key']
|
425
433
|
variable = @feature_variable_key_map[feature_flag_key][variable_key]
|
426
434
|
return variable if variable
|
435
|
+
|
427
436
|
@logger.log Logger::ERROR, "No feature variable was found for key '#{variable_key}' in feature flag "\
|
428
437
|
"'#{feature_flag_key}'."
|
429
438
|
nil
|
@@ -437,6 +446,7 @@ module Optimizely
|
|
437
446
|
# Returns the rollout if found, otherwise nil
|
438
447
|
rollout = @rollout_id_map[rollout_id]
|
439
448
|
return rollout if rollout
|
449
|
+
|
440
450
|
@logger.log Logger::ERROR, "Rollout with ID '#{rollout_id}' is not in the datafile."
|
441
451
|
nil
|
442
452
|
end
|