"""Configure dedicated eval run logs (defaults: repo ``logs/``; override via ``config.yaml`` ``search_evaluation.eval_log_dir``).""" from __future__ import annotations import logging import sys from pathlib import Path from .constants import EVAL_LOG_DIR _setup_done = False def setup_eval_logging(eval_log_dir: Path | None = None) -> Path: """Attach file + stderr handlers to ``search_eval`` once; ensure log directories exist. Returns the path to the primary ``eval.log`` file. """ global _setup_done log_dir = Path(eval_log_dir).resolve() if eval_log_dir is not None else EVAL_LOG_DIR.resolve() verbose_dir = log_dir / "verbose" log_file = log_dir / "eval.log" log_dir.mkdir(parents=True, exist_ok=True) verbose_dir.mkdir(parents=True, exist_ok=True) fmt = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s") root = logging.getLogger("search_eval") root.setLevel(logging.INFO) if root.handlers: _setup_done = True return log_file fh = logging.FileHandler(log_file, encoding="utf-8") fh.setFormatter(fmt) sh = logging.StreamHandler(sys.stderr) sh.setFormatter(fmt) root.addHandler(fh) root.addHandler(sh) root.propagate = False _setup_done = True return log_file