hi chris

updated memmon.py, docs and tests.
patch attached.

not sure about the additional test_subject_no_name.
maybe there is a way to test this in a cleaner way?

i did not test the option/argument parser yet.


would be great to see a 0.6 release soon, so i can use the new feature in 
production ;-)

regards, harald


Am Freitag, 30. Juli 2010, um 08:48:21 schrieb Chris McDonough:
> On Fri, 2010-07-30 at 08:42 +0200, Harald Friessnegger wrote:
> > hi chris
> > 
> > you are right about the slam-dunk, and about the *-mail.
> > 
> > i'll see if i can add the feature this weekend - looks like it'll be
> > raining anyway here in austria ;-)
> > 
> > could you give me access to http://svn.supervisord.org/superlance/ or do
> > you prefere a patch for current trunk?
> 
> A patch is fine.  The tests can be run via "python setup.py test".
> Please add tests if possible, too.  There are docs in the "docs"
> directory of superlance that will need updating too.
> 
> Thanks!


-- 
Webmeisterei GmbH - Büro für Netzfragen
Tel: +43 5572 908877,  Fax: +43 5572 908877-66
Steinebach 18, A-6850 Dornbirn

http://www.webmeisterei.com
Index: CHANGES.txt
===================================================================
--- CHANGES.txt (revision 980)
+++ CHANGES.txt (working copy)
@@ -4,6 +4,12 @@
 Next Release
 ------------
 
+- Added ``-n`` option to memmon that adds this name to the email
+  subject to identify which memmon process restarted a process.
+  Useful in case you run multiple supervisors that control
+  different processes with the same name.
+  [fRiSi]
+
 - Separated unit tests into their own files
 
 - Created ``fatalmailbatch`` plugin
Index: docs/memmon.rst
===================================================================
--- docs/memmon.rst     (revision 980)
+++ docs/memmon.rst     (working copy)
@@ -29,7 +29,7 @@
 .. code-block:: sh
 
    $ memmon [-p processname=byte_size] [-g groupname=byte_size] \
-            [-a byte_size] [-s sendmail] [-m email_address]
+            [-a byte_size] [-s sendmail] [-m email_address] [-n memmon_name]
 
 .. program:: memmon
 
@@ -84,6 +84,17 @@
    By default, memmon will not send any mail unless an email address is
    specified.
 
+.. cmdoption:: -n <memmon name>, --name=<memmon name>
+
+   An optional name that identifies this memmon process. If given, the
+   email subject will start with ``memmon [<memmon name>]:`` instead
+   of ``memmon:``
+   In case you run multiple supervisors on a single host that control
+   different processes with the same name (eg `zopeinstance1`) you can
+   use this option to indicate which project the restarted instance
+   belongs to.
+
+
 
 Configuring :command:`memmon` Into the Supervisor Config
 --------------------------------------------------------
Index: superlance/memmon.py
===================================================================
--- superlance/memmon.py        (revision 980)
+++ superlance/memmon.py        (working copy)
@@ -27,8 +27,9 @@
 # events=TICK_60
 
 doc = """\
-memmon.py [-p processname=byte_size]  [-g groupname=byte_size] 
+memmon.py [-p processname=byte_size]  [-g groupname=byte_size]
           [-a byte_size] [-s sendmail] [-m email_address]
+          [-n memmon_name]
 
 Options:
 
@@ -36,10 +37,10 @@
       process named 'process_name' when it uses more than byte_size
       RSS.  If this process is in a group, it can be specified using
       the 'process_name:group_name' syntax.
-      
+
 -g -- specify a group_name=byte_size pair.  Restart any process in this group
       when it uses more than byte_size RSS.
-      
+
 -a -- specify a global byte_size.  Restart any child of the supervisord
       under which this runs if it uses more than byte_size RSS.
 
@@ -52,6 +53,10 @@
       address when any process is restarted.  If no email address is
       specified, email will not be sent.
 
+-n -- optionally specify the name of the memmon process. This name will
+      be used in the email subject to identify which memmon process
+      restarted the process.
+
 The -p and -g options may be specified more than once, allowing for
 specification of multiple groups and processes.
 
@@ -61,7 +66,7 @@
 
 A sample invocation:
 
-memmon.py -p program1=200MB -p theprog:thegroup=100MB -g thegroup=100MB -a 1GB 
-s "/usr/sbin/sendmail -t -i" -m [email protected]
+memmon.py -p program1=200MB -p theprog:thegroup=100MB -g thegroup=100MB -a 1GB 
-s "/usr/sbin/sendmail -t -i" -m [email protected] -n "Project 1"
 """
 
 import os
