# utils/logging_setup.py from __future__ import annotations import logging, os, sys from typing import Optional def setup_logging(app_name: str = "videomatte", level: Optional[str] = None) -> None: """ Initialize root logging for the whole app. Call this ONCE, as early as possible (in app entrypoint), BEFORE importing modules that log. """ # Respect env var if provided; else use DEBUG in dev, INFO otherwise env_level = (level or os.environ.get("LOG_LEVEL") or "DEBUG").upper() lvl = getattr(logging, env_level, logging.DEBUG) # Make stdout unbuffered so Space/terminal shows logs immediately try: sys.stdout.reconfigure(line_buffering=True) # py3.7+ except Exception: os.environ.setdefault("PYTHONUNBUFFERED", "1") fmt = "%(asctime)s | %(levelname)-7s | %(name)s: %(message)s" datefmt = "%H:%M:%S" # Force=True ensures edits/reloads don’t leave you with no handlers logging.basicConfig( level=lvl, format=fmt, datefmt=datefmt, handlers=[logging.StreamHandler(sys.stdout)], force=True, ) # Quiet down super chatty libraries, but keep errors for noisy in ("urllib3", "PIL", "matplotlib", "numba", "hf_transfer", "transformers", "torch._dynamo"): logging.getLogger(noisy).setLevel(logging.WARNING) # Capture warnings as logs logging.captureWarnings(True) logging.getLogger(app_name).info("Logging initialized (level=%s)", env_level) def make_logger(name: str) -> logging.Logger: # Use a consistent app prefix so filtering is easy return logging.getLogger(f"videomatte.{name}")