Skip to content

Commit bd7357a

Browse files
authored
Merge pull request #587 from splitio/feature/impressions-properties
Feature/impressions properties
2 parents 5328afb + 69a39b8 commit bd7357a

20 files changed

+819
-447
lines changed

splitio/api/impressions.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,7 @@ def _build_bulk(impressions):
3030
{
3131
'f': test_name,
3232
'i': [
33-
{
34-
'k': impression.matching_key,
35-
't': impression.treatment,
36-
'm': impression.time,
37-
'c': impression.change_number,
38-
'r': impression.label,
39-
'b': impression.bucketing_key,
40-
'pt': impression.previous_time
41-
}
33+
ImpressionsAPIBase._filter_out_null_prop(impression)
4234
for impression in imps
4335
]
4436
}
@@ -48,6 +40,30 @@ def _build_bulk(impressions):
4840
)
4941
]
5042

43+
@staticmethod
44+
def _filter_out_null_prop(impression):
45+
if impression.properties == None:
46+
return {
47+
'k': impression.matching_key,
48+
't': impression.treatment,
49+
'm': impression.time,
50+
'c': impression.change_number,
51+
'r': impression.label,
52+
'b': impression.bucketing_key,
53+
'pt': impression.previous_time
54+
}
55+
56+
return {
57+
'k': impression.matching_key,
58+
't': impression.treatment,
59+
'm': impression.time,
60+
'c': impression.change_number,
61+
'r': impression.label,
62+
'b': impression.bucketing_key,
63+
'pt': impression.previous_time,
64+
'properties': impression.properties
65+
}
66+
5167
@staticmethod
5268
def _build_counters(counters):
5369
"""

splitio/client/client.py

Lines changed: 80 additions & 68 deletions
Large diffs are not rendered by default.

splitio/client/input_validator.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ def validate_factory_instantiation(sdk_key):
564564
return True
565565

566566

567-
def valid_properties(properties):
567+
def valid_properties(properties, source):
568568
"""
569569
Check if properties is a valid dict and returns the properties
570570
that will be sent to the track method, avoiding unexpected types.
@@ -580,7 +580,7 @@ def valid_properties(properties):
580580
return True, None, size
581581

582582
if not isinstance(properties, dict):
583-
_LOGGER.error('track: properties must be of type dictionary.')
583+
_LOGGER.error('%s: properties must be of type dictionary.', source)
584584
return False, None, 0
585585

586586
valid_properties = dict()
@@ -595,9 +595,8 @@ def valid_properties(properties):
595595
if element is None:
596596
continue
597597

598-
if not isinstance(element, str) and not isinstance(element, Number) \
599-
and not isinstance(element, bool):
600-
_LOGGER.warning('Property %s is of invalid type. Setting value to None', element)
598+
if not _check_element_type(element):
599+
_LOGGER.warning('%s: Property %s is of invalid type. Setting value to None', source, element)
601600
element = None
602601

603602
valid_properties[property] = element
@@ -607,16 +606,22 @@ def valid_properties(properties):
607606

608607
if size > MAX_PROPERTIES_LENGTH_BYTES:
609608
_LOGGER.error(
610-
'The maximum size allowed for the properties is 32768 bytes. ' +
611-
'Current one is ' + str(size) + ' bytes. Event not queued'
612-
)
609+
'%s: The maximum size allowed for the properties is 32768 bytes. ' +
610+
'Current one is ' + str(size) + ' bytes. Event not queued', source)
613611
return False, None, size
614612

615613
if len(valid_properties.keys()) > 300:
616-
_LOGGER.warning('Event has more than 300 properties. Some of them will be trimmed' +
617-
' when processed')
614+
_LOGGER.warning('%s: Event has more than 300 properties. Some of them will be trimmed' +
615+
' when processed', source)
618616
return True, valid_properties if len(valid_properties) else None, size
619617

