zabbix-trappers/scripts/apache.trap.py
2013-06-28 12:42:51 -04:00

263 lines
9.1 KiB
Python
Executable file

#!/usr/bin/python2
""" Fetch Apache stats via mod_status and send to Zabbix
By Paulson McIntyre
Patches by:
Zach Bailey <znbailey@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import urllib
from optparse import OptionParser
import os
from tempfile import mkstemp
import StringIO
import csv
import socket
class ErrorSendingValues(RuntimeError):
""" An error occured while sending the values to the Zabbix
server using zabbix_sender.
"""
def fetchURL(url, user = None, passwd = None):
""" Return the data from a URL """
if user and passwd:
parts = url.split('://')
url = parts[0] + "://" + user + ":" + passwd + "@" + parts[1]
conn = urllib.urlopen(url)
try:
data = conn.read()
finally:
conn.close()
return data
def sendValues(filepath, zabbixserver = "localhost", zabbixport = 10051, senderloc = "zabbix_sender"):
r = os.system("%s --zabbix-server '%s' --port '%s' -i '%s' -vv" % (senderloc, zabbixserver, zabbixport, filepath))
if r != 0:
raise ErrorSendingValues, "An error occured sending the values to the server"
def clean(string, chars):
for i in chars:
string = string.replace(i, '')
return string
def parse(data):
""" Parse the CSV file into a dict of data
"""
mapping = {
"_":"Waiting For Connection",
"S":"Starting Up",
"R":"Reading Request",
"W":"Sending Reply",
"K":"KeepAlive",
"D":"DNS Lookup",
"C":"Closing Connection",
"L":"Logging",
"G":"Gracefully Finishing",
"I":"Idle Cleanup Of Worker",
".":"Open slot with no current process",
}
mappingFloat = [
"CPULoad",
"ReqPerSec",
"BytesPerReq",
"BytesPerSec",
]
# Clean out certian chars
replace = '() '
csvobj = csv.reader(StringIO.StringIO(data), delimiter = ":", skipinitialspace = True)
ret = {}
for (key, val) in csvobj:
if key == 'Scoreboard':
sb = {
"Waiting For Connection":0,
"Starting Up":0,
"Reading Request":0,
"Sending Reply":0,
"KeepAlive":0,
"DNS Lookup":0,
"Closing Connection":0,
"Logging":0,
"Gracefully Finishing":0,
"Idle Cleanup Of Worker":0,
"Open slot with no current process":0,
}
for i in val:
sb[mapping[i]] += 1
ret[key] = sb
else:
ret[key] = val
ret2 = {}
for (key, val) in ret.items():
if key == "Scoreboard":
for (key, val) in val.items():
ret2[clean(key, replace)] = val
if key in mappingFloat:
ret2[clean(key, replace)] = float(val)
else:
ret2[clean(key, replace)] = val
return ret2
if __name__ == "__main__":
parser = OptionParser(
usage = "%prog [-z <Zabbix hostname or IP>] [-o <Apache hostname or IP>]",
version = "%prog $Revision$",
prog = "ApacheStatsForZabbix",
description = """This program gathers data from Apache's
built-in status page and sends it to
Zabbix. The data is sent via zabbix_sender.
Author: Paulson McIntyre (GpMidi)
License: GPLv2
""",
)
parser.add_option(
"-l",
"--url",
action = "store",
type = "string",
dest = "url",
default = None,
help = "Override the automatically generated URL with one of your own",
)
parser.add_option(
"-o",
"--host",
action = "store",
type = "string",
dest = "host",
default = "localhost",
help = "Host to connect to. [default: %default]",
)
parser.add_option(
"-p",
"--port",
action = "store",
type = "int",
dest = "port",
default = 80,
help = "Port to connect on. [default: %default]",
)
parser.add_option(
"-r",
"--proto",
action = "store",
type = "string",
dest = "proto",
default = "http",
help = "Protocol to connect on. Can be http or https. [default: %default]",
)
parser.add_option(
"-z",
"--zabixserver",
action = "store",
type = "string",
dest = "zabbixserver",
default = None,
help = "Zabbix Server to send metrics to. [default: Disabled]",
)
parser.add_option(
"-u",
"--user",
action = "store",
type = "string",
dest = "user",
default = None,
help = "HTTP authentication user to use when connection. [default: None]",
)
parser.add_option(
"-a",
"--passwd",
action = "store",
type = "string",
dest = "passwd",
default = None,
help = "HTTP authentication password to use when connecting. [default: None]",
)
parser.add_option(
"-s",
"--sender",
action = "store",
type = "string",
dest = "senderloc",
default = "/usr/bin/zabbix_sender",
help = "Location to the zabbix_sender executable. [default: %default]",
)
parser.add_option(
"-q",
"--zabbixport",
action = "store",
type = "int",
dest = "zabbixport",
default = 10051,
help = "Zabbix port to connect to. [default: %default]",
)
parser.add_option(
"-c",
"--zabbixsource",
action = "store",
type = "string",
dest = "zabbixsource",
default = socket.gethostname(),
help = "Zabbix host to use when sending values. [default: %default]",
)
(opts, args) = parser.parse_args()
if opts.url and (opts.port != 80 or opts.proto != "http"):
parser.error("Can't specify -u with -p or -r")
if not opts.url:
opts.url = "%s://%s:%s/server-status?auto" % (opts.proto, opts.host, opts.port)
data = fetchURL(opts.url, user = opts.user, passwd = opts.passwd)
try:
if opts.zabbixserver is not None:
(tempfiled, tempfilepath) = mkstemp()
tempfile = open(tempfilepath, 'wb')
except:
parser.error("Error creating temporary file")
try:
data = parse(data = data)
except csv.Error:
parser.error("Error parsing returned data")
try:
for key, val in data.items():
if opts.zabbixserver is not None:
tempfile.write("%s apache[%s] %s\n" % (opts.zabbixsource, key, val))
else:
print "%s apache[%s] %s"%(opts.zabbixsource, key, val)
if opts.zabbixserver is not None:
tempfile.close()
except IndexError:
parser.error("No data")
except "bogus":
parser.error("Error creating the file to send")
try:
if opts.zabbixserver is not None:
sendValues(filepath = tempfilepath, zabbixserver = opts.zabbixserver, zabbixport = opts.zabbixport, senderloc = opts.senderloc)
except ErrorSendingValues:
parser.error("An error occurred while sending values to the Zabbix server")
finally:
if opts.zabbixserver is not None:
try:
tempfile.close()
except:
pass
os.remove(tempfilepath)