Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6c9b1a5

Browse files
authored
Merge pull request #553 from splitio/track-impressions
merging impressions toggle branch
2 parents 6b675a4 + 2fcffce commit 6c9b1a5

File tree

15 files changed

+1485
-219
lines changed

15 files changed

+1485
-219
lines changed

splitio/client/client.py

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from splitio.engine.evaluator import Evaluator, CONTROL, EvaluationDataFactory, AsyncEvaluationDataFactory
55
from splitio.engine.splitters import Splitter
6-
from splitio.models.impressions import Impression, Label
6+
from splitio.models.impressions import Impression, Label, ImpressionDecorated
77
from splitio.models.events import Event, EventWrapper
88
from splitio.models.telemetry import get_latency_bucket_index, MethodExceptionsAndLatencies
99
from splitio.client import input_validator
@@ -22,7 +22,8 @@ class ClientBase(object): # pylint: disable=too-many-instance-attributes
2222
'impression': {
2323
'label': Label.EXCEPTION,
2424
'change_number': None,
25-
}
25+
},
26+
'impressions_disabled': False
2627
}
2728

2829
_NON_READY_EVAL_RESULT = {
@@ -31,7 +32,8 @@ class ClientBase(object): # pylint: disable=too-many-instance-attributes
3132
'impression': {
3233
'label': Label.NOT_READY,
3334
'change_number': None
34-
}
35+
},
36+
'impressions_disabled': False
3537
}
3638

3739
def __init__(self, factory, recorder, labels_enabled=True):
@@ -116,14 +118,15 @@ def _validate_treatments_input(key, features, attributes, method):
116118

117119
def _build_impression(self, key, bucketing, feature, result):
118120
"""Build an impression based on evaluation data & it's result."""
119-
return Impression(
120-
matching_key=key,
121+
return ImpressionDecorated(
122+
Impression(matching_key=key,
121123
feature_name=feature,
122124
treatment=result['treatment'],
123125
label=result['impression']['label'] if self._labels_enabled else None,
124126
change_number=result['impression']['change_number'],
125127
bucketing_key=bucketing,
126-
time=utctime_ms())
128+
time=utctime_ms()),
129+
disabled=result['impressions_disabled'])
127130

128131
def _build_impressions(self, key, bucketing, results):
129132
"""Build an impression based on evaluation data & it's result."""
@@ -296,8 +299,8 @@ def _get_treatment(self, method, key, feature, attributes=None):
296299
result = self._FAILED_EVAL_RESULT
297300

298301
if result['impression']['label'] != Label.SPLIT_NOT_FOUND:
299-
impression = self._build_impression(key, bucketing, feature, result)
300-
self._record_stats([(impression, attributes)], start, method)
302+
impression_decorated = self._build_impression(key, bucketing, feature, result)
303+
self._record_stats([(impression_decorated, attributes)], start, method)
301304

302305
return result['treatment'], result['configurations']
303306

@@ -571,23 +574,23 @@ def _get_treatments(self, key, features, method, attributes=None):
571574
self._telemetry_evaluation_producer.record_exception(method)
572575
results = {n: self._FAILED_EVAL_RESULT for n in features}
573576

