'Save a simple sample, evict old values if needed'

def save_sample(self, metric, value, timestamp=None, tags=None, hostname=None, device_name=None):

    from util import cast_metric_val
    if (timestamp is None):
        timestamp = time.time()
    if (metric not in self._sample_store):
        raise CheckException(('Saving    a    sample    for    an    undefined    metric:    %s' % metric))
    try:
        value = cast_metric_val(value)
    except ValueError as ve:
        raise NaN(ve)
    if (tags is not None):
        if (type(tags) not in [type([]), type(())]):
            raise CheckException('Tags    must    be    a    list    or    tuple    of    strings')
        else:
            tags = tuple(sorted(tags))
    key = (tags, 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 CheckException(('%s    must    be    either    gauge    or    counter,    skipping    sample    at    %s' % (metric, time.ctime(timestamp))))
    if self.is_gauge(metric):
        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]