@@ -80,12 +85,13 @@
     return os.popen(cmd).read()
 
 class Memmon:
-    def __init__(self, programs, groups, any, sendmail, email, rpc):
+    def __init__(self, programs, groups, any, sendmail, email, name, rpc):
         self.programs = programs
         self.groups = groups
         self.any = any
         self.sendmail = sendmail
         self.email = email
+        self.memmonName = name
         self.rpc = rpc
         self.stdin = sys.stdin
         self.stdout = sys.stdout
@@ -174,7 +180,7 @@
 
     def restart(self, name, rss):
         self.stderr.write('Restarting %s\n' % name)
-
+        memmonId = self.memmonName and " [%s]" % self.memmonName or ""
         try:
             self.rpc.supervisor.stopProcess(name)
         except xmlrpclib.Fault, what:
@@ -182,7 +188,7 @@
                    (name, rss, what))
             self.stderr.write(str(msg))
             if self.email:
-                subject = 'memmon: failed to stop process %s, exiting' % name
+                subject = 'memmon%s: failed to stop process %s, exiting' % 
(memmonId, name)
                 self.mail(self.email, subject, msg)
             raise
 
@@ -193,7 +199,7 @@
                    'exiting: %s' % (name, what))
             self.stderr.write(str(msg))
             if self.email:
-                subject = 'memmon: failed to start process %s, exiting' % name
+                subject = 'memmon%s: failed to start process %s, exiting' % 
(memmonId, name)
                 self.mail(self.email, subject, msg)
             raise
 
@@ -204,7 +210,7 @@
                 'it was consuming too much memory (%s bytes RSS)' % (
                 name, now, rss)
                 )
-            subject = 'memmon: process %s restarted' % name
+            subject = 'memmon%s: process %s restarted' % (memmonId, name)
             self.mail(self.email, subject, msg)
 
     def mail(self, email, subject, msg):
@@ -216,7 +222,7 @@
         m.write(body)
         m.close()
         self.mailed = body
-        
+
 def parse_namesize(option, value):
     try:
         name, size = value.split('=')
@@ -232,12 +238,12 @@
     except:
         print 'Unparseable byte_size in %r for %r' % (value, option)
         usage()
-        
+
     return size
 
 def main():
     import getopt
-    short_args="hp:g:a:s:m:"
+    short_args="hp:g:a:s:m:n:"
     long_args=[
         "help",
         "program=",
@@ -245,6 +251,7 @@
         "any=",
         "sendmail_program=",
         "email=",
+        "name=",
         ]
     arguments = sys.argv[1:]
     if not arguments:
@@ -260,6 +267,7 @@
     any = None
     sendmail = '/usr/sbin/sendmail -t -i'
     email = None
+    name = None
 
     for option, value in opts:
 
@@ -284,12 +292,15 @@
         if option in ('-m', '--email'):
             email = value
 
+        if option in ('-n', '--name'):
+            name = value
+
     rpc = childutils.getRPCInterface(os.environ)
-    memmon = Memmon(programs, groups, any, sendmail, email, rpc)
+    memmon = Memmon(programs, groups, any, sendmail, email, name, rpc)
     memmon.runforever()
 
 if __name__ == '__main__':
     main()
