aileen3-core / demo /demo_logging.py
ndurner's picture
add comments
0c163b8
from __future__ import annotations
import logging
import os
from pathlib import Path
from typing import Optional
# Lightweight logging helper for the Gradio demo.
# The MCP server has its own logging configuration; this module keeps
# demo-specific logs in a separate file referenced from the UI.
LOGGER_NAME = "aileen3_demo"
LOG_LEVEL_ENV = "AILEEN3_DEMO_LOGLEVEL"
_configured = False
_log_file_path: Path | None = None
def _resolve_level() -> int:
level_name = (os.environ.get(LOG_LEVEL_ENV) or "INFO").upper()
level = getattr(logging, level_name, None)
if isinstance(level, int):
return level
try:
return int(level_name)
except Exception:
return logging.INFO
def _pick_log_path() -> Path:
primary_base = Path(os.environ.get("AILEEN3_CACHE_DIR", Path.home() / ".cache" / "aileen3"))
primary = primary_base / "logs" / "aileen3-demo.log"
fallback = Path.cwd() / ".aileen3_logs" / "aileen3-demo.log"
for candidate in (primary, fallback):
try:
candidate.parent.mkdir(parents=True, exist_ok=True)
with open(candidate, "a", encoding="utf-8"):
pass
return candidate
except PermissionError:
continue
except OSError:
continue
# Last resort: stderr-only logger
return fallback
def _ensure_logger() -> None:
global _configured, _log_file_path
if _configured:
return
level = _resolve_level()
logger = logging.getLogger(LOGGER_NAME)
logger.setLevel(level)
logger.propagate = False
log_path = _pick_log_path()
_log_file_path = log_path
try:
handler = logging.FileHandler(log_path, encoding="utf-8")
handler.setLevel(level)
handler.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s"))
logger.addHandler(handler)
except Exception:
# Fallback to stderr only
handler = logging.StreamHandler()
handler.setLevel(level)
handler.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s"))
logger.addHandler(handler)
_configured = True
def get_demo_logger(name: Optional[str] = None) -> logging.Logger:
"""Return a logger that writes into a cache or repo-local log file."""
_ensure_logger()
return logging.getLogger(name or LOGGER_NAME)
def get_demo_log_path() -> Path:
_ensure_logger()
return _log_file_path or Path(".aileen3_logs/aileen3-demo.log")
__all__ = ["get_demo_logger", "get_demo_log_path"]