"""Steward's logging: one handler on the root logger, its level a setting (#5159). Until this, nothing in Steward configured logging. Lines reached the container log only because a library called basicConfig on import, so the level and the format were whatever that library chose. configure_logging runs first thing in the CLI, so a later basicConfig anywhere is a no-op. The level is the `log.level` setting, applied once settings load and again when it is saved. """ from __future__ import annotations import logging import sys LEVELS = ("DEBUG", "INFO", "WARNING", "ERROR") DEFAULT_LEVEL = "INFO" FORMAT = "%(asctime)s %(levelname)s [%(name)s] %(message)s" def set_log_level(level: object) -> str: """Set the root level; an unknown value falls back to INFO. Returns the level applied.""" name = str(level or "").strip().upper() if name not in LEVELS: name = DEFAULT_LEVEL logging.getLogger().setLevel(name) return name def configure_logging(level: object = DEFAULT_LEVEL) -> str: """Install Steward's handler on the root logger (once) and set its level.""" root = logging.getLogger() if not any(getattr(h, "_steward", False) for h in root.handlers): handler = logging.StreamHandler(sys.stderr) handler.setFormatter(logging.Formatter(FORMAT)) handler._steward = True # type: ignore[attr-defined] root.addHandler(handler) return set_log_level(level)