Skip to content
34 changes: 25 additions & 9 deletions splitio/api/impressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,7 @@ def _build_bulk(impressions):
{
'f': test_name,
'i': [
{
'k': impression.matching_key,
't': impression.treatment,
'm': impression.time,
'c': impression.change_number,
'r': impression.label,
'b': impression.bucketing_key,
'pt': impression.previous_time
}
ImpressionsAPIBase._filter_out_null_prop(impression)
for impression in imps
]
}
Expand All @@ -48,6 +40,30 @@ def _build_bulk(impressions):
)
]

@staticmethod
def _filter_out_null_prop(impression):
if impression.properties == None:
return {
'k': impression.matching_key,
't': impression.treatment,
'm': impression.time,
'c': impression.change_number,
'r': impression.label,
'b': impression.bucketing_key,
'pt': impression.previous_time
}

return {
'k': impression.matching_key,
't': impression.treatment,
'm': impression.time,
'c': impression.change_number,
'r': impression.label,
'b': impression.bucketing_key,
'pt': impression.previous_time,
'properties': impression.properties
}

@staticmethod
def _build_counters(counters):
"""
Expand Down
148 changes: 80 additions & 68 deletions splitio/client/client.py

Large diffs are not rendered by default.

25 changes: 15 additions & 10 deletions splitio/client/input_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ def validate_factory_instantiation(sdk_key):
return True


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

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

valid_properties = dict()
Expand All @@ -595,9 +595,8 @@ def valid_properties(properties):
if element is None:
continue

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

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

if size > MAX_PROPERTIES_LENGTH_BYTES:
_LOGGER.error(
'The maximum size allowed for the properties is 32768 bytes. ' +
'Current one is ' + str(size) + ' bytes. Event not queued'
)
'%s: The maximum size allowed for the properties is 32768 bytes. ' +
'Current one is ' + str(size) + ' bytes. Event not queued', source)
return False, None, size

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

def _check_element_type(element):
if not isinstance(element, str) and not isinstance(element, Number) \
and not isinstance(element, bool):
return False

return True

def validate_pluggable_adapter(config):
"""
Check if pluggable adapter contains the expected method signature
Expand Down
18 changes: 16 additions & 2 deletions splitio/engine/impressions/strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,14 @@ def process_impressions(self, impressions):
:returns: Tuple of to be stored, observed and counted impressions, and unique keys tuple
:rtype: list[tuple[splitio.models.impression.Impression, dict]], list[], list[], list[]
"""
imps = [(self._observer.test_and_set(imp), attrs) for imp, attrs in impressions]
imps = []
for imp, attrs in impressions:
if imp.properties is not None:
imps.append((imp, attrs))
continue

imps.append((self._observer.test_and_set(imp), attrs))

return [i for i, _ in imps], imps, [], []

class StrategyNoneMode(BaseStrategy):
Expand Down Expand Up @@ -85,7 +92,14 @@ def process_impressions(self, impressions):
:returns: Tuple of to be stored, observed and counted impressions, and unique keys tuple
:rtype: list[tuple[splitio.models.impression.Impression, dict]], list[splitio.models.impression.Impression], list[splitio.models.impression.Impression], list[]
"""
imps = [(self._observer.test_and_set(imp), attrs) for imp, attrs in impressions]
imps = []
for imp, attrs in impressions:
if imp.properties is not None:
imps.append((imp, attrs))
continue

imps.append((self._observer.test_and_set(imp), attrs))

counter_imps = [imp for imp, _ in imps if imp.previous_time != None]
this_hour = truncate_time(utctime_ms())
return [i for i, _ in imps if i.previous_time is None or i.previous_time < this_hour], imps, counter_imps, []
3 changes: 2 additions & 1 deletion splitio/models/impressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
'change_number',
'bucketing_key',
'time',
'previous_time'
'previous_time',
'properties'
]
)

Expand Down
1 change: 1 addition & 0 deletions splitio/storage/pluggable.py
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,7 @@ def _wrap_impressions(self, impressions):
'r': impression.label,
'c': impression.change_number,
'm': impression.time,
'properties': impression.properties
}
}
bulk_impressions.append(json.dumps(to_store))
Expand Down
1 change: 1 addition & 0 deletions splitio/storage/redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,7 @@ def _wrap_impressions(self, impressions):
'r': impression.label,
'c': impression.change_number,
'm': impression.time,
'properties': impression.properties
}
}
bulk_impressions.append(json.dumps(to_store))
Expand Down
8 changes: 4 additions & 4 deletions tests/api/test_impressions_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
from splitio.storage.inmemmory import InMemoryTelemetryStorage, InMemoryTelemetryStorageAsync

impressions_mock = [
Impression('k1', 'f1', 'on', 'l1', 123456, 'b1', 321654),
Impression('k2', 'f2', 'off', 'l1', 123456, 'b1', 321654),
Impression('k3', 'f1', 'on', 'l1', 123456, 'b1', 321654)
Impression('k1', 'f1', 'on', 'l1', 123456, 'b1', 321654, None, {'prop': 'val'}),
Impression('k2', 'f2', 'off', 'l1', 123456, 'b1', 321654, None, None),
Impression('k3', 'f1', 'on', 'l1', 123456, 'b1', 321654, None, None)
]
expectedImpressions = [{
'f': 'f1',
'i': [
{'k': 'k1', 'b': 'b1', 't': 'on', 'r': 'l1', 'm': 321654, 'c': 123456, 'pt': None},
{'k': 'k1', 'b': 'b1', 't': 'on', 'r': 'l1', 'm': 321654, 'c': 123456, 'pt': None, 'properties': {"prop": "val"}},
{'k': 'k3', 'b': 'b1', 't': 'on', 'r': 'l1', 'm': 321654, 'c': 123456, 'pt': None},
],
}, {
Expand Down
Loading