Files
NF-MSL/modules/logging.py
T
2026-05-30 10:52:45 +08:00

82 lines
2.4 KiB
Python

"""
logging.py — Centralized colored logging for the NF-MSL project.
All loggers in this project propagate to the root logger, which is configured
once with coloredlogs. Named loggers (platform runners, MSL modules) only need
their level set — they inherit formatting and color from the root handler.
Set the MSL_DEBUG=1 environment variable to enable DEBUG-level output.
"""
from __future__ import annotations
import logging
import os
from typing import Optional
try:
import coloredlogs
_COLOREDLOGS = True
except ImportError:
_COLOREDLOGS = False
_ROOT_CONFIGURED = False
# ---------------------------------------------------------------------------
# Color scheme
# ---------------------------------------------------------------------------
LEVEL_STYLES: dict = {
"debug": {"color": "blue"},
"info": {"color": "green"},
"warning": {"color": "yellow", "bold": True},
"error": {"color": "red", "bold": True},
"critical": {"color": "magenta", "bold": True},
}
FIELD_STYLES: dict = {
"name": {"color": "cyan", "bold": True},
"levelname": {"color": "white", "bold": True},
"asctime": {"color": "white"},
"message": {},
}
DEFAULT_FMT = "%(name)s - %(levelname)s - %(message)s"
# ---------------------------------------------------------------------------
# Public API
# ---------------------------------------------------------------------------
def setup_logger(
name: str,
level: int = logging.INFO,
fmt: Optional[str] = None,
) -> logging.Logger:
"""Return a named logger, configuring the root handler on first call.
All loggers propagate to a single root handler so that module-level
loggers (``_log = logging.getLogger(__name__)``) automatically inherit
the same coloredlogs formatting without extra setup.
"""
global _ROOT_CONFIGURED
if not _ROOT_CONFIGURED:
root_level = logging.DEBUG if os.getenv("MSL_DEBUG") else logging.INFO
_fmt = fmt or DEFAULT_FMT
if _COLOREDLOGS:
coloredlogs.install(
level=root_level,
fmt=_fmt,
level_styles=LEVEL_STYLES,
field_styles=FIELD_STYLES,
)
else:
logging.basicConfig(level=root_level, format=_fmt)
_ROOT_CONFIGURED = True
logger = logging.getLogger(name)
logger.setLevel(level)
return logger