def save_sample(self, metric, value, timestamp=None, dimensions=None, hostname=None, device_name=None): """Save a simple sample, evict old values if needed. """ if timestamp is None: timestamp = time.time() if metric not in self._sample_store: raise exceptions.CheckException("Saving a sample for an undefined metric: %s" % metric) try: value = util.cast_metric_val(value) except ValueError as ve: raise exceptions.NaN(ve) # Data eviction rules key = (tuple(sorted(dimensions.items())), device_name) if self.is_gauge(metric): self._sample_store[metric][key] = ((timestamp, value, hostname, device_name), ) elif self.is_counter(metric): if self._sample_store[metric].get(key) is None: self._sample_store[metric][key] = [(timestamp, value, hostname, device_name)] else: self._sample_store[metric][key] = self._sample_store[metric][key][-1:] + \ [(timestamp, value, hostname, device_name)] else: raise exceptions.CheckException("%s must be either gauge or counter, skipping sample at %s" % (metric, time.ctime(timestamp))) if self.is_gauge(metric): # store[metric][dimensions] = (ts, val) - only 1 value allowed assert len(self._sample_store[metric][key]) == 1, self._sample_store[metric] elif self.is_counter(metric): assert len(self._sample_store[metric][key]) in (1, 2), self._sample_store[metric]
def __init__(self, check, prefix=None, default_mapping=None): """C'tor :param check: Target check instance """ self._check = check self._prefix = prefix self._groups = {} self._metric_map = {} self._dimension_map = {} self._metric_cache = {} self._grp_metric_map = {} self._grp_dimension_map = {} self._grp_metric_cache = {} self._metric_to_group = {} for inst in self._check.instances: iname = inst['name'] mappings = inst.get('mapping', default_mapping) if mappings: # build global name filter and rate/gauge assignment self._metric_map[iname] = mappings self._metric_cache[iname] = {} # build global dimension map self._dimension_map[ iname] = DynamicCheckHelper._build_dimension_map(mappings) # check if groups are used groups = mappings.get('groups') self._metric_to_group[iname] = {} self._groups[iname] = [] if groups: self._groups[iname] = groups.keys() self._grp_metric_map[iname] = {} self._grp_metric_cache[iname] = {} self._grp_dimension_map[iname] = {} for grp, gspec in groups.items(): self._grp_metric_map[iname][grp] = gspec self._grp_metric_cache[iname][grp] = {} self._grp_dimension_map[iname][ grp] = DynamicCheckHelper._build_dimension_map( gspec) # add the global mappings as pseudo group, so that it is considered when searching for metrics self._groups[iname].append( DynamicCheckHelper.DEFAULT_GROUP) self._grp_metric_map[iname][ DynamicCheckHelper. DEFAULT_GROUP] = self._metric_map[iname] self._grp_metric_cache[iname][ DynamicCheckHelper. DEFAULT_GROUP] = self._metric_cache[iname] self._grp_dimension_map[iname][ DynamicCheckHelper. DEFAULT_GROUP] = self._dimension_map[iname] else: raise exceptions.CheckException( 'instance %s is not supported: no element "mapping" found!', iname)