diff --git a/backend/bootstrap/runtime.py b/backend/bootstrap/runtime.py index 3a1ea68..52333fe 100644 --- a/backend/bootstrap/runtime.py +++ b/backend/bootstrap/runtime.py @@ -1,11 +1,23 @@ from __future__ import annotations import argparse +import logging from http.server import ThreadingHTTPServer from typing import Any +def configure_logging() -> None: + """让 INFO 级结构化日志(含 datahub 影子对比报告)落到容器日志。""" + if logging.getLogger().handlers: + return + logging.basicConfig( + level=logging.INFO, + format="%(asctime)s %(levelname)s %(name)s %(message)s", + ) + + def main(handler_class: type[Any] | None = None, service: Any | None = None) -> None: + configure_logging() if handler_class is None or service is None: from backend.application import RequestHandler, SERVICE diff --git a/tests/test_bootstrap_runtime.py b/tests/test_bootstrap_runtime.py new file mode 100644 index 0000000..20e2ea8 --- /dev/null +++ b/tests/test_bootstrap_runtime.py @@ -0,0 +1,34 @@ +import logging +import unittest + +from backend.bootstrap.runtime import configure_logging + + +class ConfigureLoggingTest(unittest.TestCase): + def setUp(self) -> None: + self._saved_handlers = logging.getLogger().handlers[:] + self._saved_level = logging.getLogger().level + logging.getLogger().handlers.clear() + + def tearDown(self) -> None: + logging.getLogger().handlers[:] = self._saved_handlers + logging.getLogger().setLevel(self._saved_level) + + def test_configures_root_logger_at_info(self) -> None: + configure_logging() + root = logging.getLogger() + self.assertTrue(root.handlers) + self.assertEqual(root.level, logging.INFO) + with self.assertLogs("xiaobai.datahub", level="INFO") as captured: + logging.getLogger("xiaobai.datahub").info("datahub shadow %s", {"dataset": "daily"}) + self.assertIn("datahub shadow", captured.output[0]) + + def test_keeps_existing_configuration(self) -> None: + handler = logging.NullHandler() + logging.getLogger().addHandler(handler) + configure_logging() + self.assertEqual(logging.getLogger().handlers, [handler]) + + +if __name__ == "__main__": + unittest.main()