Venket / src /utils /logging_utils.py
venki101's picture
Add files using upload-large-folder tool
3f820d9 verified
Raw History Blame Contribute Delete
1.67 kB
"""Centralized logging configuration.
The pipeline uses ``logging`` exclusively (no ``print``). Every module obtains
its logger via :func:`get_logger`, which guarantees handlers are configured
exactly once per process, even under multiprocessing worker re-imports.
"""
from __future__ import annotations
import logging
import sys
from pathlib import Path
_CONFIGURED = False
LOG_FORMAT = "%(asctime)s | %(levelname)-8s | %(processName)s | %(name)s | %(message)s"
DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
def configure_logging(level: int = logging.INFO, log_file: "Path | None" = None) -> None:
"""Configure the root logger once for the entire process.
Args:
level: Root logging level (e.g. ``logging.INFO``, ``logging.DEBUG``).
log_file: Optional file path to additionally write logs to.
"""
global _CONFIGURED
root = logging.getLogger()
if _CONFIGURED:
root.setLevel(level)
return
root.setLevel(level)
formatter = logging.Formatter(LOG_FORMAT, datefmt=DATE_FORMAT)
stream_handler = logging.StreamHandler(stream=sys.stdout)
stream_handler.setFormatter(formatter)
root.addHandler(stream_handler)
if log_file is not None:
log_file.parent.mkdir(parents=True, exist_ok=True)
file_handler = logging.FileHandler(log_file, encoding="utf-8")
file_handler.setFormatter(formatter)
root.addHandler(file_handler)
_CONFIGURED = True
def get_logger(name: str) -> logging.Logger:
"""Return a module-scoped logger, configuring root logging with sane defaults if needed."""
if not _CONFIGURED:
configure_logging()
return logging.getLogger(name)