"""Root-logger configuration: a rotating file handler under the same /data volume as the sqlite DB and legacy config.json, so the admin log viewer has something to read and log content survives container restarts -- a redeploy happens on every push to main touching server/**, which would make an in-memory-only log buffer nearly useless in practice. Before this, the root logger had no handler at all, so every module's logger.info() call (user creation, claims, password resets, ...) was silently dropped rather than merely un-viewable -- this fixes that too, not just adds a viewer.""" from __future__ import annotations import logging import os from logging.handlers import RotatingFileHandler from pathlib import Path LOG_PATH = Path(os.environ.get("LOG_PATH", "/data/server.log")) def configure_logging() -> None: LOG_PATH.parent.mkdir(parents=True, exist_ok=True) handler = RotatingFileHandler(LOG_PATH, maxBytes=2_000_000, backupCount=3) handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(name)s: %(message)s")) root = logging.getLogger() root.addHandler(handler) root.setLevel(os.environ.get("LOG_LEVEL", "INFO")) def read_log_tail(lines: int) -> str: if not LOG_PATH.exists(): return "" text = LOG_PATH.read_text(errors="replace") return "\n".join(text.splitlines()[-lines:])