618+
def _check_element_type(element):
619+
if not isinstance(element, str) and not isinstance(element, Number) \
620+
and not isinstance(element, bool):
621+
return False
622+
623+
return True
624+
620625
def validate_pluggable_adapter(config):
621626
"""
622627
Check if pluggable adapter contains the expected method signature

splitio/engine/impressions/strategies.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,14 @@ def process_impressions(self, impressions):
3838
:returns: Tuple of to be stored, observed and counted impressions, and unique keys tuple
3939
:rtype: list[tuple[splitio.models.impression.Impression, dict]], list[], list[], list[]
4040
"""
41-
imps = [(self._observer.test_and_set(imp), attrs) for imp, attrs in impressions]
41+
imps = []
42+
for imp, attrs in impressions:
43+
if imp.properties is not None:
44+
imps.append((imp, attrs))
45+
continue
46+
47+
imps.append((self._observer.test_and_set(imp), attrs))
48+
4249
return [i for i, _ in imps], imps, [], []
4350

4451
class StrategyNoneMode(BaseStrategy):
@@ -85,7 +92,14 @@ def process_impressions(self, impressions):
8592
:returns: Tuple of to be stored, observed and counted impressions, and unique keys tuple
8693
:rtype: list[tuple[splitio.models.impression.Impression, dict]], list[splitio.models.impression.Impression], list[splitio.models.impression.Impression], list[]
8794
"""
88-
imps = [(self._observer.test_and_set(imp), attrs) for imp, attrs in impressions]
95+
imps = []
96+
for imp, attrs in impressions:
97+
if imp.properties is not None:
98+
imps.append((imp, attrs))
99+
continue
100+
101+
imps.append((self._observer.test_and_set(imp), attrs))
102+
89103
counter_imps = [imp for imp, _ in imps if imp.previous_time != None]
90104
this_hour = truncate_time(utctime_ms())
91105
return [i for i, _ in imps if i.previous_time is None or i.previous_time < this_hour], imps, counter_imps, []

splitio/models/impressions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
'change_number',
1313
'bucketing_key',
1414
'time',
15-
'previous_time'
15+
'previous_time',
16+
'properties'
1617
]
1718
)
1819

splitio/storage/pluggable.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,7 @@ def _wrap_impressions(self, impressions):
12311231
'r': impression.label,
12321232
'c': impression.change_number,
12331233
'm': impression.time,
1234+
'properties': impression.properties
12341235
}
12351236
}
12361237
bulk_impressions.append(json.dumps(to_store))

splitio/storage/redis.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,7 @@ def _wrap_impressions(self, impressions):
11001100
'r': impression.label,
11011101
'c': impression.change_number,
11021102
'm': impression.time,
1103+
'properties': impression.properties
11031104
}
11041105
}
11051106
bulk_impressions.append(json.dumps(to_store))

tests/api/test_impressions_api.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414
from splitio.storage.inmemmory import InMemoryTelemetryStorage, InMemoryTelemetryStorageAsync
1515

1616
impressions_mock = [
17-
Impression('k1', 'f1', 'on', 'l1', 123456, 'b1', 321654),
18-
Impression('k2', 'f2', 'off', 'l1', 123456, 'b1', 321654),
19-
Impression('k3', 'f1', 'on', 'l1', 123456, 'b1', 321654)
17+
Impression('k1', 'f1', 'on', 'l1', 123456, 'b1', 321654, None, {'prop': 'val'}),
18+
Impression('k2', 'f2', 'off', 'l1', 123456, 'b1', 321654, None, None),
19+
Impression('k3', 'f1', 'on', 'l1', 123456, 'b1', 321654, None, None)
2020
]
2121
expectedImpressions = [{
2222
'f': 'f1',
2323
'i': [
24-
{'k': 'k1', 'b': 'b1', 't': 'on', 'r': 'l1', 'm': 321654, 'c': 123456, 'pt': None},
24+
{'k': 'k1', 'b': 'b1', 't': 'on', 'r': 'l1', 'm': 321654, 'c': 123456, 'pt': None, 'properties': {"prop": "val"}},
2525
{'k': 'k3', 'b': 'b1', 't': 'on', 'r': 'l1', 'm': 321654, 'c': 123456, 'pt': None},
2626
],
2727
}, {

0 commit comments

Comments
 (0)