Spaces:
Sleeping
Sleeping
| import logging | |
| import logging.handlers | |
| import multiprocessing | |
| import datetime | |
| from pathlib import Path | |
| import atexit | |
| from typing import Tuple, Optional | |
| DEFAULT_LOGS_DIR = "logs" | |
| def setup_logging(project_name: str, logs_dir: str = DEFAULT_LOGS_DIR, level: int = logging.INFO, | |
| queue_logging: bool = True) -> Tuple[logging.Logger, Optional[logging.handlers.QueueListener]]: | |
| """ | |
| Configure parallel-safe logging. | |
| Creates a log file named ``{project_name}-{timestamp}.log`` inside ``logs_dir``. | |
| If ``queue_logging`` is True, uses ``multiprocessing.Queue`` with ``QueueHandler``/``QueueListener`` | |
| for process-safe logging. Returns the application logger and the listener (if any). | |
| Caller does not need to manage handlers individually; the listener is auto-stopped at exit. | |
| """ | |
| timestamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S") | |
| logs_path = Path(logs_dir) | |
| logs_path.mkdir(parents=True, exist_ok=True) | |
| logfile = logs_path / f"{project_name}-{timestamp}.log" | |
| formatter = logging.Formatter( | |
| fmt="%(asctime)s | %(levelname)s | %(processName)s | %(name)s | %(message)s", | |
| datefmt="%Y-%m-%d %H:%M:%S" | |
| ) | |
| logger = logging.getLogger("bidsifier") | |
| logger.setLevel(level) | |
| listener: Optional[logging.handlers.QueueListener] = None | |
| if queue_logging: | |
| log_queue: multiprocessing.Queue = multiprocessing.Queue(-1) | |
| queue_handler = logging.handlers.QueueHandler(log_queue) | |
| file_handler = logging.FileHandler(str(logfile), encoding="utf-8") | |
| file_handler.setFormatter(formatter) | |
| listener = logging.handlers.QueueListener(log_queue, file_handler) | |
| listener.start() | |
| logger.addHandler(queue_handler) | |
| def _stop_listener() -> None: | |
| try: | |
| listener.stop() | |
| except Exception: | |
| pass | |
| atexit.register(_stop_listener) | |
| else: | |
| file_handler = logging.FileHandler(str(logfile), encoding="utf-8") | |
| file_handler.setFormatter(formatter) | |
| logger.addHandler(file_handler) | |
| # Also add a simple stderr stream handler for immediate feedback. | |
| stream_handler = logging.StreamHandler() | |
| stream_handler.setFormatter(formatter) | |
| logger.addHandler(stream_handler) | |
| logger.debug("Logging initialized: %s", logfile) | |
| return logger, listener | |