Skip to content

Instantly share code, notes, and snippets.

@guyc
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save guyc/3b3819d5daf207a61796 to your computer and use it in GitHub Desktop.
Save guyc/3b3819d5daf207a61796 to your computer and use it in GitHub Desktop.
Tools for writing efficient zabbix custom queries. Includes data collection for mysqladmin extended-status, mysql show slave status and port usage collected with ss
#!/usr/bin/python
#
# Command-line:
# Dump everything
# ./portstat.py
#
# Dump specific value
# ./portstat.py state-time-wait
#
# UserParameter=oth.port[*],/etc/zabbix/scripts/portstat.py '$1'
#
import sys
import pickle
import fcntl
import time
import os
import stat
import re
from collections import defaultdict
class Cache:
def __init__(self, cachefile):
self.cachefile = cachefile
def write(self, stats):
outfile = open(self.cachefile, 'wb')
pickle.dump(stats, outfile)
outfile.close
def read(self):
infile = open(self.cachefile, 'rb')
stats = pickle.load(infile)
infile.close()
return stats
def age(self):
if os.path.isfile(self.cachefile):
st = os.stat(self.cachefile)
elapsed = time.time() - st.st_mtime
else:
elapsed = None
return elapsed
#======================================================================
class ReadLock:
def __init__(self, lockfile):
self.fh = open(lockfile, 'a')
def __enter__(self):
fcntl.flock(self.fh, fcntl.LOCK_SH)
def __exit__(self, type, value, traceback):
fcntl.flock(self.fh, fcntl.LOCK_UN)
class WriteLock(ReadLock):
def __enter__(self):
fcntl.flock(self.fh, fcntl.LOCK_EX)
#======================================================================
class CustomQuery:
args = []
flags = {}
def parseargs(self):
pattern = re.compile('^-([a-z])(.*)')
for arg in sys.argv[1:]:
result = re.match(pattern, arg)
if result:
self.flags[result.group(1)]=result.group(2)
else:
self.args.append(arg)
def generate(self):
stats = defaultdict(int)
return stats
def run(self):
self.parseargs()
cache = Cache(self.cachefile)
age = cache.age()
if (age is not None and age < self.max_cache_time):
with ReadLock(self.lockfile):
stats = cache.read()
else:
stats = self.generate()
with WriteLock(self.lockfile):
cache.write(stats)
if len(self.args):
for arg in self.args:
if arg in stats:
print stats[arg]
else:
print 0
else:
for key in stats:
print "{0}:{1}".format(key, stats[key])
#!/usr/bin/python
#
from custom_query import CustomQuery
from collections import defaultdict
import subprocess
import re
class MysqlSlaveStat(CustomQuery):
def __init__(self):
self.cachefile = '/tmp/mysqlslave.cache'
self.lockfile = '/tmp/mysqlslave.lock'
self.max_cache_time = 80
def generate(self):
username = self.flags['u']
password = self.flags['p']
cmd = ['/usr/bin/mysql','-u'+username,'-p'+password,'-e','show slave status\G']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
stats = defaultdict(int)
output = proc.communicate()[0]
pattern = re.compile('^\s*([^:]+): (.*)$')
for line in output.split('\n'):
result = re.match(pattern, line)
if result:
key = result.group(1)
value = result.group(2)
stats[key] = value
return stats
MysqlSlaveStat().run()
#!/usr/bin/python
#
from custom_query import CustomQuery
from collections import defaultdict
import subprocess
import re
class MysqlStat(CustomQuery):
def __init__(self):
self.cachefile = '/tmp/mysqlstat.cache'
self.lockfile = '/tmp/mysqlstat.lock'
self.max_cache_time = 80
def generate(self):
username = self.flags['u']
password = self.flags['p']
cmd = ['/usr/bin/mysqladmin','-u'+username,'-p'+password,'extended-status']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
stats = defaultdict(int)
output = proc.communicate()[0]
pattern = re.compile('^\| ([A-Za-z_]+)\s+\| (\d+)')
for line in output.split('\n'):
result = re.match(pattern, line)
if result:
key = result.group(1)
value = result.group(2)
stats[key] = value
return stats
MysqlStat().run()
#!/usr/bin/python
#
from custom_query import CustomQuery
from collections import defaultdict
import subprocess
import re
class PortStat(CustomQuery):
def __init__(self):
self.cachefile = '/tmp/portstat.cache'
self.lockfile = '/tmp/portstat.lock'
self.max_cache_time = 80
def generate(self):
cmd = ['/usr/sbin/ss','-a']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
stats = defaultdict(int)
# discard header
output = proc.communicate()[0]
pattern = re.compile('^([A-Z-]+)\s+\d+\s+\d+\s+\S+:(\S+)\s+\S+:(\S+)')
for line in output.split('\n'):
result = re.match(pattern, line)
if result:
state = result.group(1).lower()
localport = result.group(2).lower()
remoteport = result.group(3).lower()
stats['state-any'] += 1
stats['state-'+state] += 1
stats['local-'+localport] += 1
stats['remote-'+remoteport] += 1
stats['state-'+state+'-local-'+localport] += 1
stats['state-'+state+'-remote-'+remoteport] += 1
return stats
PortStat().run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment