Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add check for kyoto tycoon #426

Merged
merged 5 commits into from
Mar 27, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions checks.d/kyototycoon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import re
import urllib2
from collections import defaultdict

from 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 = {
'serv_conn_count': 'connections',
'serv_thread_count': 'threads',
'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',
'repl_delay': 'replication.delay',
}
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.get.total',
'cnt_remove_misses': 'ops.get.total',
}

def check(self, instance):
url = instance.get('report_url')
if not url:
raise Exception('Invalid Kyoto Tycoon report url %r' % url)

tags = instance.get('tags', {})
name = instance.get('name')

# generate the formatted list of tags
tags = ['%s:%s' % (k, v) for k, v in tags.items()]
if name is not None:
tags.append('instance:%s' % 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), tags=tags)

elif db_stats.match(key):
# Also produce a per-db metrics tagged with the db
# number in addition to the default tags
m = db_stats.match(key)
dbnum = int(m.group(1))
mytags = tags + ['db:%d' % 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), tags=mytags)

if key in self.TOTALS:
totals[self.TOTALS[key]] += float(value)

for key, value in totals.items():
self.gauge('kyototycoon.%s' % key, value, tags=tags)

if __name__ == '__main__':
check, instances = KyotoTycoonCheck.from_yaml('kyototycoon.yaml')
for instance in instances:
check.check(instance)
if check.has_events():
print 'Events: %s' % (check.get_events())
print 'Metrics: %s'
import pprint
pprint.pprint(check.get_metrics())
15 changes: 15 additions & 0 deletions conf.d/kyototycoon.yaml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
init_config:
# The Kyoto Tycoon check does not require any init_config

instances:
# Add one or more instances, which accept report_url,
# name, and optionally tags keys. The report URL should
# be a URL to the Kyoto Tycoon "report" RPC endpoint.
#
# Complete example:
#
# - name: my_kyoto_instance
# report_url: http://localhost:3003/rpc/report
# tags:
# foo: bar
# baz: bat