# src/utils/logger.py import logging import sys from typing import Optional def setup_logger( name: str = "chatbot", log_level: str = "INFO", log_file: Optional[str] = None ) -> logging.Logger: """ Set up a comprehensive logger for the application Args: name (str): Name of the logger log_level (str): Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) log_file (Optional[str]): Path to log file (optional) Returns: logging.Logger: Configured logger instance """ # Create logger logger = logging.getLogger(name) logger.setLevel(getattr(logging, log_level.upper())) # Create formatters console_formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) file_formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s' ) # Console Handler console_handler = logging.StreamHandler(sys.stdout) console_handler.setFormatter(console_formatter) logger.addHandler(console_handler) # File Handler (if log_file is provided) if log_file: file_handler = logging.FileHandler(log_file) file_handler.setFormatter(file_formatter) logger.addHandler(file_handler) return logger # Global logger instance logger = setup_logger() class AppException(Exception): """ Custom base exception for the application """ def __init__(self, message: str, error_code: Optional[str] = None): """ Initialize custom exception Args: message (str): Error message error_code (Optional[str]): Optional error code """ self.message = message self.error_code = error_code super().__init__(self.message) # Log the exception logger.error(f"AppException: {message}") class ConfigurationError(AppException): """Exception raised for configuration-related errors""" pass class LLMProviderError(AppException): """Exception raised for LLM provider-related errors""" pass class EmbeddingError(AppException): """Exception raised for embedding-related errors""" pass class VectorStoreError(AppException): """Exception raised for vector store-related errors""" pass