Parcourir la source

Revert "Merge pull request #241 from jaraco/log-targets"

The syslog changes introduced in this merge are being reverted on the
Supervisor 3.x branch only.  These changes remain in the 4.x branch.
There are a number of open issues related to syslog support now, and
more work may need to be done here.  We've decided not to release this
in 3.x, but we do intend to include it in Supervisor 4.

This reverts commit 2ab53646eb740a5e594b917e6df3e4a4ce913715, reversing
changes made to 4d4f9c9201f34b2bc5cd553ce612481c43a36d66.

Conflicts:
	docs/configuration.rst
	supervisor/tests/test_dispatchers.py
Mike Naberezny il y a 11 ans
Parent
commit
a2eef5c615

+ 0 - 6
CHANGES.txt

@@ -39,12 +39,6 @@
   a homogeneous process group.  This allows each process to have its own
   working directory.  Patch by Perttu Ranta-aho.
 
-- Added new ``stdout_syslog`` and ``stderr_syslog`` options to the config
-  file.  These are boolean options that indicate whether process output will
-  be sent to syslog.  Supervisor can now log to both files and syslog at the
-  same time.  Specifying a log filename of ``syslog`` is still supported
-  but deprecated.  Patch by Jason R. Coombs.
-
 - Removed ``setuptools`` from the ``requires`` list in ``setup.py`` because
   it caused installation issues on some systems.
 

+ 0 - 20
docs/configuration.rst

@@ -854,16 +854,6 @@ where specified.
 
   *Introduced*: 3.0a7
 
-``stdout_syslog``
-
-  If true, stdout will be directed to syslog along with the process name.
-
-  *Default*: False
-
-  *Required*:  No.
-
-  *Introduced*: 3.1a1
-
 ``stderr_logfile``
 
   Put process stderr output in this file unless ``redirect_stderr`` is
@@ -931,16 +921,6 @@ where specified.
 
   *Introduced*: 3.0a7
 
-``stderr_syslog``
-
-  If true, stderr will be directed to syslog along with the process name.
-
-  *Default*: False
-
-  *Required*:  No.
-
-  *Introduced*: 3.1a1
-
 ``environment``
 
   A list of key/value pairs in the form ``KEY="val",KEY2="val2"`` that

+ 6 - 3
docs/logging.rst

@@ -134,10 +134,13 @@ The configuration keys that influence child process logging in
 ``[program:x]`` and ``[fcgi-program:x]`` sections are these:
 
 ``redirect_stderr``, ``stdout_logfile``, ``stdout_logfile_maxbytes``,
-``stdout_logfile_backups``, ``stdout_capture_maxbytes``, ``stdout_syslog``,
+``stdout_logfile_backups``, ``stdout_capture_maxbytes``,
 ``stderr_logfile``, ``stderr_logfile_maxbytes``,
-``stderr_logfile_backups``, ``stderr_capture_maxbytes``, and
-``stderr_syslog``.
+``stderr_logfile_backups`` and ``stderr_capture_maxbytes``.
+
+One may set ``stdout_logfile`` or ``stderr_logfile`` to the
+special string "syslog". In this case, logs will be routed to the
+syslog service instead of being saved to files.
 
 ``[eventlistener:x]`` sections may not specify
 ``stdout_capture_maxbytes`` or ``stderr_capture_maxbytes``,

+ 27 - 54
supervisor/dispatchers.py

@@ -1,4 +1,3 @@
-import warnings
 import errno
 from supervisor.medusa.asyncore_25 import compact_traceback
 
@@ -62,15 +61,9 @@ class PDispatcher:
         pass
 
 class POutputDispatcher(PDispatcher):
-    """
-    A Process Output (stdout/stderr) dispatcher. Serves several purposes:
-
-    - capture output sent within <!--XSUPERVISOR:BEGIN--> and
-      <!--XSUPERVISOR:END--> tags and signal a ProcessCommunicationEvent
-      by calling notify(event).
-    - route the output to the appropriate log handlers as specified in the
-      config.
-    """
+    """ Output (stdout/stderr) dispatcher, capture output sent within
+    <!--XSUPERVISOR:BEGIN--><!--XSUPERVISOR:END--> tags and notify
+    with a ProcessCommunicationEvent """
 
     process = None # process which "owns" this dispatcher
     channel = None # 'stderr' or 'stdout'
@@ -81,25 +74,35 @@ class POutputDispatcher(PDispatcher):
     output_buffer = '' # data waiting to be logged
 
     def __init__(self, process, event_type, fd):
-        """
-        Initialize the dispatcher.
-
-        `event_type` should be one of ProcessLogStdoutEvent or
-        ProcessLogStderrEvent
-        """
         self.process = process
         self.event_type = event_type
         self.fd = fd
         self.channel = channel = self.event_type.channel
 
-        self._setup_logging(process.config, channel)
-
+        logfile = getattr(process.config, '%s_logfile' % channel)
         capture_maxbytes = getattr(process.config,
                                    '%s_capture_maxbytes' % channel)
+
+        if logfile:
+            maxbytes = getattr(process.config, '%s_logfile_maxbytes' % channel)
+            backups = getattr(process.config, '%s_logfile_backups' % channel)
+            fmt = '%(message)s'
+            if logfile == 'syslog':
+                fmt = ' '.join((process.config.name, fmt))
+            self.mainlog = process.config.options.getLogger(
+                logfile,
+                loggers.LevelsByName.INFO,
+                fmt=fmt,
+                rotating=not not maxbytes, # optimization
+                maxbytes=maxbytes,
+                backups=backups)
+
         if capture_maxbytes:
-            self.capturelog = loggers.handle_boundIO(
-                self.process.config.options.getLogger(),
-                fmt='%(message)s',
+            self.capturelog = self.process.config.options.getLogger(
+                None, # BoundIO
+                loggers.LevelsByName.INFO,
+                '%(message)s',
+                rotating=False,
                 maxbytes=capture_maxbytes,
                 )
 
@@ -116,35 +119,6 @@ class POutputDispatcher(PDispatcher):
         self.stdout_events_enabled = config.stdout_events_enabled
         self.stderr_events_enabled = config.stderr_events_enabled
 
-    def _setup_logging(self, config, channel):
-        """
-        Configure the main log according to the process' configuration and
-        channel. Sets `mainlog` on self. Returns nothing.
-        """
-
-        logfile = getattr(config, '%s_logfile' % channel)
-        if not logfile:
-            return
-
-        maxbytes = getattr(config, '%s_logfile_maxbytes' % channel)
-        backups = getattr(config, '%s_logfile_backups' % channel)
-        fmt = '%(message)s'
-        if logfile == 'syslog':
-            warnings.warn("Specifying 'syslog' for filename is deprecated. "
-                "Use %s_syslog instead." % channel, DeprecationWarning)
-            fmt = ' '.join((config.name, fmt))
-        self.mainlog = loggers.handle_file(
-            config.options.getLogger(),
-            filename=logfile,
-            fmt=fmt,
-            rotating=not not maxbytes, # optimization
-            maxbytes=maxbytes,
-            backups=backups)
-
-        if getattr(config, '%s_syslog' % channel, False):
-            fmt = config.name + ' %(message)s'
-            loggers.handle_syslog(self.mainlog, fmt)
-
     def removelogs(self):
         for log in (self.mainlog, self.capturelog):
             if log is not None:
@@ -290,14 +264,13 @@ class PEventListenerDispatcher(PDispatcher):
         if logfile:
             maxbytes = getattr(process.config, '%s_logfile_maxbytes' % channel)
             backups = getattr(process.config, '%s_logfile_backups' % channel)
-            self.childlog = loggers.handle_file(
-                process.config.options.getLogger(),
+            self.childlog = process.config.options.getLogger(
                 logfile,
+                loggers.LevelsByName.INFO,
                 '%(message)s',
                 rotating=not not maxbytes, # optimization
                 maxbytes=maxbytes,
-                backups=backups,
-            )
+                backups=backups)
 
     def removelogs(self):
         if self.childlog is not None:

+ 22 - 31
supervisor/loggers.py

@@ -322,45 +322,36 @@ class SyslogHandler(Handler):
         except:
             self.handleError()
 
-def getLogger(level=None):
-    return Logger(level)
+def getLogger(filename, level, fmt, rotating=False, maxbytes=0, backups=0,
+              stdout=False):
 
-_2MB = 1<<21
+    handlers = []
 
-def handle_boundIO(logger, fmt, maxbytes=_2MB):
-    io = BoundIO(maxbytes)
-    handler = StreamHandler(io)
-    handler.setLevel(logger.level)
-    handler.setFormat(fmt)
-    logger.addHandler(handler)
-    logger.getvalue = io.getvalue
+    logger = Logger(level)
 
-    return logger
-
-def handle_stdout(logger, fmt):
-    handler = StreamHandler(sys.stdout)
-    handler.setFormat(fmt)
-    handler.setLevel(logger.level)
-    logger.addHandler(handler)
-
-def handle_syslog(logger, fmt):
-    handler = SyslogHandler()
-    handler.setFormat(fmt)
-    handler.setLevel(logger.level)
-    logger.addHandler(handler)
+    if filename is None:
+        if not maxbytes:
+            maxbytes = 1<<21 #2MB
+        io = BoundIO(maxbytes)
+        handlers.append(StreamHandler(io))
+        logger.getvalue = io.getvalue
 
-def handle_file(logger, filename, fmt, rotating=False, maxbytes=0, backups=0):
-    if filename == 'syslog':
-        handler = SyslogHandler()
+    elif filename == 'syslog':
+        handlers.append(SyslogHandler())
 
     else:
         if rotating is False:
-            handler = FileHandler(filename)
+            handlers.append(FileHandler(filename))
         else:
-            handler = RotatingFileHandler(filename, 'a', maxbytes, backups)
+            handlers.append(RotatingFileHandler(filename,'a',maxbytes,backups))
 
-    handler.setFormat(fmt)
-    handler.setLevel(logger.level)
-    logger.addHandler(handler)
+    if stdout:
+        handlers.append(StreamHandler(sys.stdout))
+
+    for handler in handlers:
+        handler.setFormat(fmt)
+        handler.setLevel(level)
+        logger.addHandler(handler)
 
     return logger
+

+ 14 - 24
supervisor/options.py

@@ -307,7 +307,7 @@ class Options:
 
     def process_config(self, do_usage=True):
         """Process configuration data structure.
-
+        
         This includes reading config file if necessary, setting defaults etc.
         """
         if self.configfile:
@@ -440,12 +440,10 @@ class ServerOptions(Options):
         self.stdout.write('%s\n' % VERSION)
         self.exit(0)
 
-    def getLogger(self, *args, **kwargs):
-        """
-        A proxy to loggers.getLogger so the options might customize log setup.
-        Used by tests to mock log setup.
-        """
-        return loggers.getLogger(*args, **kwargs)
+    def getLogger(self, filename, level, fmt, rotating=False, maxbytes=0,
+                  backups=0, stdout=False):
+        return loggers.getLogger(filename, level, fmt, rotating, maxbytes,
+                                 backups, stdout)
 
     def realize(self, *arg, **kw):
         Options.realize(self, *arg, **kw)
@@ -830,7 +828,7 @@ class ServerOptions(Options):
                 raise ValueError(
                     '%(process_num) must be present within process_name when '
                     'numprocs > 1')
-
+                    
         if stopasgroup and not killasgroup:
             raise ValueError("Cannot set stopasgroup=true and killasgroup=false")
 
@@ -868,10 +866,6 @@ class ServerOptions(Options):
                 maxbytes = byte_size(get(section, mb_key, '50MB'))
                 logfiles[mb_key] = maxbytes
 
-                sy_key = '%s_syslog' % k
-                syslog = boolean(get(section, sy_key, False))
-                logfiles[sy_key] = syslog
-
                 if lf_val is Automatic and not maxbytes:
                     self.parse_warnings.append(
                         'For [%s], AUTO logging used for %s without '
@@ -895,13 +889,11 @@ class ServerOptions(Options):
                 stdout_events_enabled = stdout_events,
                 stdout_logfile_backups=logfiles['stdout_logfile_backups'],
                 stdout_logfile_maxbytes=logfiles['stdout_logfile_maxbytes'],
-                stdout_syslog=logfiles['stdout_syslog'],
                 stderr_logfile=logfiles['stderr_logfile'],
                 stderr_capture_maxbytes = stderr_cmaxbytes,
                 stderr_events_enabled = stderr_events,
                 stderr_logfile_backups=logfiles['stderr_logfile_backups'],
                 stderr_logfile_maxbytes=logfiles['stderr_logfile_maxbytes'],
-                stderr_syslog=logfiles['stderr_syslog'],
                 stopsignal=stopsignal,
                 stopwaitsecs=stopwaitsecs,
                 stopasgroup=stopasgroup,
@@ -1222,7 +1214,7 @@ class ServerOptions(Options):
 
             # always put our primary gid first in this list, otherwise we can
             # lose group info since sometimes the first group in the setgroups
-            # list gets overwritten on the subsequent setgid call (at least on
+            # list gets overwritten on the subsequent setgid call (at least on 
             # freebsd 9 with python 2.7 - this will be safe though for all unix
             # /python version combos)
             groups.insert(0, gid)
@@ -1315,18 +1307,16 @@ class ServerOptions(Options):
 
     def make_logger(self, critical_messages, warn_messages, info_messages):
         # must be called after realize() and after supervisor does setuid()
-        format = '%(asctime)s %(levelname)s %(message)s\n'
-        self.logger = loggers.getLogger(self.loglevel)
-        if self.nodaemon:
-            loggers.handle_stdout(self.logger, format)
-        loggers.handle_file(
-            self.logger,
+        format =  '%(asctime)s %(levelname)s %(message)s\n'
+        self.logger = loggers.getLogger(
             self.logfile,
+            self.loglevel,
             format,
             rotating=True,
             maxbytes=self.logfile_maxbytes,
             backups=self.logfile_backups,
-        )
+            stdout = self.nodaemon,
+            )
         for msg in critical_messages:
             self.logger.critical(msg)
         for msg in warn_messages:
@@ -1637,11 +1627,11 @@ class ProcessConfig(Config):
         'name', 'uid', 'command', 'directory', 'umask', 'priority',
         'autostart', 'autorestart', 'startsecs', 'startretries',
         'stdout_logfile', 'stdout_capture_maxbytes',
-        'stdout_events_enabled', 'stdout_syslog',
+        'stdout_events_enabled',
         'stdout_logfile_backups', 'stdout_logfile_maxbytes',
         'stderr_logfile', 'stderr_capture_maxbytes',
         'stderr_logfile_backups', 'stderr_logfile_maxbytes',
-        'stderr_events_enabled', 'stderr_syslog',
+        'stderr_events_enabled',
         'stopsignal', 'stopwaitsecs', 'stopasgroup', 'killasgroup',
         'exitcodes', 'redirect_stderr' ]
     optional_param_names = [ 'environment', 'serverurl' ]

+ 14 - 19
supervisor/tests/base.py

@@ -142,7 +142,7 @@ class DummyOptions:
     def get_pid(self):
         import os
         return os.getpid()
-
+        
     def check_execv_args(self, filename, argv, st):
         if filename == '/bad/filename':
             from supervisor.options import NotFound
@@ -251,8 +251,6 @@ class DummyOptions:
         self.umaskset = mask
 
 class DummyLogger:
-    level = None
-
     def __init__(self):
         self.reopened = False
         self.removed = False
@@ -269,10 +267,7 @@ class DummyLogger:
         if kw:
             msg = msg % kw
         self.data.append(msg)
-
-    def addHandler(self, handler):
-        pass
-
+        
     def reopen(self):
         self.reopened = True
     def close(self):
@@ -356,7 +351,7 @@ class DummySocketManager:
 
     def get_socket(self):
         return DummySocket(self._config.fd)
-
+        
 class DummyProcess:
     # Initial state; overridden by instance variables
     pid = 0 # Subprocess pid; 0 when not running
@@ -553,7 +548,7 @@ def makeExecutable(file, substitutions=None):
     import os
     import sys
     import tempfile
-
+    
     if substitutions is None:
         substitutions = {}
     data = open(file).read()
@@ -562,7 +557,7 @@ def makeExecutable(file, substitutions=None):
     substitutions['PYTHON'] = sys.executable
     for key in substitutions.keys():
         data = data.replace('<<%s>>' % key.upper(), substitutions[key])
-
+    
     tmpnam = tempfile.mktemp(prefix=last)
     f = open(tmpnam, 'w')
     f.write(data)
@@ -647,7 +642,7 @@ class DummyRequest:
 
     def get_server_url(self):
         return 'http://example.com'
-
+        
 
 class DummyRPCInterfaceFactory:
     def __init__(self, supervisord, **config):
@@ -822,9 +817,9 @@ class DummySupervisorRPCNamespace:
             raise Fault(xmlrpc.Faults.NOT_RUNNING, 'NOT_RUNNING')
         if name == 'FAILED':
             raise Fault(xmlrpc.Faults.FAILED, 'FAILED')
-
+        
         return True
-
+    
     def stopAllProcesses(self):
         from supervisor import xmlrpc
         return [
@@ -955,15 +950,15 @@ class DummyProcessGroup:
 
     def stop_all(self):
         self.all_stopped = True
-
+        
     def get_unstopped_processes(self):
         return self.unstopped_processes
 
     def get_dispatchers(self):
         return self.dispatchers
-
+        
 class DummyFCGIProcessGroup(DummyProcessGroup):
-
+    
     def __init__(self, config):
         DummyProcessGroup.__init__(self, config)
         self.socket_manager = DummySocketManager(config.socket_config)
@@ -1031,7 +1026,7 @@ class DummyDispatcher:
         if self.flush_error:
             raise OSError(self.flush_error)
         self.flushed = True
-
+                
 class DummyStream:
     def __init__(self, error=None):
         self.error = error
@@ -1052,7 +1047,7 @@ class DummyStream:
         pass
     def tell(self):
         return len(self.written)
-
+        
 class DummyEvent:
     def __init__(self, serial='abc'):
         if serial is not None:
@@ -1060,7 +1055,7 @@ class DummyEvent:
 
     def __str__(self):
         return 'dummy event'
-
+        
 def dummy_handler(event, result):
     pass
 

+ 1 - 1
supervisor/tests/test_dispatchers.py

@@ -102,7 +102,7 @@ class POutputDispatcherTests(unittest.TestCase):
         process.pid = 4000
         dispatcher = self._makeOne(process)
         dispatcher.capturemode = True
-        dispatcher.capturelog.getvalue = lambda: 'hallooo'
+        dispatcher.capturelog.data = ['hallooo']
         L = []
         def doit(event):
             L.append(event)

+ 5 - 5
supervisor/tests/test_options.py

@@ -978,7 +978,7 @@ class ServerOptionsTests(unittest.TestCase):
         pconfig = pconfigs[0]
         self.assertEqual(pconfig.stopasgroup, True)
         self.assertEqual(pconfig.killasgroup, True)
-
+    
     def test_processes_from_section_killasgroup_mismatch_w_stopasgroup(self):
         instance = self._makeOne()
         text = lstrip("""\
@@ -1610,10 +1610,10 @@ class TestProcessConfig(unittest.TestCase):
                      'priority', 'autostart', 'autorestart',
                      'startsecs', 'startretries', 'uid',
                      'stdout_logfile', 'stdout_capture_maxbytes',
-                     'stdout_events_enabled', 'stdout_syslog',
+                     'stdout_events_enabled',
                      'stdout_logfile_backups', 'stdout_logfile_maxbytes',
                      'stderr_logfile', 'stderr_capture_maxbytes',
-                     'stderr_events_enabled', 'stderr_syslog',
+                     'stderr_events_enabled',
                      'stderr_logfile_backups', 'stderr_logfile_maxbytes',
                      'stopsignal', 'stopwaitsecs', 'stopasgroup', 'killasgroup', 'exitcodes',
                      'redirect_stderr', 'environment'):
@@ -1684,10 +1684,10 @@ class FastCGIProcessConfigTest(unittest.TestCase):
                      'priority', 'autostart', 'autorestart',
                      'startsecs', 'startretries', 'uid',
                      'stdout_logfile', 'stdout_capture_maxbytes',
-                     'stdout_events_enabled', 'stdout_syslog',
+                     'stdout_events_enabled',
                      'stdout_logfile_backups', 'stdout_logfile_maxbytes',
                      'stderr_logfile', 'stderr_capture_maxbytes',
-                     'stderr_events_enabled', 'stderr_syslog',
+                     'stderr_events_enabled',
                      'stderr_logfile_backups', 'stderr_logfile_maxbytes',
                      'stopsignal', 'stopwaitsecs', 'stopasgroup', 'killasgroup', 'exitcodes',
                      'redirect_stderr', 'environment'):

+ 6 - 9
supervisor/tests/test_supervisord.py

@@ -62,7 +62,7 @@ class SupervisordTests(unittest.TestCase):
     def tearDown(self):
         from supervisor.events import clear
         clear()
-
+        
     def _getTargetClass(self):
         from supervisor.supervisord import Supervisor
         return Supervisor
@@ -131,7 +131,7 @@ class SupervisordTests(unittest.TestCase):
         process.waitstatus = None, None
         options.pidhistory = {1:process}
         supervisord = self._makeOne(options)
-
+        
         supervisord.reap(once=True)
         self.assertEqual(process.finished, (1,1))
 
@@ -283,17 +283,14 @@ class SupervisordTests(unittest.TestCase):
                 'uid': None, 'stdout_logfile': None, 'stdout_capture_maxbytes': 0,
                 'stdout_events_enabled': False,
                 'stdout_logfile_backups': 0, 'stdout_logfile_maxbytes': 0,
-                'stdout_syslog': False,
                 'stderr_logfile': None, 'stderr_capture_maxbytes': 0,
                 'stderr_events_enabled': False,
                 'stderr_logfile_backups': 0, 'stderr_logfile_maxbytes': 0,
-                'stderr_syslog': False,
                 'redirect_stderr': False,
                 'stopsignal': None, 'stopwaitsecs': 10,
                 'stopasgroup': False,
                 'killasgroup': False,
-                'exitcodes': (0,2), 'environment': None, 'serverurl': None,
-            }
+                'exitcodes': (0,2), 'environment': None, 'serverurl': None }
             result.update(params)
             return ProcessConfig(options, **result)
 
@@ -512,7 +509,7 @@ class SupervisordTests(unittest.TestCase):
         self.assertTrue(isinstance(L[0], events.SupervisorStateChangeEvent))
         self.assertTrue(isinstance(L[1], events.SupervisorStoppingEvent))
         self.assertTrue(isinstance(L[1], events.SupervisorStateChangeEvent))
-
+        
     def test_exit(self):
         options = DummyOptions()
         supervisord = self._makeOne(options)
@@ -573,14 +570,14 @@ class SupervisordTests(unittest.TestCase):
         self.assertEqual(supervisord.ticks[3600], 0)
         self.assertEqual(len(L), 1)
         self.assertEqual(L[-1].__class__, events.Tick5Event)
-
+        
         supervisord.tick(now=61)
         self.assertEqual(supervisord.ticks[5], 60)
         self.assertEqual(supervisord.ticks[60], 60)
         self.assertEqual(supervisord.ticks[3600], 0)
         self.assertEqual(len(L), 3)
         self.assertEqual(L[-1].__class__, events.Tick60Event)
-
+        
         supervisord.tick(now=3601)
         self.assertEqual(supervisord.ticks[5], 3600)
         self.assertEqual(supervisord.ticks[60], 3600)