def pop_many(self, count): """ Pop the oldest N impressions from storage. :param count: Number of impressions to pop. :type count: int """ with UWSGILock(self._uwsgi, self._LOCK_IMPRESSION_KEY): try: current = json.loads( self._uwsgi.cache_get( self._IMPRESSIONS_KEY, _SPLITIO_IMPRESSIONS_CACHE_NAMESPACE)) except TypeError: return [] self._uwsgi.cache_update(self._IMPRESSIONS_KEY, json.dumps(current[count:]), 0, _SPLITIO_IMPRESSIONS_CACHE_NAMESPACE) return [ Impression(impression['matching_key'], impression['feature_name'], impression['treatment'], impression['label'], impression['change_number'], impression['bucketing_key'], impression['time']) for impression in current[:count] ]
def remove(self, split_name): """ Remove a split from storage. :param split_name: Name of the feature to remove. :type split_name: str :return: True if the split was found and removed. False otherwise. :rtype: bool """ with UWSGILock(self._uwsgi, self._KEY_FEATURE_LIST_LOCK): try: current = set( json.loads( self._uwsgi.cache_get(self._KEY_FEATURE_LIST, _SPLITIO_MISC_NAMESPACE))) current.remove(split_name) self._uwsgi.cache_update(self._KEY_FEATURE_LIST, json.dumps(list(current)), 0, _SPLITIO_MISC_NAMESPACE) except TypeError: # Split list not found, no need to delete anything pass except KeyError: # Split not found in list. nothing to do. pass result = self._uwsgi.cache_del( self._KEY_TEMPLATE.format(suffix=split_name), _SPLITIO_SPLITS_CACHE_NAMESPACE) if not result is False: self._logger.warning( "Trying to retrieve nonexistant split %s. Ignoring.", split_name) return result
def pop_latencies(self): """ Get all latencies. :rtype: list """ with UWSGILock(self._uwsgi, self._LATENCIES_LOCK_KEY): latencies_raw = self._uwsgi.cache_get( self._LATENCIES_KEY, _SPLITIO_METRICS_CACHE_NAMESPACE) self._uwsgi.cache_del(self._LATENCIES_KEY, _SPLITIO_METRICS_CACHE_NAMESPACE) return json.loads(latencies_raw) if latencies_raw else {}
def pop_counters(self): """ Get all the counters. :rtype: list """ with UWSGILock(self._uwsgi, self._COUNTERS_LOCK_KEY): counters_raw = self._uwsgi.cache_get( self._COUNTERS_KEY, _SPLITIO_METRICS_CACHE_NAMESPACE) self._uwsgi.cache_del(self._COUNTERS_KEY, _SPLITIO_METRICS_CACHE_NAMESPACE) return json.loads(counters_raw) if counters_raw else {}
def pop_gauges(self): """ Get all the gauges. :rtype: list """ with UWSGILock(self._uwsgi, self._GAUGES_LOCK_KEY): gauges_raw = self._uwsgi.cache_get( self._GAUGES_KEY, _SPLITIO_METRICS_CACHE_NAMESPACE) self._uwsgi.cache_del(self._GAUGES_KEY, _SPLITIO_METRICS_CACHE_NAMESPACE) return json.loads(gauges_raw) if gauges_raw else {}
def put_gauge(self, name, value): """ Add a gauge metric. :param name: Name of the gauge metric. :type name: str :param value: Value of the gauge metric. :type value: int """ with UWSGILock(self._uwsgi, self._GAUGES_LOCK_KEY): gauges_raw = self._uwsgi.cache_get( self._GAUGES_KEY, _SPLITIO_METRICS_CACHE_NAMESPACE) gauges = json.loads(gauges_raw) if gauges_raw else {} gauges[name] = value self._uwsgi.cache_set(self._GAUGES_KEY, json.dumps(gauges), 0, _SPLITIO_METRICS_CACHE_NAMESPACE)
def inc_counter(self, name): """ Increment a counter. :param name: Name of the counter metric. :type name: str """ with UWSGILock(self._uwsgi, self._COUNTERS_LOCK_KEY): counters_raw = self._uwsgi.cache_get( self._COUNTERS_KEY, _SPLITIO_METRICS_CACHE_NAMESPACE) counters = json.loads(counters_raw) if counters_raw else {} value = counters.get(name, 0) value += 1 counters[name] = value self._uwsgi.cache_set(self._COUNTERS_KEY, json.dumps(counters), 0, _SPLITIO_METRICS_CACHE_NAMESPACE)
def put(self, events): """ Put one or more events in storage. :param events: List of one or more events to store. :type events: list """ with UWSGILock(self._uwsgi, self._LOCK_EVENTS_KEY): try: current = json.loads( self._uwsgi.cache_get(self._EVENTS_KEY, _SPLITIO_EVENTS_CACHE_NAMESPACE)) except TypeError: current = [] self._uwsgi.cache_update( self._EVENTS_KEY, json.dumps(current + [e.event._asdict() for e in events]), 0, _SPLITIO_EVENTS_CACHE_NAMESPACE)
def _increase_traffic_type_count(self, traffic_type_name): """ Increase by 1 the count for a specific traffic type. :param traffic_type_name: Traffic type name to increase count. :type traffic_type_name: str """ with UWSGILock(self._uwsgi, self._KEY_TRAFFIC_TYPES_LOCK): try: tts = json.loads( self._uwsgi.cache_get(self._KEY_TRAFFIC_TYPES, _SPLITIO_MISC_NAMESPACE)) tts[traffic_type_name] = tts.get(traffic_type_name, 0) + 1 except TypeError: tts = {traffic_type_name: 1} self._uwsgi.cache_update(self._KEY_TRAFFIC_TYPES, json.dumps(tts), 0, _SPLITIO_MISC_NAMESPACE)
def _add_split_to_list(self, split_name): """ Add a specific split to the list we keep track of. :param split_name: Name of the split to add. :type split_name: str """ with UWSGILock(self._uwsgi, self._KEY_FEATURE_LIST_LOCK): try: current = set( json.loads( self._uwsgi.cache_get(self._KEY_FEATURE_LIST, _SPLITIO_MISC_NAMESPACE))) except TypeError: current = set() current.add(split_name) self._uwsgi.cache_update(self._KEY_FEATURE_LIST, json.dumps(list(current)), 0, _SPLITIO_MISC_NAMESPACE)
def put(self, impressions): """ Put one or more impressions in storage. :param impressions: List of one or more impressions to store. :type impressions: list """ to_store = [i._asdict() for i in impressions] with UWSGILock(self._uwsgi, self._LOCK_IMPRESSION_KEY): try: current = json.loads( self._uwsgi.cache_get( self._IMPRESSIONS_KEY, _SPLITIO_IMPRESSIONS_CACHE_NAMESPACE)) except TypeError: current = [] self._uwsgi.cache_update(self._IMPRESSIONS_KEY, json.dumps(current + to_store), 0, _SPLITIO_IMPRESSIONS_CACHE_NAMESPACE)
def _decrease_traffic_type_count(self, traffic_type_name): """ Decreaase by 1 the count for a specific traffic type. :param traffic_type_name: Traffic type name to decrease count. :type traffic_type_name: str """ with UWSGILock(self._uwsgi, self._KEY_TRAFFIC_TYPES_LOCK): try: tts = json.loads( self._uwsgi.cache_get(self._KEY_TRAFFIC_TYPES, _SPLITIO_MISC_NAMESPACE)) tts[traffic_type_name] = tts.get(traffic_type_name, 0) - 1 if tts[traffic_type_name] <= 0: del tts[traffic_type_name] except TypeError: # Traffic type list not present. nothing to do here. return self._uwsgi.cache_update(self._KEY_TRAFFIC_TYPES, json.dumps(tts), 0, _SPLITIO_MISC_NAMESPACE)
def inc_latency(self, name, bucket): """ Add a latency. :param name: Name of the latency metric. :type name: str :param value: Value of the latency metric. :tyoe value: int """ if not 0 <= bucket <= 21: _LOGGER.error('Incorect bucket "%d" for latency "%s". Ignoring.', bucket, name) return with UWSGILock(self._uwsgi, self._LATENCIES_LOCK_KEY): latencies_raw = self._uwsgi.cache_get( self._LATENCIES_KEY, _SPLITIO_METRICS_CACHE_NAMESPACE) latencies = json.loads(latencies_raw) if latencies_raw else {} to_update = latencies.get(name, [0] * 22) to_update[bucket] += 1 latencies[name] = to_update self._uwsgi.cache_set(self._LATENCIES_KEY, json.dumps(latencies), 0, _SPLITIO_METRICS_CACHE_NAMESPACE)
def _remove_split_from_list(self, split_name): """ Remove a specific split from the list we keep track of. :param split_name: Name of the split to remove. :type split_name: str """ with UWSGILock(self._uwsgi, self._KEY_FEATURE_LIST_LOCK): try: current = set( json.loads( self._uwsgi.cache_get(self._KEY_FEATURE_LIST, _SPLITIO_MISC_NAMESPACE))) current.remove(split_name) self._uwsgi.cache_update(self._KEY_FEATURE_LIST, json.dumps(list(current)), 0, _SPLITIO_MISC_NAMESPACE) except TypeError: # Split list not found, no need to delete anything pass except KeyError: # Split not found in list. nothing to do. pass
def put(self, split): """ Store a split. :param split: Split object to store :type split: splitio.models.splits.Split """ self._uwsgi.cache_update(self._KEY_TEMPLATE.format(suffix=split.name), json.dumps(split.to_json()), 0, _SPLITIO_SPLITS_CACHE_NAMESPACE) with UWSGILock(self._uwsgi, self._KEY_FEATURE_LIST_LOCK): try: current = set( json.loads( self._uwsgi.cache_get(self._KEY_FEATURE_LIST, _SPLITIO_MISC_NAMESPACE))) except TypeError: current = set() current.add(split.name) self._uwsgi.cache_update(self._KEY_FEATURE_LIST, json.dumps(list(current)), 0, _SPLITIO_MISC_NAMESPACE)
def pop_many(self, count): """ Pop the oldest N events from storage. :param count: Number of events to pop. :type count: int """ with UWSGILock(self._uwsgi, self._LOCK_EVENTS_KEY): try: current = json.loads( self._uwsgi.cache_get(self._EVENTS_KEY, _SPLITIO_EVENTS_CACHE_NAMESPACE)) except TypeError: return [] self._uwsgi.cache_update(self._EVENTS_KEY, json.dumps(current[count:]), 0, _SPLITIO_EVENTS_CACHE_NAMESPACE) return [ Event(event['key'], event['traffic_type_name'], event['event_type_id'], event['value'], event['timestamp'], event['properties']) for event in current[:count] ]