Supervisor event listener that emails on a proces writing to stderr
#!/usr/bin/env python
import os
import smtplib
import sys
import time
from optparse import OptionParser
from supervisor import childutils
class ErrorMailer(object):
def __init__(self, address, processes=None):
self.address = address
self.processes = processes
self.stdin = sys.stdin
self.stdout = sys.stdout
self.mailcmd = "mail"
def run(self):
last_email = {}
while True:
headers, payload = childutils.listener.wait(self.stdin, self.stdout)
if headers['eventname'] not in ('PROCESS_STATE_EXITED', 'PROCESS_LOG_STDERR'):
childutils.listener.ok(self.stdout)
continue
if headers['eventname'] == 'PROCESS_STATE_EXITED':
pheaders, pdata = childutils.eventdata(payload+'\n')
if int(pheaders['expected']):
childutils.listener.ok(self.stdout)
continue
msg = ('Process %(processname)s in group %(groupname)s exited '
'unexpectedly (pid %(pid)s) from state %(from_state)s' %
pheaders)
subject = ' %s crashed at %s' % (pheaders['processname'],
childutils.get_asctime())
# self.stderr.write('unexpected exit, mailing\n')
# self.stderr.flush()
self.mail(subject, msg)
childutils.listener.ok(self.stdout)
else: # PROCESS_LOG_STDERR
pheaders, pdata = childutils.eventdata(payload)
name = pheaders['processname']
now = time.time()
if now - last_email.get(name, 0) < 30:
childutils.listener.ok(self.stdout)
continue
last_email[name] = now
subject = ('Process %(processname)s in group %(groupname)s wrote to stderr'
% pheaders)
# self.stderr.write('wrote to stderr, mailing\n')
# self.stderr.flush()
self.mail(subject, pdata.strip())
childutils.listener.ok(self.stdout)
def mail(self, subject, msg):
fromaddress = "root@localhost"
body = "\r\n".join((
"From: %s" % fromaddress,
"To: %s" % self.address,
"Subject: %s" % subject,
"",
msg,
))
server = smtplib.SMTP('localhost')
server.sendmail(fromaddress, [self.address], body)
server.quit()
def build_parser():
parser = OptionParser(usage="Usage: %prog [options]")
parser.add_option("-p", "--process", dest="processes", help="Process name", action="append")
parser.add_option("-m", "--address", dest="address", help="Email address")
return parser
def main():
parser = build_parser()
options, system = parser.parse_args()
if not options.address:
parser.error("must specify an email address")
prog = ErrorMailer(processes=options.processes, address=options.address)
prog.run()
if __name__ == '__main__':
main()