From 2d2ef5d72ca9db798a7518870109ac07ec0dc5be Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Sat, 2 Dec 2023 11:48:51 -0500 Subject: [PATCH 1/3] ensure that setting loglevel on one logger doesn't change others --- invokeai/backend/util/logging.py | 11 +++--- tests/backend/util/test_logging.py | 57 ++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 tests/backend/util/test_logging.py diff --git a/invokeai/backend/util/logging.py b/invokeai/backend/util/logging.py index be8aeec9c9..67419bf834 100644 --- a/invokeai/backend/util/logging.py +++ b/invokeai/backend/util/logging.py @@ -342,8 +342,7 @@ class InvokeAILogger(object): # noqa D102 cls, name: str = "InvokeAI", config: InvokeAIAppConfig = InvokeAIAppConfig.get_config() ) -> logging.Logger: # noqa D102 if name in cls.loggers: - logger = cls.loggers[name] - logger.handlers.clear() + return cls.loggers[name] else: logger = logging.getLogger(name) logger.setLevel(config.log_level.upper()) # yes, strings work here @@ -358,7 +357,7 @@ class InvokeAILogger(object): # noqa D102 handlers = [] for handler in handler_strs: handler_name, *args = handler.split("=", 2) - args = args[0] if len(args) > 0 else None + arg = args[0] if len(args) > 0 else None # console and file get the fancy formatter. # syslog gets a simple one @@ -370,16 +369,16 @@ class InvokeAILogger(object): # noqa D102 handlers.append(ch) elif handler_name == "syslog": - ch = cls._parse_syslog_args(args) + ch = cls._parse_syslog_args(arg) handlers.append(ch) elif handler_name == "file": - ch = cls._parse_file_args(args) + ch = cls._parse_file_args(arg) ch.setFormatter(formatter()) handlers.append(ch) elif handler_name == "http": - ch = cls._parse_http_args(args) + ch = cls._parse_http_args(arg) handlers.append(ch) return handlers diff --git a/tests/backend/util/test_logging.py b/tests/backend/util/test_logging.py new file mode 100644 index 0000000000..dd3cee35bc --- /dev/null +++ b/tests/backend/util/test_logging.py @@ -0,0 +1,57 @@ +""" +Test interaction of logging with configuration system. +""" +import io +import logging +import re + +from invokeai.app.services.config import InvokeAIAppConfig +from invokeai.backend.util.logging import InvokeAILogger, LOG_FORMATTERS + + +# test formatting +# Would prefer to use the capfd/capsys fixture here, but it is broken +# when used with the logging module: https://github.com/pytest-dev/pytest/issue +def test_formatting(): + logger = InvokeAILogger.get_logger() + stream = io.StringIO() + handler = logging.StreamHandler(stream) + handler.setFormatter(LOG_FORMATTERS["plain"]()) + logger.addHandler(handler) + logger.info("test1") + output = stream.getvalue() + assert re.search(r"\[InvokeAI\]::INFO --> test1$", output) + + handler.setFormatter(LOG_FORMATTERS["legacy"]()) + logger.info("test2") + output = stream.getvalue() + assert re.search(r">> test2$", output) + + +# test independence of two loggers with different names +def test_independence(): + logger1 = InvokeAILogger.get_logger() + logger2 = InvokeAILogger.get_logger("Test") + assert logger1.name == "InvokeAI" + assert logger2.name == "Test" + assert logger1.level == logging.INFO + assert logger2.level == logging.INFO + logger2.setLevel(logging.DEBUG) + assert logger1.level == logging.INFO + assert logger2.level == logging.DEBUG + + +# test that the logger is returned from two similar get_logger() calls +def test_retrieval(): + logger1 = InvokeAILogger.get_logger() + logger2 = InvokeAILogger.get_logger() + logger3 = InvokeAILogger.get_logger("Test") + assert logger1 == logger2 + assert logger1 != logger3 + + +# test that the configuration is used to set the initial logging level +def test_config(): + config = InvokeAIAppConfig(log_level="debug") + logger1 = InvokeAILogger.get_logger("DebugTest", config=config) + assert logger1.level == logging.DEBUG From bdb0d13a2d0d8dbb4c89de9bfc5f0d32bc83de59 Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Sat, 2 Dec 2023 11:56:41 -0500 Subject: [PATCH 2/3] fix import order --- tests/backend/util/test_logging.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/backend/util/test_logging.py b/tests/backend/util/test_logging.py index dd3cee35bc..0d229df7c1 100644 --- a/tests/backend/util/test_logging.py +++ b/tests/backend/util/test_logging.py @@ -6,7 +6,7 @@ import logging import re from invokeai.app.services.config import InvokeAIAppConfig -from invokeai.backend.util.logging import InvokeAILogger, LOG_FORMATTERS +from invokeai.backend.util.logging import LOG_FORMATTERS, InvokeAILogger # test formatting From 3c7d1fcd323a3283a64784f584e73932f4cb8693 Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Mon, 4 Dec 2023 22:41:59 -0500 Subject: [PATCH 3/3] clean up get_logger() call --- invokeai/app/api/routers/model_records.py | 2 +- invokeai/backend/util/logging.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/invokeai/app/api/routers/model_records.py b/invokeai/app/api/routers/model_records.py index cffca25d9f..87d8211d12 100644 --- a/invokeai/app/api/routers/model_records.py +++ b/invokeai/app/api/routers/model_records.py @@ -141,7 +141,7 @@ async def del_model_record( status_code=201, ) async def add_model_record( - config: Annotated[AnyModelConfig, Body(description="Model config", discriminator="type")] + config: Annotated[AnyModelConfig, Body(description="Model config", discriminator="type")], ) -> AnyModelConfig: """ Add a model using the configuration information appropriate for its type. diff --git a/invokeai/backend/util/logging.py b/invokeai/backend/util/logging.py index 67419bf834..c607e91835 100644 --- a/invokeai/backend/util/logging.py +++ b/invokeai/backend/util/logging.py @@ -343,12 +343,12 @@ class InvokeAILogger(object): # noqa D102 ) -> logging.Logger: # noqa D102 if name in cls.loggers: return cls.loggers[name] - else: - logger = logging.getLogger(name) + + logger = logging.getLogger(name) logger.setLevel(config.log_level.upper()) # yes, strings work here for ch in cls.get_loggers(config): logger.addHandler(ch) - cls.loggers[name] = logger + cls.loggers[name] = logger return cls.loggers[name] @classmethod