feat: add structured logging configuration module
- Create logging_config.py with configure_logging() helper - Add tests for level setting, format, idempotency, and inheritance U1 of P2-001 (replace print with logging)
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
DEFAULT_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||||
|
|
||||||
|
|
||||||
|
def configure_logging(level: int = logging.INFO) -> None:
|
||||||
|
root = logging.getLogger()
|
||||||
|
root.setLevel(level)
|
||||||
|
|
||||||
|
if not root.handlers:
|
||||||
|
handler = logging.StreamHandler()
|
||||||
|
handler.setFormatter(logging.Formatter(DEFAULT_FORMAT))
|
||||||
|
root.addHandler(handler)
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from logging_config import configure_logging
|
||||||
|
|
||||||
|
|
||||||
|
class TestConfigureLogging:
|
||||||
|
def _clear_handlers(self):
|
||||||
|
root = logging.getLogger()
|
||||||
|
root.handlers.clear()
|
||||||
|
root.setLevel(logging.WARNING)
|
||||||
|
|
||||||
|
def test_sets_root_logger_level(self):
|
||||||
|
self._clear_handlers()
|
||||||
|
configure_logging(level=logging.DEBUG)
|
||||||
|
root = logging.getLogger()
|
||||||
|
assert root.level == logging.DEBUG
|
||||||
|
|
||||||
|
def test_default_level_is_info(self):
|
||||||
|
self._clear_handlers()
|
||||||
|
configure_logging()
|
||||||
|
root = logging.getLogger()
|
||||||
|
assert root.level == logging.INFO
|
||||||
|
|
||||||
|
def test_handler_format_includes_name_and_level(self):
|
||||||
|
self._clear_handlers()
|
||||||
|
configure_logging()
|
||||||
|
root = logging.getLogger()
|
||||||
|
assert len(root.handlers) == 1
|
||||||
|
handler = root.handlers[0]
|
||||||
|
formatter = handler.formatter
|
||||||
|
assert "%(name)s" in formatter._fmt
|
||||||
|
assert "%(levelname)s" in formatter._fmt
|
||||||
|
assert "%(asctime)s" in formatter._fmt
|
||||||
|
|
||||||
|
def test_idempotent_second_call(self):
|
||||||
|
self._clear_handlers()
|
||||||
|
configure_logging()
|
||||||
|
initial_handlers = len(logging.getLogger().handlers)
|
||||||
|
configure_logging()
|
||||||
|
assert len(logging.getLogger().handlers) == initial_handlers
|
||||||
|
|
||||||
|
def test_module_logger_inherits_level(self):
|
||||||
|
self._clear_handlers()
|
||||||
|
configure_logging(level=logging.WARNING)
|
||||||
|
logger = logging.getLogger("some.module")
|
||||||
|
assert logger.level == logging.NOTSET
|
||||||
|
assert logger.isEnabledFor(logging.WARNING)
|
||||||
|
assert not logger.isEnabledFor(logging.INFO)
|
||||||
Reference in New Issue
Block a user