ソースを参照

Prevent empty <string>.log from multiprocessing spawn children

oslo_log derives the log filename from inspect in spawn children (python -c),
which resolves to <string>. Disable file handlers there; logs still go to the
parent via QueueHandler.
Fabian Fulga 2 週間 前
コミット
b16312b7bf

+ 2 - 1
coriolis/taskflow/runner.py

@@ -90,7 +90,8 @@ class TaskFlowRunner(object):
     def _setup_task_process_logging(self, mp_log_q):
         # Setting up logging and cfg, needed since this is a new process
         cfg.CONF(sys.argv[1:], project='coriolis', version="1.0.0")
-        utils.setup_logging()
+        # Spawn children are started via python -c; avoid creating <string>.log
+        utils.setup_logging(disable_file_handlers=True)
 
         # Log events need to be handled in the parent process
         log_root = logging.getLogger(None).logger

+ 2 - 1
coriolis/tests/taskflow/test_runner.py

@@ -116,7 +116,8 @@ class TaskFlowRunnerTestCase(test_base.CoriolisBaseTestCase):
         self.runner._setup_task_process_logging(self.mock_mp_log_q)
         mock_conf.assert_called_once_with(sys.argv[1:], project='coriolis',
                                           version='1.0.0')
-        mock_setup_logging.assert_called_once()
+        mock_setup_logging.assert_called_once_with(
+            disable_file_handlers=True)
         mock_get_logger.assert_called_once_with(None)
         mock_queue_handler.assert_called_once_with(self.mock_mp_log_q)
         mock_get_logger.return_value.logger.removeHandler.\

+ 11 - 0
coriolis/tests/test_utils.py

@@ -43,6 +43,17 @@ class UtilsTestCase(test_base.CoriolisBaseTestCase):
         utils.setup_logging()
         mock_setup.assert_called_once_with(utils.CONF, 'coriolis')
 
+    @mock.patch.object(utils.CONF, 'set_override')
+    @mock.patch('oslo_log.log.setup')
+    def test_setup_logging_disable_file_handlers(
+            self, mock_setup, mock_set_override):
+        utils.setup_logging(disable_file_handlers=True)
+        mock_set_override.assert_has_calls([
+            mock.call('log_dir', None),
+            mock.call('log_file', None),
+        ])
+        mock_setup.assert_called_once_with(utils.CONF, 'coriolis')
+
     @mock.patch.object(utils, 'get_exception_details')
     def test_ignore_exceptions(self, mock_get_details):
         mock_get_details.return_value = 'Test exception details'

+ 2 - 1
coriolis/tests/worker/rpc/test_server.py

@@ -1243,7 +1243,8 @@ class WorkerServerEndpointTestCase(test_base.CoriolisBaseTestCase):
         mock_conf.assert_called_once_with(
             mock_get_worker_count_from_args.return_value[1][1:],
             project='coriolis', version='1.0.0')
-        mock_setup_logging.assert_called_once_with()
+        mock_setup_logging.assert_called_once_with(
+            disable_file_handlers=True)
         mock_get_logger.assert_called_once_with(None)
         mock_logger.removeHandler.assert_called_once_with(
             mock.sentinel.handler)

+ 12 - 1
coriolis/utils.py

@@ -141,7 +141,18 @@ def get_diagnostics_info():
     }
 
 
-def setup_logging():
+def setup_logging(disable_file_handlers=False):
+    """Configure oslo logging for Coriolis.
+
+    :param disable_file_handlers: When True, clear log_dir/log_file so oslo_log
+        does not create a log file. Needed for multiprocessing spawn children,
+        where the binary name resolves to ``<string>`` and would otherwise
+        create an empty ``<string>.log`` under log_dir. Callers that set this
+        typically replace handlers with a QueueHandler afterwards.
+    """
+    if disable_file_handlers:
+        CONF.set_override('log_dir', None)
+        CONF.set_override('log_file', None)
     logging.setup(CONF, 'coriolis')
 
 

+ 2 - 1
coriolis/worker/rpc/server.py

@@ -666,7 +666,8 @@ def _setup_task_process(mp_log_q):
     # Setting up logging and cfg, needed since this is a new process
     _, args = service.get_worker_count_from_args(sys.argv)
     cfg.CONF(args[1:], project='coriolis', version="1.0.0")
-    utils.setup_logging()
+    # Spawn children are started via python -c; avoid creating <string>.log
+    utils.setup_logging(disable_file_handlers=True)
 
     # Log events need to be handled in the parent process
     log_root = logging.getLogger(None).logger