GenerAI / errors.py
amogaddy's picture
Full AI stack: brain, knowledge_base, scraper, seed β€” FastAPI wrapper
65de2c3
Raw
History Blame Contribute Delete
2.38 kB
import logging
import traceback
import sys
from enum import Enum
# ── Logging setup ─────────────────────────────────────────────────────────────
LOG_FORMAT = "[%(asctime)s] %(levelname)-8s %(name)s β€” %(message)s"
DATE_FORMAT = "%H:%M:%S"
logging.basicConfig(
level=logging.DEBUG,
format=LOG_FORMAT,
datefmt=DATE_FORMAT,
handlers=[
logging.StreamHandler(sys.stdout),
logging.FileHandler("generai.log", encoding="utf-8"),
],
)
def get_logger(name: str) -> logging.Logger:
return logging.getLogger(name)
# ── Error categories ───────────────────────────────────────────────────────────
class ErrorCode(Enum):
# DB / Knowledge Base
KB_INIT_FAILED = "KB-001"
KB_SEARCH_FAILED = "KB-002"
KB_WRITE_FAILED = "KB-003"
KB_REINFORCE_FAILED = "KB-004"
KB_SEED_FAILED = "KB-005"
# Scraper / Web
WEB_SEARCH_FAILED = "WEB-001"
WEB_FETCH_FAILED = "WEB-002"
WEB_EXTRACT_FAILED = "WEB-003"
WEB_NO_RESULTS = "WEB-004"
# Brain
BRAIN_ASK_FAILED = "BRN-001"
BRAIN_ASYNC_FAILED = "BRN-002"
# UI
UI_INPUT_EMPTY = "UI-001"
UI_HANDLER_FAILED = "UI-002"
class GenerAIError(Exception):
"""Base exception with error code and user-friendly message."""
def __init__(self, code: ErrorCode, detail: str, cause: Exception | None = None):
self.code = code
self.detail = detail
self.cause = cause
super().__init__(f"[{code.value}] {detail}")
def user_message(self) -> str:
cause_str = f"\n> Causa: `{type(self.cause).__name__}: {self.cause}`" if self.cause else ""
return f"⚠️ **Errore {self.code.value}** β€” {self.detail}{cause_str}"
def log(self, logger: logging.Logger):
logger.error("[%s] %s", self.code.value, self.detail)
if self.cause:
logger.debug("Traceback originale:\n%s", "".join(traceback.format_exception(type(self.cause), self.cause, self.cause.__traceback__)))
def fmt_exc(e: Exception) -> str:
"""One-line summary of an exception for log messages."""
return f"{type(e).__name__}: {e}"