Skip to content

Instantly share code, notes, and snippets.

@viviandarkbloom
Created November 19, 2015 07:27
Show Gist options
  • Save viviandarkbloom/9198e2908c5a4d180e1c to your computer and use it in GitHub Desktop.
Save viviandarkbloom/9198e2908c5a4d180e1c to your computer and use it in GitHub Desktop.
zookeeper mntr metrics to graphite - only sends numeric values; relies on nventory fqdns
#!/usr/bin/python
import os
import sys
import socket
import logging
import random
import re
import subprocess
import telnetlib
import time
import argparse
from StringIO import StringIO
class ZooKeeperServer(object):
def __init__(self, host='localhost', port='2181', timeout=1):
self._address = (host, int(port))
self._timeout = timeout
def get_stats(self):
""" Get ZooKeeper server stats as a map """
data = self._send_cmd('mntr')
if data:
return self._parse(data)
else:
data = self._send_cmd('stat')
return self._parse_stat(data)
def _create_socket(self):
return socket.socket()
def _send_cmd(self, cmd):
""" Send a 4letter word command to the server """
s = self._create_socket()
s.settimeout(self._timeout)
s.connect(self._address)
s.send(cmd)
data = s.recv(2048)
s.close()
return data
def _parse_line(self, line):
try:
key, value = map(str.strip, line.split('\t'))
except ValueError:
raise ValueError('Found invalid line: %s' % line)
if not key:
raise ValueError('The key is mandatory and should not be empty')
try:
value = int(value)
except (TypeError, ValueError):
pass
return key, value
def _parse(self, data):
""" Parse the output from the 'mntr' 4letter word command """
h = StringIO(data)
result = {}
for line in h.readlines():
try:
key, value = self._parse_line(line)
result[key] = value
except ValueError:
pass # ignore broken lines
return result
def get_cluster_stats():
""" Get stats for all the servers in the cluster """
stats = {}
host = "127.0.0.1"
port = "2181"
try:
zk = ZooKeeperServer(host, port)
stats["%s:%s" % (host, port)] = zk.get_stats()
except socket.error, e:
# ignore because the cluster can still work even
# if some servers fail completely
# this error should be also visible in a variable
# exposed by the server in the statistics
logging.info('unable to connect to server '\
'"%s" on port "%s"' % (host, port))
return stats
def write_to_graphite(g_host, g_port, message):
"""Write text based data to an open tcp port"""
graphite = telnetlib.Telnet(g_host, g_port)
graphite.write(message + "\n")
graphite.close()
def main():
parser = argparse.ArgumentParser()
parser.add_argument('graphite_host',
help='name of graphite server' )
args = parser.parse_args()
host = "127.0.0.1"
port = "2181"
graphite_host = args.graphite_host
fqdncommand = "facter fqdn"
getfqdn = subprocess.Popen(fqdncommand, stdout=subprocess.PIPE, shell=True)
fqdn, err = getfqdn.communicate()
my_host = fqdn.replace('.', '_').rstrip()
my_class = fqdn[7:10]
TIMESTAMP = int(time.time())
cluster_stats = get_cluster_stats()
for server, stats in cluster_stats.items():
for key, value in stats.items():
metric_path = "%s.%s.ZK_mntr.%s" % (my_class, my_host, key)
if type(value) is int:
line = "servers.%s %s %s" % (metric_path, value, TIMESTAMP)
random.seed(my_host)
sleep = random.randint(0, 40)
logging.debug("Sleeping for %i seconds", sleep)
logging.debug("Message : \n%s", line)
write_to_graphite(graphite_host, 2003, line)
print line
else:
pass
logging.debug("Line : %s", line)
if __name__ == '__main__':
sys.exit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment