Anshul Prasad
Initial commit.
9f3385c
"""
Centralized logging setup for the project.
Usage β€” call once at the very start of any entry point:
from utils.logger import setup_logging
setup_logging()
Then in any module just use:
import logging
logger = logging.getLogger(__name__)
logger.info("...")
"""
import logging
import sys
from pathlib import Path
from datetime import datetime
# ── Constants ──────────────────────────────────────────────────────────────────
LOG_DIR = Path("logs")
LOG_FMT = "%(asctime)s %(levelname)-8s [%(name)s] %(message)s"
DATE_FMT = "%Y-%m-%d %H:%M:%S"
def setup_logging(
level: int = logging.INFO,
log_dir: Path = LOG_DIR,
filename: str | None = None,
) -> None:
"""
Configure root logger to stream to both terminal and a rotating log file.
Args:
level: logging level (default: INFO)
log_dir: directory where log files are stored (default: logs/)
filename: log file name (default: YYYY-MM-DD_HH-MM-SS.log)
"""
log_dir.mkdir(parents=True, exist_ok=True)
if filename is None:
filename = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + ".log"
log_path = log_dir / filename
formatter = logging.Formatter(fmt=LOG_FMT, datefmt=DATE_FMT)
# ── Terminal handler ───────────────────────────────────────────────────────
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setFormatter(formatter)
stream_handler.setLevel(level)
# ── File handler ───────────────────────────────────────────────────────────
file_handler = logging.FileHandler(log_path, encoding="utf-8")
file_handler.setFormatter(formatter)
file_handler.setLevel(level)
# ── Root logger ────────────────────────────────────────────────────────────
root = logging.getLogger()
root.setLevel(level)
# Avoid adding duplicate handlers if called more than once
if not root.handlers:
root.addHandler(stream_handler)
root.addHandler(file_handler)
else:
root.handlers.clear()
root.addHandler(stream_handler)
root.addHandler(file_handler)
logging.info("Logging initialised β†’ %s", log_path)