Skip to content

Commit 73aa36f

Browse files
committed
Revert "Send event on feature access (#75)"
This reverts commit 70e1d44.
1 parent 0b2f019 commit 73aa36f

File tree

4 files changed

+48
-130
lines changed

4 files changed

+48
-130
lines changed

optimizely/decision_service.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# limitations under the License.
1313

1414
import sys
15-
from collections import namedtuple
1615

1716
from . import bucketer
1817
from .helpers import audience as audience_helper
@@ -22,7 +21,6 @@
2221
from .user_profile import UserProfile
2322

2423

25-
Decision = namedtuple('Decision', 'experiment variation')
2624
RESERVED_BUCKETING_ID_ATTRIBUTE = '$opt_bucketing_id'
2725

2826

@@ -106,7 +104,7 @@ def get_variation(self, experiment, user_id, attributes, ignore_user_profile=Fal
106104
Fifth, bucket the user and return the variation.
107105
108106
Args:
109-
experiment: Experiment for which user variation needs to be determined.
107+
experiment_key: Experiment for which user variation needs to be determined.
110108
user_id: ID for user.
111109
attributes: Dict representing user attributes.
112110
ignore_user_profile: True to ignore the user profile lookup. Defaults to False.
@@ -178,7 +176,7 @@ def get_variation(self, experiment, user_id, attributes, ignore_user_profile=Fal
178176
return None
179177

180178
def get_variation_for_rollout(self, rollout, user_id, attributes=None):
181-
""" Determine which experiment/variation the user is in for a given rollout.
179+
""" Determine which variation the user is in for a given rollout.
182180
Returns the variation of the first experiment the user qualifies for.
183181
184182
Args:
@@ -187,7 +185,7 @@ def get_variation_for_rollout(self, rollout, user_id, attributes=None):
187185
attributes: Dict representing user attributes.
188186
189187
Returns:
190-
Decision namedtuple consisting of experiment and variation for the user.
188+
Variation the user should see. None if the user is not in any of the rollout's targeting rules.
191189
"""
192190

193191
# Go through each experiment in order and try to get the variation for the user
@@ -210,7 +208,7 @@ def get_variation_for_rollout(self, rollout, user_id, attributes=None):
210208
if variation:
211209
self.logger.log(enums.LogLevels.DEBUG,
212210
'User "%s" is in variation %s of experiment %s.' % (user_id, variation.key, experiment.key))
213-
return Decision(experiment, variation)
211+
return variation
214212
else:
215213
# Evaluate no further rules
216214
self.logger.log(enums.LogLevels.DEBUG,
@@ -229,9 +227,9 @@ def get_variation_for_rollout(self, rollout, user_id, attributes=None):
229227
if variation:
230228
self.logger.log(enums.LogLevels.DEBUG,
231229
'User "%s" meets conditions for targeting rule "Everyone Else".' % user_id)
232-
return Decision(everyone_else_experiment, variation)
230+
return variation
233231

234-
return Decision(None, None)
232+
return None
235233

236234
def get_experiment_in_group(self, group, bucketing_id):
237235
""" Determine which experiment in the group the user is bucketed into.
@@ -260,18 +258,17 @@ def get_experiment_in_group(self, group, bucketing_id):
260258
return None
261259

262260
def get_variation_for_feature(self, feature, user_id, attributes=None):
263-
""" Returns the experiment/variation the user is bucketed in for the given feature.
261+
""" Returns the variation the user is bucketed in for the given feature.
264262
265263
Args:
266264
feature: Feature for which we are determining if it is enabled or not for the given user.
267265
user_id: ID for user.
268266
attributes: Dict representing user attributes.
269267
270268
Returns:
271-
Decision namedtuple consisting of experiment and variation for the user.
269+
Variation that the user is bucketed in. None if the user is not in any variation.
272270
"""
273271

274-
experiment = None
275272
variation = None
276273
bucketing_id = self._get_bucketing_id(user_id, attributes)
277274

@@ -303,6 +300,6 @@ def get_variation_for_feature(self, feature, user_id, attributes=None):
303300
# Next check if user is part of a rollout
304301
if not variation and feature.rolloutId:
305302
rollout = self.config.get_rollout_from_id(feature.rolloutId)
306-
return self.get_variation_for_rollout(rollout, user_id, attributes)
303+
variation = self.get_variation_for_rollout(rollout, user_id, attributes)
307304

308-
return Decision(experiment, variation)
305+
return variation

optimizely/optimizely.py

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
from .error_handler import NoOpErrorHandler as noop_error_handler
2222
from .event_dispatcher import EventDispatcher as default_event_dispatcher
2323
from .helpers import enums
24-
from .helpers import event_tag_utils
2524
from .helpers import validator
2625
from .logger import NoOpLogger as noop_logger
2726
from .logger import SimpleLogger
@@ -155,33 +154,6 @@ def _get_decisions(self, event, user_id, attributes):
155154

156155
return decisions
157156

158-
def _send_impression_event(self, experiment, variation, user_id, attributes):
159-
""" Helper method to send impression event.
160-
161-
Args:
162-
experiment: Experiment for which impression event is being sent.
163-
variation: Variation picked for user for the given experiment.
164-
user_id: ID for user.
165-
attributes: Dict representing user attributes and values which need to be recorded.
166-
"""
167-
168-
impression_event = self.event_builder.create_impression_event(experiment,
169-
variation.id,
170-
user_id,
171-
attributes)
172-
173-
self.logger.log(enums.LogLevels.DEBUG,
174-
'Dispatching impression event to URL %s with params %s.' % (impression_event.url,
175-
impression_event.params))
176-
177-
try:
178-
self.event_dispatcher.dispatch_event(impression_event)
179-
except:
180-
error = sys.exc_info()[1]
181-
self.logger.log(enums.LogLevels.ERROR, 'Unable to dispatch impression event. Error: %s' % str(error))
182-
self.notification_center.send_notifications(enums.NotificationTypes.ACTIVATE,
183-
experiment, user_id, attributes, variation, impression_event)
184-
185157
def activate(self, experiment_key, user_id, attributes=None):
186158
""" Buckets visitor and sends impression event to Optimizely.
187159
@@ -205,12 +177,19 @@ def activate(self, experiment_key, user_id, attributes=None):
205177
self.logger.log(enums.LogLevels.INFO, 'Not activating user "%s".' % user_id)
206178
return None
207179

180+
# Create and dispatch impression event
208181
experiment = self.config.get_experiment_from_key(experiment_key)
209182
variation = self.config.get_variation_from_key(experiment_key, variation_key)
210-
211-
# Create and dispatch impression event
183+
impression_event = self.event_builder.create_impression_event(experiment, variation.id, user_id, attributes)
212184
self.logger.log(enums.LogLevels.INFO, 'Activating user "%s" in experiment "%s".' % (user_id, experiment.key))
213-
self._send_impression_event(experiment, variation, user_id, attributes)
185+
self.logger.log(enums.LogLevels.DEBUG,
186+
'Dispatching impression event to URL %s with params %s.' % (impression_event.url,
187+
impression_event.params))
188+
try:
189+
self.event_dispatcher.dispatch_event(impression_event)
190+
except:
191+
error = sys.exc_info()[1]
192+
self.logger.log(enums.LogLevels.ERROR, 'Unable to dispatch impression event. Error: %s' % str(error))
214193

215194
return variation.key
216195

@@ -321,13 +300,9 @@ def is_feature_enabled(self, feature_key, user_id, attributes=None):
321300
if not feature:
322301
return False
323302

324-
decision = self.decision_service.get_variation_for_feature(feature, user_id, attributes)
325-
if decision.variation:
303+
variation = self.decision_service.get_variation_for_feature(feature, user_id, attributes)
304+
if variation:
326305
self.logger.log(enums.LogLevels.INFO, 'Feature "%s" is enabled for user "%s".' % (feature_key, user_id))
327-
self._send_impression_event(decision.experiment,
328-
decision.variation,
329-
user_id,
330-
attributes)
331306
return True
332307

333308
self.logger.log(enums.LogLevels.INFO, 'Feature "%s" is not enabled for user "%s".' % (feature_key, user_id))

tests/test_decision_service.py

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import json
1515
import mock
1616

17-
from optimizely import decision_service
1817
from optimizely import entities
1918
from optimizely import optimizely
2019
from optimizely import user_profile
@@ -377,8 +376,7 @@ def test_get_variation_for_rollout__returns_none_if_no_experiments(self, mock_lo
377376
""" Test that get_variation_for_rollout returns None if there are no experiments (targeting rules). """
378377

379378
no_experiment_rollout = self.project_config.get_rollout_from_id('201111')
380-
self.assertEqual(decision_service.Decision(None, None),
381-
self.decision_service.get_variation_for_rollout(no_experiment_rollout, 'test_user'))
379+
self.assertIsNone(self.decision_service.get_variation_for_rollout(no_experiment_rollout, 'test_user'))
382380

383381
# Assert no log messages were generated
384382
self.assertEqual(0, mock_logging.call_count)
@@ -438,8 +436,7 @@ def test_get_variation_for_rollout__skips_to_everyone_else_rule(self, mock_loggi
438436

439437
with mock.patch('optimizely.helpers.audience.is_user_in_experiment', return_value=True) as mock_audience_check,\
440438
mock.patch('optimizely.bucketer.Bucketer.bucket', return_value=None):
441-
self.assertEqual(decision_service.Decision(None, None),
442-
self.decision_service.get_variation_for_rollout(rollout, 'test_user'))
439+
self.assertIsNone(self.decision_service.get_variation_for_rollout(rollout, 'test_user'))
443440

444441
# Check that after first experiment, it skips to the last experiment to check
445442
self.assertEqual(
@@ -461,8 +458,7 @@ def test_get_variation_for_rollout__returns_none_for_user_not_in_rollout(self, m
461458
rollout = self.project_config.get_rollout_from_id('211111')
462459

463460
with mock.patch('optimizely.helpers.audience.is_user_in_experiment', return_value=False) as mock_audience_check:
464-
self.assertEqual(decision_service.Decision(None, None),
465-
self.decision_service.get_variation_for_rollout(rollout, 'test_user'))
461+
self.assertIsNone(self.decision_service.get_variation_for_rollout(rollout, 'test_user'))
466462

467463
# Check that all experiments in rollout layer were checked
468464
self.assertEqual(
@@ -483,12 +479,11 @@ def test_get_variation_for_feature__returns_variation_for_feature_in_experiment(
483479

484480
feature = self.project_config.get_feature_from_key('test_feature_in_experiment')
485481

486-
expected_experiment = self.project_config.get_experiment_from_key('test_experiment')
487482
expected_variation = self.project_config.get_variation_from_id('test_experiment', '111129')
488-
with mock.patch('optimizely.decision_service.DecisionService.get_variation',
489-
return_value=expected_variation) as mock_decision:
490-
self.assertEqual(decision_service.Decision(expected_experiment, expected_variation),
491-
self.decision_service.get_variation_for_feature(feature, 'user1'))
483+
with mock.patch(
484+
'optimizely.decision_service.DecisionService.get_variation',
485+
return_value=expected_variation) as mock_decision:
486+
self.assertEqual(expected_variation, self.decision_service.get_variation_for_feature(feature, 'user1'))
492487

493488
mock_decision.assert_called_once_with(
494489
self.project_config.get_experiment_from_key('test_experiment'), 'test_user', None
@@ -521,14 +516,12 @@ def test_get_variation_for_feature__returns_variation_if_user_not_in_experiment_
521516

522517
feature = self.project_config.get_feature_from_key('test_feature_in_experiment_and_rollout')
523518

524-
expected_experiment = self.project_config.get_experiment_from_key('211127')
525519
expected_variation = self.project_config.get_variation_from_id('211127', '211129')
526520
with mock.patch(
527521
'optimizely.helpers.audience.is_user_in_experiment',
528522
side_effect=[False, True]) as mock_audience_check, \
529523
mock.patch('optimizely.bucketer.Bucketer.bucket', return_value=expected_variation):
530-
self.assertEqual(decision_service.Decision(expected_experiment, expected_variation),
531-
self.decision_service.get_variation_for_feature(feature, 'user1'))
524+
self.assertEqual(expected_variation, self.decision_service.get_variation_for_feature(feature, 'user1'))
532525

533526
self.assertEqual(2, mock_audience_check.call_count)
534527
mock_audience_check.assert_any_call(self.project_config,
@@ -540,20 +533,21 @@ def test_get_variation_for_feature__returns_variation_for_feature_in_group(self,
540533
""" Test that get_variation_for_feature returns the variation of
541534
the experiment the user is bucketed in the feature's group. """
542535

543-
feature = self.project_config.get_feature_from_key('test_feature_in_group')
536+
opt_obj = optimizely.Optimizely(json.dumps(self.config_dict_with_features))
537+
project_config = opt_obj.config
538+
decision_service = opt_obj.decision_service
539+
feature = project_config.get_feature_from_key('test_feature_in_group')
544540

545-
expected_experiment = self.project_config.get_experiment_from_key('group_exp_1')
546-
expected_variation = self.project_config.get_variation_from_id('group_exp_1', '28901')
541+
expected_variation = project_config.get_variation_from_id('group_exp_1', '28901')
547542
with mock.patch(
548543
'optimizely.decision_service.DecisionService.get_experiment_in_group',
549-
return_value=self.project_config.get_experiment_from_key('group_exp_1')) as mock_get_experiment_in_group, \
544+
return_value=project_config.get_experiment_from_key('group_exp_1')) as mock_get_experiment_in_group, \
550545
mock.patch('optimizely.decision_service.DecisionService.get_variation',
551546
return_value=expected_variation) as mock_decision:
552-
self.assertEqual(decision_service.Decision(expected_experiment, expected_variation),
553-
self.decision_service.get_variation_for_feature(feature, 'user1'))
547+
self.assertEqual(expected_variation, decision_service.get_variation_for_feature(feature, 'user1'))
554548

555-
mock_get_experiment_in_group.assert_called_once_with(self.project_config.get_group('19228'), 'test_user')
556-
mock_decision.assert_called_once_with(self.project_config.get_experiment_from_key('group_exp_1'), 'test_user', None)
549+
mock_get_experiment_in_group.assert_called_once_with(project_config.get_group('19228'), 'user1')
550+
mock_decision.assert_called_once_with(project_config.get_experiment_from_key('group_exp_1'), 'user1', None)
557551

558552
def test_get_variation_for_feature__returns_none_for_user_not_in_group(self, _):
559553
""" Test that get_variation_for_feature returns None for
@@ -564,8 +558,7 @@ def test_get_variation_for_feature__returns_none_for_user_not_in_group(self, _):
564558
with mock.patch('optimizely.decision_service.DecisionService.get_experiment_in_group',
565559
return_value=None) as mock_get_experiment_in_group, \
566560
mock.patch('optimizely.decision_service.DecisionService.get_variation') as mock_decision:
567-
self.assertEqual(decision_service.Decision(None, None),
568-
self.decision_service.get_variation_for_feature(feature, 'user1'))
561+
self.assertIsNone(self.decision_service.get_variation_for_feature(feature, 'user1'))
569562

570563
mock_get_experiment_in_group.assert_called_once_with(self.project_config.get_group('19228'), 'test_user')
571564
self.assertFalse(mock_decision.called)
@@ -574,11 +567,9 @@ def test_get_variation_for_feature__returns_none_for_user_not_in_experiment(self
574567
""" Test that get_variation_for_feature returns None for user not in the associated experiment. """
575568

576569
feature = self.project_config.get_feature_from_key('test_feature_in_experiment')
577-
expected_experiment = self.project_config.get_experiment_from_key('test_experiment')
578570

579571
with mock.patch('optimizely.decision_service.DecisionService.get_variation', return_value=None) as mock_decision:
580-
self.assertEqual(decision_service.Decision(expected_experiment, None),
581-
self.decision_service.get_variation_for_feature(feature, 'user1'))
572+
self.assertIsNone(self.decision_service.get_variation_for_feature(feature, 'user1'))
582573

583574
mock_decision.assert_called_once_with(
584575
self.project_config.get_experiment_from_key('test_experiment'), 'test_user', None
@@ -589,12 +580,10 @@ def test_get_variation_for_feature__returns_none_for_user_in_group_experiment_no
589580
not targeting a feature, then None is returned. """
590581

591582
feature = self.project_config.get_feature_from_key('test_feature_in_group')
592-
expected_experiment = self.project_config.get_experiment_from_key('group_exp_2')
593583

594584
with mock.patch('optimizely.decision_service.DecisionService.get_experiment_in_group',
595585
return_value=self.project_config.get_experiment_from_key('group_exp_2')) as mock_decision:
596-
self.assertEqual(decision_service.Decision(expected_experiment, None),
597-
self.decision_service.get_variation_for_feature(feature, 'user_1'))
586+
self.assertIsNone(self.decision_service.get_variation_for_feature(feature, 'user_1'))
598587

599588
mock_decision.assert_called_once_with(self.project_config.get_group('19228'), 'test_user')
600589

0 commit comments

Comments
 (0)