| import logging |
| import traceback |
| import sys |
| from enum import Enum |
|
|
| |
|
|
| 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) |
|
|
|
|
| |
|
|
| class ErrorCode(Enum): |
| |
| 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" |
| |
| WEB_SEARCH_FAILED = "WEB-001" |
| WEB_FETCH_FAILED = "WEB-002" |
| WEB_EXTRACT_FAILED = "WEB-003" |
| WEB_NO_RESULTS = "WEB-004" |
| |
| BRAIN_ASK_FAILED = "BRN-001" |
| BRAIN_ASYNC_FAILED = "BRN-002" |
| |
| 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}" |
|
|