# (C) Copyright 2015 Hewlett Packard Enterprise Development Company LP from collections import defaultdict import re import urllib2 from monasca_agent.collector.checks import AgentCheck db_stats = re.compile(r'^db_(\d)+$') whitespace = re.compile(r'\s') class KyotoTycoonCheck(AgentCheck): """Report statistics about the Kyoto Tycoon DBM-style database server (http://fallabs.com/kyototycoon/) """ GAUGES = { 'repl_delay': 'replication.delay', 'serv_thread_count': 'threads', } RATES = { 'serv_conn_count': 'connections', 'cnt_get': 'ops.get.hits', 'cnt_get_misses': 'ops.get.misses', 'cnt_set': 'ops.set.hits', 'cnt_set_misses': 'ops.set.misses', 'cnt_remove': 'ops.del.hits', 'cnt_remove_misses': 'ops.del.misses', } DB_GAUGES = { 'count': 'records', 'size': 'size', } TOTALS = { 'cnt_get': 'ops.get.total', 'cnt_get_misses': 'ops.get.total', 'cnt_set': 'ops.set.total', 'cnt_set_misses': 'ops.set.total', 'cnt_remove': 'ops.del.total', 'cnt_remove_misses': 'ops.del.total', } def check(self, instance): url = instance.get('report_url') if not url: raise Exception('Invalid Kyoto Tycoon report url %r' % url) dimensions = self._set_dimensions(None, instance) name = instance.get('name') if name is not None: dimensions.update({'instance': name}) response = urllib2.urlopen(url) body = response.read() totals = defaultdict(lambda: 0) for line in body.split('\n'): if '\t' not in line: continue key, value = line.strip().split('\t', 1) if key in self.GAUGES: name = self.GAUGES[key] self.gauge('kyototycoon.%s' % name, float(value), dimensions=dimensions) elif key in self.RATES: name = self.RATES[key] self.rate('kyototycoon.%s_per_s' % name, float(value), dimensions=dimensions) elif db_stats.match(key): # Also produce a per-db metrics tagged with the db # number in addition to the default dimensions m = db_stats.match(key) dbnum = int(m.group(1)) db_dimensions = dimensions.copy() db_dimensions.update({'db': dbnum}) for part in whitespace.split(value): k, v = part.split('=', 1) if k in self.DB_GAUGES: name = self.DB_GAUGES[k] self.gauge('kyototycoon.%s' % name, float(v), dimensions=db_dimensions) if key in self.TOTALS: totals[self.TOTALS[key]] += float(value) for key, value in totals.items(): self.rate('kyototycoon.%s_per_s' % key, value, dimensions=dimensions)