Skip to content

Instantly share code, notes, and snippets.

@samuel
Created December 17, 2010 02:50
Show Gist options
  • Save samuel/744413 to your computer and use it in GitHub Desktop.
Save samuel/744413 to your computer and use it in GitHub Desktop.
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()
@gregorynicholas
Copy link

@samuel what did your supervisord.conf config file look like to map events to this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment