Ver Fonte

- New 'stdout_events_enabled' and 'stderr_events_enabled' config options
have been added to the '[program:x]', '[fcgi-program:x]', and
'[eventlistener:x]' sections. These enable the emitting of new
PROCESS_LOG events for a program. If unspecified, the default is False.

If enabled for a subprocess, and data is received from the stdout or
stderr of the subprocess while not in the special capture mode used by
PROCESS_COMMUNICATION, an event will be emitted.

Event listeners can subscribe to either PROCESS_LOG_STDOUT or
PROCESS_LOG_STDERR individually, or PROCESS_LOG for both.

Mike Naberezny há 16 anos atrás
pai
commit
8ac4c407f7

+ 9 - 3
CHANGES.txt

@@ -1,8 +1,14 @@
 Next Release
 
-  - Added new event types that are emitted when a subprocess sends data to
-    stdout or stderr that would be logged (i.e., data received when not in 
-    the special capture mode used by the PROCESS_COMMUNICATION events).  
+  - New 'stdout_events_enabled' and 'stderr_events_enabled' config options
+    have been added to the '[program:x]', '[fcgi-program:x]', and 
+    '[eventlistener:x]' sections.  These enable the emitting of new 
+    PROCESS_LOG events for a program.  If unspecified, the default is False.
+
+    If enabled for a subprocess, and data is received from the stdout or
+    stderr of the subprocess while not in the special capture mode used by 
+    PROCESS_COMMUNICATION, an event will be emitted.
+
     Event listeners can subscribe to either PROCESS_LOG_STDOUT or 
     PROCESS_LOG_STDERR individually, or PROCESS_LOG for both.
 

+ 16 - 7
src/supervisor/dispatchers.py

@@ -125,8 +125,10 @@ class POutputDispatcher(PDispatcher):
         self.begintoken_data = (begintoken, len(begintoken))
         self.endtoken_data = (endtoken, len(endtoken))
         self.mainlog_level = loggers.LevelsByName.DEBG
-        options_loglevel = self.process.config.options.loglevel 
-        self.log_to_mainlog = options_loglevel <= self.mainlog_level
+        config = self.process.config
+        self.log_to_mainlog = config.options.loglevel <= self.mainlog_level
+        self.stdout_events_enabled = config.stdout_events_enabled
+        self.stderr_events_enabled = config.stderr_events_enabled
 
     def removelogs(self):
         for log in (self.mainlog, self.capturelog):
@@ -153,11 +155,18 @@ class POutputDispatcher(PDispatcher):
                 config.options.logger.log(
                     self.mainlog_level, msg, name=config.name,
                     channel=self.channel, data=data)
-            if self.channel == 'stderr':
-                event = ProcessLogStderrEvent
-            else:
-                event = ProcessLogStdoutEvent
-            notify(event(self.process, self.process.pid, data))
+            if self.channel == 'stdout':
+                if self.stdout_events_enabled:
+                    notify(
+                        ProcessLogStdoutEvent(self.process, 
+                            self.process.pid, data)
+                    )
+            else: # channel == stderr
+                if self.stderr_events_enabled:
+                    notify(
+                        ProcessLogStderrEvent(self.process, 
+                            self.process.pid, data)
+                    )
 
     def record_output(self):
         if self.capturelog is None:

+ 7 - 1
src/supervisor/options.py

@@ -712,7 +712,9 @@ class ServerOptions(Options):
         process_name = get(section, 'process_name', '%(program_name)s')
         environment_str = get(section, 'environment', '')
         stdout_cmaxbytes = byte_size(get(section,'stdout_capture_maxbytes','0'))
+        stdout_events = boolean(get(section, 'stdout_events_enabled','false'))
         stderr_cmaxbytes = byte_size(get(section,'stderr_capture_maxbytes','0'))
+        stderr_events = boolean(get(section, 'stderr_events_enabled','false'))
         directory = get(section, 'directory', None)
         serverurl = get(section, 'serverurl', None)
         if serverurl and serverurl.strip().upper() == 'AUTO':
@@ -785,10 +787,12 @@ class ServerOptions(Options):
                 uid=uid,
                 stdout_logfile=logfiles['stdout_logfile'],
                 stdout_capture_maxbytes = stdout_cmaxbytes,
+                stdout_events_enabled = stdout_events,
                 stdout_logfile_backups=logfiles['stdout_logfile_backups'],
                 stdout_logfile_maxbytes=logfiles['stdout_logfile_maxbytes'],
                 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'],
                 stopsignal=stopsignal,
@@ -1470,9 +1474,11 @@ class ProcessConfig(Config):
         'name', 'uid', 'command', 'directory', 'umask', 'priority',
         'autostart', 'autorestart', 'startsecs', 'startretries',
         'stdout_logfile', 'stdout_capture_maxbytes',
+        'stdout_events_enabled',
         'stdout_logfile_backups', 'stdout_logfile_maxbytes',
-        'stderr_logfile', 'stderr_capture_maxbytes',
+        'stderr_logfile', 'stderr_capture_maxbytes', 
         'stderr_logfile_backups', 'stderr_logfile_maxbytes',
+        'stderr_events_enabled',
         'stopsignal', 'stopwaitsecs', 'exitcodes', 'redirect_stderr' ]
     optional_param_names = [ 'environment', 'serverurl' ]
 

+ 4 - 0
src/supervisor/skel/sample.conf

@@ -68,10 +68,12 @@ serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL  for a unix socket
 ;stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
 ;stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 ;stdout_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
+;stdout_event_enabled=false    ; emit events on stdout writes (default false)
 ;stderr_logfile=/a/path        ; stderr log path, NONE for none; default AUTO
 ;stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
 ;stderr_logfile_backups=10     ; # of stderr logfile backups (default 10)
 ;stderr_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
+;stderr_event_enabled=false    ; emit events on stderr writes (default false)
 ;environment=A=1,B=2           ; process environment additions (def no adds)
 ;serverurl=AUTO                ; override serverurl computation (childutils)
 
@@ -101,9 +103,11 @@ serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL  for a unix socket
 ;stdout_logfile=/a/path        ; stdout log path, NONE for none; default AUTO
 ;stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
 ;stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
+;stdout_event_enabled=false    ; emit events on stdout writes (default false)
 ;stderr_logfile=/a/path        ; stderr log path, NONE for none; default AUTO
 ;stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
 ;stderr_logfile_backups        ; # of stderr logfile backups (default 10)
+;stderr_event_enabled=false    ; emit events on stderr writes (default false)
 ;environment=A=1,B=2           ; process environment additions
 ;serverurl=AUTO                ; override serverurl computation (childutils)
 

+ 4 - 0
src/supervisor/tests/base.py

@@ -421,8 +421,10 @@ class DummyPConfig:
                  priority=999, autostart=True,
                  autorestart=True, startsecs=10, startretries=999,
                  uid=None, stdout_logfile=None, stdout_capture_maxbytes=0,
+                 stdout_events_enabled=False,
                  stdout_logfile_backups=0, stdout_logfile_maxbytes=0,
                  stderr_logfile=None, stderr_capture_maxbytes=0,
+                 stderr_events_enabled=False,
                  stderr_logfile_backups=0, stderr_logfile_maxbytes=0,
                  redirect_stderr=False,
                  stopsignal=None, stopwaitsecs=10,
@@ -438,10 +440,12 @@ class DummyPConfig:
         self.uid = uid
         self.stdout_logfile = stdout_logfile
         self.stdout_capture_maxbytes = stdout_capture_maxbytes
+        self.stdout_events_enabled = stdout_events_enabled
         self.stdout_logfile_backups = stdout_logfile_backups
         self.stdout_logfile_maxbytes = stdout_logfile_maxbytes
         self.stderr_logfile = stderr_logfile
         self.stderr_capture_maxbytes = stderr_capture_maxbytes
+        self.stderr_events_enabled = stderr_events_enabled
         self.stderr_logfile_backups = stderr_logfile_backups
         self.stderr_logfile_maxbytes = stderr_logfile_maxbytes
         self.redirect_stderr = redirect_stderr

+ 40 - 4
src/supervisor/tests/test_dispatchers.py

@@ -143,9 +143,10 @@ class POutputDispatcherTests(unittest.TestCase):
              "'process1' stdout output:\na")
         self.assertEqual(dispatcher.output_buffer, '')
 
-    def test_record_output_emits_stdout_event(self):
+    def test_record_output_emits_stdout_event_when_enabled(self):
         options = DummyOptions()
-        config = DummyPConfig(options, 'process1', '/bin/process1')
+        config = DummyPConfig(options, 'process1', '/bin/process1',
+                              stdout_events_enabled=True)
         process = DummyProcess(config)
         dispatcher = self._makeOne(process, 'stdout')
         dispatcher.output_buffer = 'hello from stdout'
@@ -162,9 +163,27 @@ class POutputDispatcherTests(unittest.TestCase):
         self.assertEqual(event.process, process)
         self.assertEqual(event.data, 'hello from stdout') 
 
-    def test_record_output_emits_stderr_event(self):
+    def test_record_output_does_not_emit_stdout_event_when_disabled(self):
         options = DummyOptions()
-        config = DummyPConfig(options, 'process1', '/bin/process1')
+        config = DummyPConfig(options, 'process1', '/bin/process1',
+                              stdout_events_enabled=False)
+        process = DummyProcess(config)
+        dispatcher = self._makeOne(process, 'stdout')
+        dispatcher.output_buffer = 'hello from stdout'
+
+        L = []
+        def doit(event):
+            L.append(event)
+        from supervisor import events
+        events.subscribe(events.EventTypes.PROCESS_LOG_STDOUT, doit)
+        dispatcher.record_output()
+
+        self.assertEqual(len(L), 0)
+
+    def test_record_output_emits_stderr_event_when_enabled(self):
+        options = DummyOptions()
+        config = DummyPConfig(options, 'process1', '/bin/process1',
+                              stderr_events_enabled=True)
         process = DummyProcess(config)
         dispatcher = self._makeOne(process, 'stderr')
         dispatcher.output_buffer = 'hello from stderr'
@@ -181,6 +200,23 @@ class POutputDispatcherTests(unittest.TestCase):
         self.assertEqual(event.process, process)
         self.assertEqual(event.data, 'hello from stderr') 
 
+    def test_record_output_does_not_emit_stderr_event_when_disabled(self):
+        options = DummyOptions()
+        config = DummyPConfig(options, 'process1', '/bin/process1',
+                              stderr_events_enabled=False)
+        process = DummyProcess(config)
+        dispatcher = self._makeOne(process, 'stderr')
+        dispatcher.output_buffer = 'hello from stderr'
+
+        L = []
+        def doit(event):
+            L.append(event)
+        from supervisor import events
+        events.subscribe(events.EventTypes.PROCESS_LOG_STDERR, doit)
+        dispatcher.record_output()
+
+        self.assertEqual(len(L), 0)
+
     def test_record_output_capturemode_string_longer_than_token(self):
         # stdout/stderr goes to the process log and the main log,
         # in capturemode, the length of the data needs to be longer

+ 7 - 1
src/supervisor/tests/test_options.py

@@ -569,6 +569,7 @@ class ServerOptionsTests(unittest.TestCase):
         stdout_logfile = NONE
         stdout_logfile_backups = 1
         stdout_logfile_maxbytes = 100MB
+        stdout_events_enabled = true
         stopsignal = KILL
         stopwaitsecs = 100
         exitcodes = 1,4
@@ -593,6 +594,7 @@ class ServerOptionsTests(unittest.TestCase):
         self.assertEqual(pconfig.stdout_logfile, None)
         self.assertEqual(pconfig.stdout_capture_maxbytes, 0)
         self.assertEqual(pconfig.stdout_logfile_maxbytes, 104857600)
+        self.assertEqual(pconfig.stdout_events_enabled, True)
         self.assertEqual(pconfig.stopsignal, signal.SIGKILL)
         self.assertEqual(pconfig.stopwaitsecs, 100)
         self.assertEqual(pconfig.exitcodes, [1,4])
@@ -1140,8 +1142,10 @@ class TestProcessConfig(unittest.TestCase):
                      'priority', 'autostart', 'autorestart',
                      'startsecs', 'startretries', 'uid',
                      'stdout_logfile', 'stdout_capture_maxbytes',
+                     'stdout_events_enabled',
                      'stdout_logfile_backups', 'stdout_logfile_maxbytes',
                      'stderr_logfile', 'stderr_capture_maxbytes',
+                     'stderr_events_enabled',
                      'stderr_logfile_backups', 'stderr_logfile_maxbytes',
                      'stopsignal', 'stopwaitsecs', 'exitcodes',
                      'redirect_stderr', 'environment'):
@@ -1212,8 +1216,10 @@ class FastCGIProcessConfigTest(unittest.TestCase):
                      'priority', 'autostart', 'autorestart',
                      'startsecs', 'startretries', 'uid',
                      'stdout_logfile', 'stdout_capture_maxbytes',
+                     'stdout_events_enabled',
                      'stdout_logfile_backups', 'stdout_logfile_maxbytes',
-                     'stderr_logfile', 'stderr_capture_maxbytes',
+                     'stderr_logfile', 'stderr_capture_maxbytes',        
+                     'stderr_events_enabled',
                      'stderr_logfile_backups', 'stderr_logfile_maxbytes',
                      'stopsignal', 'stopwaitsecs', 'exitcodes',
                      'redirect_stderr', 'environment'):

+ 2 - 0
src/supervisor/tests/test_supervisord.py

@@ -227,8 +227,10 @@ class SupervisordTests(unittest.TestCase):
                 'directory': None, 'umask': None, 'priority': 999, 'autostart': True,
                 'autorestart': True, 'startsecs': 10, 'startretries': 999,
                 'uid': None, 'stdout_logfile': None, 'stdout_capture_maxbytes': 0,
+                'stdout_events_enabled': False,
                 'stdout_logfile_backups': 0, 'stdout_logfile_maxbytes': 0,
                 'stderr_logfile': None, 'stderr_capture_maxbytes': 0,
+                'stderr_events_enabled': False,
                 'stderr_logfile_backups': 0, 'stderr_logfile_maxbytes': 0,
                 'redirect_stderr': False,
                 'stopsignal': None, 'stopwaitsecs': 10,