574-
imp_attrs = [
577+
imp_decorated_attrs = [
575578
(i, attributes) for i in self._build_impressions(key, bucketing, results)
576-
if i.label != Label.SPLIT_NOT_FOUND
579+
if i.Impression.label != Label.SPLIT_NOT_FOUND
577580
]
578-
self._record_stats(imp_attrs, start, method)
581+
self._record_stats(imp_decorated_attrs, start, method)
579582

580583
return {
581584
feature: (results[feature]['treatment'], results[feature]['configurations'])
582585
for feature in results
583586
}
584587

585-
def _record_stats(self, impressions, start, operation):
588+
def _record_stats(self, impressions_decorated, start, operation):
586589
"""
587590
Record impressions.
588591
589-
:param impressions: Generated impressions
590-
:type impressions: list[tuple[splitio.models.impression.Impression, dict]]
592+
:param impressions_decorated: Generated impressions
593+
:type impressions_decorated: list[tuple[splitio.models.impression.ImpressionDecorated, dict]]
591594
592595
:param start: timestamp when get_treatment or get_treatments was called
593596
:type start: int
@@ -596,7 +599,7 @@ def _record_stats(self, impressions, start, operation):
596599
:type operation: str
597600
"""
598601
end = get_current_epoch_time_ms()
599-
self._recorder.record_treatment_stats(impressions, get_latency_bucket_index(end - start),
602+
self._recorder.record_treatment_stats(impressions_decorated, get_latency_bucket_index(end - start),
600603
operation, 'get_' + operation.value)
601604

602605
def track(self, key, traffic_type, event_type, value=None, properties=None):
@@ -763,8 +766,8 @@ async def _get_treatment(self, method, key, feature, attributes=None):
763766
result = self._FAILED_EVAL_RESULT
764767

765768
if result['impression']['label'] != Label.SPLIT_NOT_FOUND:
766-
impression = self._build_impression(key, bucketing, feature, result)
767-
await self._record_stats([(impression, attributes)], start, method)
769+
impression_decorated = self._build_impression(key, bucketing, feature, result)
770+
await self._record_stats([(impression_decorated, attributes)], start, method)
768771
return result['treatment'], result['configurations']
769772

770773
async def get_treatments(self, key, feature_flag_names, attributes=None):
@@ -960,23 +963,23 @@ async def _get_treatments(self, key, features, method, attributes=None):
960963
await self._telemetry_evaluation_producer.record_exception(method)
961964
results = {n: self._FAILED_EVAL_RESULT for n in features}
962965

963-
imp_attrs = [
966+
imp_decorated_attrs = [
964967
(i, attributes) for i in self._build_impressions(key, bucketing, results)
965-
if i.label != Label.SPLIT_NOT_FOUND
968+
if i.Impression.label != Label.SPLIT_NOT_FOUND
966969
]
967-
await self._record_stats(imp_attrs, start, method)
970+
await self._record_stats(imp_decorated_attrs, start, method)
968971

969972
return {
970973
feature: (res['treatment'], res['configurations'])
971974
for feature, res in results.items()
972975
}
973976

974-
async def _record_stats(self, impressions, start, operation):
977+
async def _record_stats(self, impressions_decorated, start, operation):
975978
"""
976979
Record impressions for async calls
977980
978-
:param impressions: Generated impressions
979-
:type impressions: list[tuple[splitio.models.impression.Impression, dict]]
981+
:param impressions_decorated: Generated impressions decorated
982+
:type impressions_decorated: list[tuple[splitio.models.impression.Impression, dict]]
980983
981984
:param start: timestamp when get_treatment or get_treatments was called
982985
:type start: int
@@ -985,7 +988,7 @@ async def _record_stats(self, impressions, start, operation):
985988
:type operation: str
986989
"""
987990
end = get_current_epoch_time_ms()
988-
await self._recorder.record_treatment_stats(impressions, get_latency_bucket_index(end - start),
991+
await self._recorder.record_treatment_stats(impressions_decorated, get_latency_bucket_index(end - start),
989992
operation, 'get_' + operation.value)
990993

991994
async def track(self, key, traffic_type, event_type, value=None, properties=None):

splitio/client/factory.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from splitio.client.listener import ImpressionListenerWrapper, ImpressionListenerWrapperAsync
1414
from splitio.engine.impressions.impressions import Manager as ImpressionsManager
1515
from splitio.engine.impressions import set_classes, set_classes_async
16-
from splitio.engine.impressions.strategies import StrategyDebugMode
16+
from splitio.engine.impressions.strategies import StrategyDebugMode, StrategyNoneMode
1717
from splitio.engine.telemetry import TelemetryStorageProducer, TelemetryStorageConsumer, \
1818
TelemetryStorageProducerAsync, TelemetryStorageConsumerAsync
1919
from splitio.engine.impressions.manager import Counter as ImpressionsCounter
@@ -553,10 +553,10 @@ def _build_in_memory_factory(api_key, cfg, sdk_url=None, events_url=None, # pyl
553553
unique_keys_tracker = UniqueKeysTracker(_UNIQUE_KEYS_CACHE_SIZE)
554554
unique_keys_synchronizer, clear_filter_sync, unique_keys_task, \
555555
clear_filter_task, impressions_count_sync, impressions_count_task, \
556-
imp_strategy = set_classes('MEMORY', cfg['impressionsMode'], apis, imp_counter, unique_keys_tracker)
556+
imp_strategy, none_strategy = set_classes('MEMORY', cfg['impressionsMode'], apis, imp_counter, unique_keys_tracker)
557557

558558
imp_manager = ImpressionsManager(
559-
imp_strategy, telemetry_runtime_producer)
559+
imp_strategy, none_strategy, telemetry_runtime_producer)
560560

561561
synchronizers = SplitSynchronizers(
562562
SplitSynchronizer(apis['splits'], storages['splits']),
@@ -681,10 +681,10 @@ async def _build_in_memory_factory_async(api_key, cfg, sdk_url=None, events_url=
681681
unique_keys_tracker = UniqueKeysTrackerAsync(_UNIQUE_KEYS_CACHE_SIZE)
682682
unique_keys_synchronizer, clear_filter_sync, unique_keys_task, \
683683
clear_filter_task, impressions_count_sync, impressions_count_task, \
684-
imp_strategy = set_classes_async('MEMORY', cfg['impressionsMode'], apis, imp_counter, unique_keys_tracker)
684+
imp_strategy, none_strategy = set_classes_async('MEMORY', cfg['impressionsMode'], apis, imp_counter, unique_keys_tracker)
685685

686686
imp_manager = ImpressionsManager(
687-
imp_strategy, telemetry_runtime_producer)
687+
imp_strategy, none_strategy, telemetry_runtime_producer)
688688

689689
synchronizers = SplitSynchronizers(
690690
SplitSynchronizerAsync(apis['splits'], storages['splits']),
@@ -775,10 +775,10 @@ def _build_redis_factory(api_key, cfg):
775775
unique_keys_tracker = UniqueKeysTracker(_UNIQUE_KEYS_CACHE_SIZE)
776776
unique_keys_synchronizer, clear_filter_sync, unique_keys_task, \
777777
clear_filter_task, impressions_count_sync, impressions_count_task, \
778-
imp_strategy = set_classes('REDIS', cfg['impressionsMode'], redis_adapter, imp_counter, unique_keys_tracker)
778+
imp_strategy, none_strategy = set_classes('REDIS', cfg['impressionsMode'], redis_adapter, imp_counter, unique_keys_tracker)
779779

780780
imp_manager = ImpressionsManager(
781-
imp_strategy,
781+
imp_strategy, none_strategy,
782782
telemetry_runtime_producer)
783783

784784
synchronizers = SplitSynchronizers(None, None, None, None,
@@ -858,10 +858,10 @@ async def _build_redis_factory_async(api_key, cfg):
858858
unique_keys_tracker = UniqueKeysTrackerAsync(_UNIQUE_KEYS_CACHE_SIZE)
859859
unique_keys_synchronizer, clear_filter_sync, unique_keys_task, \
860860
clear_filter_task, impressions_count_sync, impressions_count_task, \
861-
imp_strategy = set_classes_async('REDIS', cfg['impressionsMode'], redis_adapter, imp_counter, unique_keys_tracker)
861+
imp_strategy, none_strategy = set_classes_async('REDIS', cfg['impressionsMode'], redis_adapter, imp_counter, unique_keys_tracker)
862862

863863
imp_manager = ImpressionsManager(
864-
imp_strategy,
864+
imp_strategy, none_strategy,
865865
telemetry_runtime_producer)
866866

867867
synchronizers = SplitSynchronizers(None, None, None, None,
@@ -936,10 +936,10 @@ def _build_pluggable_factory(api_key, cfg):
936936
unique_keys_tracker = UniqueKeysTracker(_UNIQUE_KEYS_CACHE_SIZE)
937937
unique_keys_synchronizer, clear_filter_sync, unique_keys_task, \
938938
clear_filter_task, impressions_count_sync, impressions_count_task, \
939-
imp_strategy = set_classes('PLUGGABLE', cfg['impressionsMode'], pluggable_adapter, imp_counter, unique_keys_tracker, storage_prefix)
939+
imp_strategy, none_strategy = set_classes('PLUGGABLE', cfg['impressionsMode'], pluggable_adapter, imp_counter, unique_keys_tracker, storage_prefix)
940940

941941
imp_manager = ImpressionsManager(
942-
imp_strategy,
942+
imp_strategy, none_strategy,
943943
telemetry_runtime_producer)
944944

945945
synchronizers = SplitSynchronizers(None, None, None, None,
@@ -1017,10 +1017,10 @@ async def _build_pluggable_factory_async(api_key, cfg):
10171017
unique_keys_tracker = UniqueKeysTrackerAsync(_UNIQUE_KEYS_CACHE_SIZE)
10181018
unique_keys_synchronizer, clear_filter_sync, unique_keys_task, \
10191019
clear_filter_task, impressions_count_sync, impressions_count_task, \
1020-
imp_strategy = set_classes_async('PLUGGABLE', cfg['impressionsMode'], pluggable_adapter, imp_counter, unique_keys_tracker, storage_prefix)
1020+
imp_strategy, none_strategy = set_classes_async('PLUGGABLE', cfg['impressionsMode'], pluggable_adapter, imp_counter, unique_keys_tracker, storage_prefix)
10211021

10221022
imp_manager = ImpressionsManager(
1023-
imp_strategy,
1023+
imp_strategy, none_strategy,
10241024
telemetry_runtime_producer)
10251025

10261026
synchronizers = SplitSynchronizers(None, None, None, None,
@@ -1123,7 +1123,7 @@ def _build_localhost_factory(cfg):
11231123
manager.start()
11241124

11251125
recorder = StandardRecorder(
1126-
ImpressionsManager(StrategyDebugMode(), telemetry_runtime_producer),
1126+
ImpressionsManager(StrategyDebugMode(), StrategyNoneMode(), telemetry_runtime_producer),
11271127
storages['events'],
11281128
storages['impressions'],
11291129
telemetry_evaluation_producer,
@@ -1192,7 +1192,7 @@ async def _build_localhost_factory_async(cfg):
11921192
await manager.start()
11931193

11941194
recorder = StandardRecorderAsync(
1195-
ImpressionsManager(StrategyDebugMode(), telemetry_runtime_producer),
1195+
ImpressionsManager(StrategyDebugMode(), StrategyNoneMode(), telemetry_runtime_producer),
11961196
storages['events'],
11971197
storages['impressions'],
11981198
telemetry_evaluation_producer,

splitio/engine/evaluator.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ def eval_with_context(self, key, bucketing, feature_name, attrs, ctx):
6767
'impression': {
6868
'label': label,
6969
'change_number': _change_number
70-
}
70+
},
71+
'impressions_disabled': feature.impressions_disabled if feature else None
7172
}
7273

7374
def _treatment_for_flag(self, flag, key, bucketing, attributes, ctx):

splitio/engine/impressions/__init__.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -53,24 +53,24 @@ def set_classes(storage_mode, impressions_mode, api_adapter, imp_counter, unique
5353
api_impressions_adapter = api_adapter['impressions']
5454
sender_adapter = InMemorySenderAdapter(api_telemetry_adapter)
5555

56+
none_strategy = StrategyNoneMode()
57+
unique_keys_synchronizer = UniqueKeysSynchronizer(sender_adapter, unique_keys_tracker)
58+
unique_keys_task = UniqueKeysSyncTask(unique_keys_synchronizer.send_all)
59+
clear_filter_sync = ClearFilterSynchronizer(unique_keys_tracker)
60+
impressions_count_sync = ImpressionsCountSynchronizer(api_impressions_adapter, imp_counter)
61+
impressions_count_task = ImpressionsCountSyncTask(impressions_count_sync.synchronize_counters)
62+
clear_filter_task = ClearFilterSyncTask(clear_filter_sync.clear_all)
63+
unique_keys_tracker.set_queue_full_hook(unique_keys_task.flush)
64+
5665
if impressions_mode == ImpressionsMode.NONE:
5766
imp_strategy = StrategyNoneMode()
58-
unique_keys_synchronizer = UniqueKeysSynchronizer(sender_adapter, unique_keys_tracker)
59-
unique_keys_task = UniqueKeysSyncTask(unique_keys_synchronizer.send_all)
60-
clear_filter_sync = ClearFilterSynchronizer(unique_keys_tracker)
61-
impressions_count_sync = ImpressionsCountSynchronizer(api_impressions_adapter, imp_counter)
62-
impressions_count_task = ImpressionsCountSyncTask(impressions_count_sync.synchronize_counters)
63-
clear_filter_task = ClearFilterSyncTask(clear_filter_sync.clear_all)
64-
unique_keys_tracker.set_queue_full_hook(unique_keys_task.flush)
6567
elif impressions_mode == ImpressionsMode.DEBUG:
6668
imp_strategy = StrategyDebugMode()
6769
else:
6870
imp_strategy = StrategyOptimizedMode()
69-
impressions_count_sync = ImpressionsCountSynchronizer(api_impressions_adapter, imp_counter)
70-
impressions_count_task = ImpressionsCountSyncTask(impressions_count_sync.synchronize_counters)
7171

7272
return unique_keys_synchronizer, clear_filter_sync, unique_keys_task, clear_filter_task, \
73-
impressions_count_sync, impressions_count_task, imp_strategy
73+
impressions_count_sync, impressions_count_task, imp_strategy, none_strategy
7474

7575
def set_classes_async(storage_mode, impressions_mode, api_adapter, imp_counter, unique_keys_tracker, prefix=None):
7676
"""
@@ -118,21 +118,21 @@ def set_classes_async(storage_mode, impressions_mode, api_adapter, imp_counter,
118118
api_impressions_adapter = api_adapter['impressions']
119119
sender_adapter = InMemorySenderAdapterAsync(api_telemetry_adapter)
120120

121+
none_strategy = StrategyNoneMode()
122+
unique_keys_synchronizer = UniqueKeysSynchronizerAsync(sender_adapter, unique_keys_tracker)
123+
unique_keys_task = UniqueKeysSyncTaskAsync(unique_keys_synchronizer.send_all)
124+
clear_filter_sync = ClearFilterSynchronizerAsync(unique_keys_tracker)
125+
impressions_count_sync = ImpressionsCountSynchronizerAsync(api_impressions_adapter, imp_counter)
126+
impressions_count_task = ImpressionsCountSyncTaskAsync(impressions_count_sync.synchronize_counters)
127+
clear_filter_task = ClearFilterSyncTaskAsync(clear_filter_sync.clear_all)
128+
unique_keys_tracker.set_queue_full_hook(unique_keys_task.flush)
129+
121130
if impressions_mode == ImpressionsMode.NONE:
122131
imp_strategy = StrategyNoneMode()
123-
unique_keys_synchronizer = UniqueKeysSynchronizerAsync(sender_adapter, unique_keys_tracker)
124-
unique_keys_task = UniqueKeysSyncTaskAsync(unique_keys_synchronizer.send_all)
125-
clear_filter_sync = ClearFilterSynchronizerAsync(unique_keys_tracker)
126-
impressions_count_sync = ImpressionsCountSynchronizerAsync(api_impressions_adapter, imp_counter)
127-
impressions_count_task = ImpressionsCountSyncTaskAsync(impressions_count_sync.synchronize_counters)
128-
clear_filter_task = ClearFilterSyncTaskAsync(clear_filter_sync.clear_all)
129-
unique_keys_tracker.set_queue_full_hook(unique_keys_task.flush)
130132
elif impressions_mode == ImpressionsMode.DEBUG:
131133
imp_strategy = StrategyDebugMode()
132134
else:
133135
imp_strategy = StrategyOptimizedMode()
134-
impressions_count_sync = ImpressionsCountSynchronizerAsync(api_impressions_adapter, imp_counter)
135-
impressions_count_task = ImpressionsCountSyncTaskAsync(impressions_count_sync.synchronize_counters)
136136

137137
return unique_keys_synchronizer, clear_filter_sync, unique_keys_task, clear_filter_task, \
138-
impressions_count_sync, impressions_count_task, imp_strategy
138+
impressions_count_sync, impressions_count_task, imp_strategy, none_strategy

0 commit comments

Comments
 (0)