def test_stats(): # The min is not enabled by default stats = Stats() metric_stats = { 'foo': 2, 'bar': 5, } # setters stats.set_stat('metrics', 4) stats.set_stat('events', 2) stats.set_stat('service_checks', 1) # totals stats.inc_stat('metrics_total', 4) stats.inc_stat('events_total', 2) stats.inc_stat('service_checks_total', 1) # info stats.set_info('metric_stats', metric_stats) stats_snapshot, info_snapshot = stats.snapshot() assert info_snapshot['metric_stats'] == metric_stats assert stats_snapshot['metrics'] == 4 assert stats_snapshot['events'] == 2 assert stats_snapshot['service_checks'] == 1 assert stats_snapshot['metrics_total'] == 4 assert stats_snapshot['events_total'] == 2 assert stats_snapshot['service_checks_total'] == 1 # test we got a deepcopy for stats stats.set_stat('metrics', 10) stats.inc_stat('metrics_total', 10) assert stats_snapshot != metric_stats assert stats_snapshot['metrics'] != stats.get_stat('metrics') # test we got a deepcopy for info metric_stats['bar'] += 1 stats.set_info('metric_stats', metric_stats) assert info_snapshot != metric_stats assert info_snapshot['metric_stats']['foo'] == metric_stats['foo'] assert info_snapshot['metric_stats']['bar'] != metric_stats['bar'] # test for updated snapshots stats_snapshot, info_snapshot = stats.snapshot() assert stats_snapshot['metrics'] == 10 assert stats_snapshot['metrics_total'] == 14 assert info_snapshot['metric_stats']['foo'] == metric_stats['foo'] assert info_snapshot['metric_stats']['bar'] == metric_stats['bar'] # test strict get with pytest.raises(KeyError): stats.get_stat('nonexistent', strict=True) with pytest.raises(KeyError): stats.get_info('nonexistent', strict=True)
class Collector(object): CORE_CHECKS = ['cpu', 'load', 'iostat', 'memory', 'filesystem', 'uptime'] def __init__(self, config, aggregator=None): self._config = config self._loaders = [] self._check_classes = {} self._check_classes_errors = defaultdict(dict) self._check_instance_errors = defaultdict(dict) self._check_instances = defaultdict(list) self._check_instance_signatures = {} self._hostname = get_hostname() self._aggregator = aggregator self._status = Stats() self.set_loaders() def set_loaders(self): check_loader = CheckLoader() check_loader.add_place(self._config['additional_checksd']) self._loaders = [check_loader] self._loaders.append(WheelLoader(namespace=DD_WHEEL_NAMESPACE)) def set_aggregator(self, aggregator): if not isinstance(aggregator, Aggregator): raise ValueError('argument should be of type Aggregator') self._aggregator = aggregator @property def status(self): return self._status def load_core_checks(self): from checks.corechecks.system import (Cpu, Load, Memory, IOStat, Filesystem, UptimeCheck) self._check_classes['cpu'] = Cpu self._check_classes['filesystem'] = Filesystem self._check_classes['iostat'] = IOStat self._check_classes['load'] = Load self._check_classes['memory'] = Memory self._check_classes['filesystem'] = Filesystem self._check_classes['uptime'] = UptimeCheck def load_check_classes(self): self.load_core_checks() for _, check_configs in self._config.get_check_configs().items(): for check_name in check_configs: log.debug("Found config for check %s...", check_name) if check_name in self._check_classes: continue for loader in self._loaders: try: check_class, errors = loader.load(check_name) if check_class: self._check_classes[check_name] = check_class if errors: self._check_classes_errors[check_name][type( loader).__name__] = errors if check_class: log.debug("Class found for %s...", check_name) break except Exception: log.exception("unexpected error loading check %s", check_name) self._status.set_info('check_classes', copy( self._check_classes)) # shallow copy suffices self._status.set_info('loader_errors', deepcopy(self._check_classes_errors)) def instantiate_checks(self): for source, check_configs in self._config.get_check_configs().items(): for check_name, configs in check_configs.items(): log.debug('Trying to instantiate: %s', check_name) check_class = self._check_classes.get(check_name) if check_class: for config in configs: init_config = config.get('init_config', {}) if init_config is None: init_config = {} instances = config.get( 'instances') # should be single instance for instance in instances: signature = (check_name, init_config, instance) signature_hash = AgentCheck.signature_hash( *signature) if signature_hash in self._check_instance_signatures: log.info( 'instance with identical signature already configured - skipping' ) continue try: check_instance = check_class( check_name, init_config, instance, self._aggregator) self._check_instances[check_name].append( check_instance) self._check_instance_signatures[ signature_hash] = signature except Exception as e: log.error( "unable to instantiate instance %s for %s: %s", instance, check_name, e) for check_name in self.CORE_CHECKS: if check_name in self._check_instances: # already instantiated - skip continue check_class = self._check_classes[check_name] signature = (check_name, {}, {}) signature_hash = AgentCheck.signature_hash(*signature) try: check_instance = check_class(*signature) check_instance.set_aggregator(self._aggregator) self._check_instances[check_name] = [check_instance] self._check_instance_signatures[signature_hash] = signature except Exception: log.error("unable to instantiate core check %s", check_name) def run_checks(self): for name, checks in self._check_instances.items(): log.info('running check %s...', name) for check in checks: try: result = check.run() except Exception: log.exception("error for instance: %s", str(check.instance)) if result: self._check_instance_errors[name][check.signature] = result log.error('There was an error running your %s: %s', name, result.get('message')) log.error('Traceback %s: %s', name, result.get('traceback')) self._status.set_info('runtime_errors', deepcopy(self._check_instance_errors))