optimizely-sdk 2.1.1 → 3.0.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 +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
|