From d3dfbd1f3dc268b67e81334370bc66c231c8fd46 Mon Sep 17 00:00:00 2001 From: Cleber Rosa Date: Mon, 10 Jun 2024 07:29:56 -0400 Subject: [PATCH] Job logging: introduce buffered behavior This introduces an option that adds the buffering layer on top of the file logging handler. Plamen Dimitrov has reported issues with heavy logging causing the status server/client connection to reset. He has suggested and has been using a workaround like this. Reference: https://github.com/avocado-framework/avocado/pull/5881 Signed-off-by: Cleber Rosa --- avocado/core/job.py | 29 ++++++++++++++++++++++++----- avocado/core/output.py | 10 ++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/avocado/core/job.py b/avocado/core/job.py index 3d66e70236..9957aaac34 100644 --- a/avocado/core/job.py +++ b/avocado/core/job.py @@ -89,6 +89,19 @@ def register_job_options(): key_type=list, ) + help_msg = ( + "Whether to add a layer of memory based buffering with a given number of " + "entries. If set to 0 or less than 0, buffering disabled." + ) + settings.register_option( + section="job.run", + key="logging_buffer_size", + help_msg=help_msg, + default=0, + metavar="SIZE", + key_type=int, + ) + register_job_options() @@ -210,13 +223,15 @@ def __start_job_logging(self): # Enable test logger full_log = os.path.join(self.logdir, "full.log") fmt = "%(asctime)s %(name)s %(module)-16.16s L%(lineno)-.4d %(levelname)-5.5s| %(message)s" + buffer_size = self.config.get("job.run.logging_buffer_size") output.add_log_handler( LOG_JOB, logging.FileHandler, self.logfile, self.loglevel, fmt, - handler_filter=output.FilterTestMessage(), + output.FilterTestMessage(), + buffer_size, ) output.add_log_handler( logging.getLogger(""), @@ -224,7 +239,8 @@ def __start_job_logging(self): full_log, self.loglevel, fmt, - handler_filter=output.FilterTestMessage(), + output.FilterTestMessage(), + buffer_size, ) output.add_log_handler( logging.getLogger(""), @@ -232,7 +248,8 @@ def __start_job_logging(self): full_log, self.loglevel, "", - handler_filter=output.FilterTestMessageOnly(), + output.FilterTestMessageOnly(), + buffer_size, ) # --store-logging-stream files @@ -251,7 +268,8 @@ def __start_job_logging(self): logfile, level, fmt, - handler_filter=output.FilterTestMessage(), + output.FilterTestMessage(), + buffer_size, ) output.add_log_handler( enabled_logger, @@ -259,7 +277,8 @@ def __start_job_logging(self): logfile, level, "", - handler_filter=output.FilterTestMessageOnly(), + output.FilterTestMessageOnly(), + buffer_size, ) def __stop_job_logging(self): diff --git a/avocado/core/output.py b/avocado/core/output.py index 8e70de3f2e..86330fee25 100644 --- a/avocado/core/output.py +++ b/avocado/core/output.py @@ -17,6 +17,7 @@ """ import errno import logging +import logging.handlers import os import re import sys @@ -666,6 +667,7 @@ def add_log_handler( level=logging.DEBUG, fmt="%(name)s: %(message)s", handler_filter=None, + buffer_size=0, ): """ Add handler to a logger. @@ -678,6 +680,9 @@ def add_log_handler( :param level: Log level (defaults to `INFO``) :param fmt: Logging format (defaults to ``%(name)s: %(message)s``) :param handler_filter: Logging filter class based on logging.Filter + :param buffer_size: whether to add a layer of memory based buffering with + a given number of entries. If <= 0, buffering is + disabled. """ def save_handler(logger_name, handler): @@ -700,6 +705,11 @@ def save_handler(logger_name, handler): if handler_filter: handler.addFilter(handler_filter) + if klass == logging.FileHandler and buffer_size > 0: + buffered_wrapper = logging.handlers.MemoryHandler(buffer_size) + buffered_wrapper.setTarget(handler) + handler = buffered_wrapper + logger.addHandler(handler) save_handler(logger.name, handler) return handler