#!/usr/bin/python ############################################################################## # # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE # ############################################################################## """%(program)s: retrieve a host's load or Zope thread status usage: %(program)s [options] mode Options: --help -- print this help text -u/--url -- the URL of the host you want to check -w/--warn -- tuple of 1m, 5m, 15m load threshold for the warning state. Ex: -w 5.0,4.0,3.0 -c/--crit -- tuple of 1m, 5m, 15m load threshold for the critical state Mode: --threads return status about the Zope threads (default) --load return status of host's load """ import getopt import os import shutil import sys import urllib STATE_OK = 0 STATE_WARN = 1 STATE_CRIT = 2 STATE_UNKNOWN = 3 def main(): try: opts, args = getopt.getopt(sys.argv[1:], "h:u:c:w:l:t:", ["help", "url","warn", "crit", "load", "threads"] ) except getopt.GetoptError, msg: usage(sys.stderr, "\nIllegal argument") mode = "t" url = "" warn = [6.0, 5.0, 3.0] crit = [7.0, 6.0, 4.0] for opt, arg in opts: if opt in ("-h", "--help"): usage(sys.stderr) if opt in ("-u", "--url"): url = arg if opt in ("-w", "--warn"): try: warn = [float(x.strip()) for x in arg.split(',')] except Exception,e: usage(sys.stderr, e) pass if opt in ("-c", "--crit"): try: crit = [float(x.strip()) for x in arg.split(',')] except Exception,e: pass if opt in ("-l", "--load"): mode = "l" if opt in ("-t", "--threads"): mode = "t" if url=='': usage(sys.stderr, "\nError: No URL supplied") result = getResult(url, mode, warn, crit) print result[1] sys.exit(result[0]) def getResult(url, mode, warn, crit): try: timer, loadelems, idle, busy = fetchThreadDump(url) except: state = STATE_CRIT info = "%s - Connection not possible" %state_text(2) return (state, info) if mode=='l': state = STATE_OK for i in range(len(loadelems)): if loadelems[i] > crit[i]: state = STATE_CRIT break elif loadelems[i] > warn[i]: state = STATE_WARN info = "%s - load average: %.2f, %.2f, %.2f|" % (state_text(state), loadelems[0], loadelems[1], loadelems[2]) return (state, info) if mode=='t': state = STATE_OK # CRITICAL if all are busy if idle==0: state = STATE_CRIT # WARNING if more than 4/5 threads are busy elif len(busy) > (4*idle): state = STATE_WARN info = "%s - BUSY: %d, IDLE; %d|" % (state_text(state), len(busy), idle) return (state, info) def state_text(state): if state==0: return "OK" if state==1: return "WARNING" if state==2: return "CRITICAL" def usage(stream, msg=None): if msg: print >>stream, msg print >>stream program = os.path.basename(sys.argv[0]) print >>stream, __doc__ % {"program": program} sys.exit(STATE_UNKNOWN) def fetchThreadDump(url): """ fetches a manage_debug_threads output """ fh = urllib.urlopen(url) data = fh.read() fh.close() threads = data.split('\n\n') idle = 0 busy = [] headline = threads[0].split(" ") timer = " ".join(headline[4:6]) loadelems = " ".join(headline[6:]) loadelems2 = [float(x) for x in headline[6:9]] for i in threads[1:]: i = i.strip() if i =='': continue if i == 'End of dump': continue lines = i.split('\n') elems = lines[0].split(' ') id = elems[1] if len(elems)>2: requrl = elems[2] + ' ' + elems[3] requrl = requrl[1:-2] busy.append((id, requrl, "\n".join(lines))) else: requrl = '' idle += 1 return (timer,loadelems2, idle, busy) if __name__ == "__main__": main()