Spaces:
Running
Running
File size: 1,487 Bytes
42029e4 44cd54e 42029e4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | """Structured logging using loguru.
The whole project goes through this module - never call print().
"""
from __future__ import annotations
import sys
from pathlib import Path
from loguru import logger
_INITIALISED = False
def setup_logging(level: str = "INFO", log_file: str | Path | None = None) -> None:
"""Initialise loguru sinks. Call once at process start.
Args:
level: Minimum level to emit (DEBUG / INFO / WARNING / ERROR)
log_file: Optional path to write structured logs to (JSON).
"""
global _INITIALISED
if _INITIALISED:
return
logger.remove()
logger.add(
sys.stderr,
level=level,
format=(
"<green>{time:YYYY-MM-DD HH:mm:ss}</green> | "
"<level>{level: <8}</level> | "
"<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - "
"<level>{message}</level>"
),
enqueue=True,
)
if log_file is not None:
log_path = Path(log_file)
log_path.parent.mkdir(parents=True, exist_ok=True)
logger.add(
log_path,
level=level,
rotation="50 MB",
retention="14 days",
serialize=True,
enqueue=True,
)
_INITIALISED = True
def get_logger(name: str | None = None):
"""Return a logger bound to a module name."""
if not _INITIALISED:
setup_logging()
return logger.bind(scope=name) if name else logger
|