-    
-    
-    
+
+
+
Index: superlance/tests/memmon_test.py
===================================================================
--- superlance/tests/memmon_test.py     (revision 980)
+++ superlance/tests/memmon_test.py     (working copy)
@@ -7,7 +7,7 @@
     def _getTargetClass(self):
         from superlance.memmon import Memmon
         return Memmon
-    
+
     def _makeOne(self, *opts):
         return self._getTargetClass()(*opts)
 
@@ -15,13 +15,14 @@
         rpc = DummyRPCServer()
         sendmail = 'cat - > /dev/null'
         email = '[email protected]'
-        memmon = self._makeOne(programs, groups, any, sendmail, email, rpc)
+        name = 'test'
+        memmon = self._makeOne(programs, groups, any, sendmail, email, name, 
rpc)
         memmon.stdin = StringIO()
         memmon.stdout = StringIO()
         memmon.stderr = StringIO()
         memmon.pscommand = 'echo 22%s'
         return memmon
-        
+
     def test_runforever_notatick(self):
         programs = {'foo':0, 'bar':0, 'baz_01':0 }
         groups = {}
@@ -54,7 +55,7 @@
         self.assertEqual(len(mailed), 4)
         self.assertEqual(mailed[0], 'To: [email protected]')
         self.assertEqual(mailed[1],
-                         'Subject: memmon: process baz:baz_01 restarted')
+                         'Subject: memmon [test]: process baz:baz_01 
restarted')
         self.assertEqual(mailed[2], '')
         self.failUnless(mailed[3].startswith('memmon.py restarted'))
 
@@ -76,7 +77,7 @@
         self.assertEqual(len(mailed), 4)
         self.assertEqual(mailed[0], 'To: [email protected]')
         self.assertEqual(mailed[1],
-          'Subject: memmon: process foo:foo restarted')
+          'Subject: memmon [test]: process foo:foo restarted')
         self.assertEqual(mailed[2], '')
         self.failUnless(mailed[3].startswith('memmon.py restarted'))
 
@@ -122,7 +123,7 @@
         self.assertEqual(len(mailed), 4)
         self.assertEqual(mailed[0], 'To: [email protected]')
         self.assertEqual(mailed[1],
-                         'Subject: memmon: process baz:baz_01 restarted')
+                         'Subject: memmon [test]: process baz:baz_01 
restarted')
         self.assertEqual(mailed[2], '')
         self.failUnless(mailed[3].startswith('memmon.py restarted'))
 
@@ -188,9 +189,27 @@
         self.assertEqual(len(mailed), 4)
         self.assertEqual(mailed[0], 'To: [email protected]')
         self.assertEqual(mailed[1],
-          'Subject: memmon: failed to stop process BAD_NAME:BAD_NAME, exiting')
+          'Subject: memmon [test]: failed to stop process BAD_NAME:BAD_NAME, 
exiting')
         self.assertEqual(mailed[2], '')
         self.failUnless(mailed[3].startswith('Failed'))
-        
+
+    def test_subject_no_name(self):
+        """set the name to None to check if subject
+        stays `memmon:...` instead `memmon [<name>]:...`
+        """
+        programs = {}
+        groups = {}
+        any = 0
+        memmon = self._makeOnePopulated(programs, groups, any)
+        memmon.memmonName = None
+        memmon.stdin.write('eventname:TICK len:0\n')
+        memmon.stdin.seek(0)
+        memmon.runforever(test=True)
+
+        mailed = memmon.mailed.split('\n')
+        self.assertEqual(mailed[1],
+          'Subject: memmon: process baz:baz_01 restarted')
+
+
 if __name__ == '__main__':
-    unittest.main()  
\ No newline at end of file
+    unittest.main()
\ No newline at end of file
_______________________________________________
Supervisor-users mailing list
[email protected]
http://lists.supervisord.org/mailman/listinfo/supervisor-users

Reply via email to