""" Logging Configuration Module Cấu hình logging tập trung cho toàn bộ ứng dụng """ import logging import logging.handlers from pathlib import Path from datetime import datetime from typing import Optional from .setting import settings class LoggerSetup: """Cấu hình logging cho ứng dụng""" def __init__(self): self.log_dir = Path(__file__).resolve().parents[2] / "logs" self.log_dir.mkdir(exist_ok=True) self.setup_done = False def setup_logging(self, log_level: Optional[str] = None, enable_file_logging: bool = True, enable_console_logging: bool = True) -> None: """ Cấu hình logging cho toàn bộ ứng dụng Args: log_level: Mức độ log (DEBUG, INFO, WARNING, ERROR, CRITICAL) enable_file_logging: Có ghi log ra file không enable_console_logging: Có hiển thị log trên console không """ if self.setup_done: return # Sử dụng log level từ settings nếu không được truyền vào if log_level is None: log_level = settings.LOG_LEVEL # Cấu hình root logger root_logger = logging.getLogger() root_logger.setLevel(getattr(logging, log_level.upper())) # Xóa các handler cũ nếu có for handler in root_logger.handlers[:]: root_logger.removeHandler(handler) # Định dạng log message formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) detailed_formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(funcName)s() - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) # Console handler if enable_console_logging: console_handler = logging.StreamHandler() console_handler.setLevel(getattr(logging, log_level.upper())) console_handler.setFormatter(formatter) root_logger.addHandler(console_handler) # File handlers if enable_file_logging: # General log file (with rotation) general_log_file = self.log_dir / "transportation.log" file_handler = logging.handlers.RotatingFileHandler( general_log_file, maxBytes=10*1024*1024, # 10MB backupCount=5, encoding='utf-8' ) file_handler.setLevel(logging.INFO) file_handler.setFormatter(detailed_formatter) root_logger.addHandler(file_handler) # Error log file (only errors and above) error_log_file = self.log_dir / "errors.log" error_handler = logging.handlers.RotatingFileHandler( error_log_file, maxBytes=10*1024*1024, # 10MB backupCount=3, encoding='utf-8' ) error_handler.setLevel(logging.ERROR) error_handler.setFormatter(detailed_formatter) root_logger.addHandler(error_handler) # Daily log file (one file per day) daily_log_file = self.log_dir / f"daily_{datetime.now().strftime('%Y%m%d')}.log" daily_handler = logging.handlers.TimedRotatingFileHandler( daily_log_file, when='midnight', interval=1, backupCount=30, # Keep 30 days encoding='utf-8' ) daily_handler.setLevel(logging.DEBUG) daily_handler.setFormatter(detailed_formatter) root_logger.addHandler(daily_handler) # Cấu hình cho các logger cụ thể self._configure_specific_loggers() self.setup_done = True logging.info("Logging system initialized successfully") def _configure_specific_loggers(self): """Cấu hình các logger cho các module cụ thể""" # FastAPI và Uvicorn logging.getLogger("uvicorn").setLevel(logging.INFO) logging.getLogger("uvicorn.access").setLevel(logging.WARNING) logging.getLogger("fastapi").setLevel(logging.INFO) # Transportation specific loggers logging.getLogger("transportation").setLevel(logging.INFO) logging.getLogger("prediction").setLevel(logging.INFO) logging.getLogger("chat").setLevel(logging.INFO) # External libraries logging.getLogger("requests").setLevel(logging.WARNING) logging.getLogger("urllib3").setLevel(logging.WARNING) logging.getLogger("google").setLevel(logging.WARNING) def get_logger(self, name: str) -> logging.Logger: """ Lấy logger với tên cụ thể Args: name: Tên của logger (thường là __name__) Returns: Logger instance """ if not self.setup_done: self.setup_logging() return logging.getLogger(name) # Global logger setup instance logger_setup = LoggerSetup() def get_logger(name: str) -> logging.Logger: """ Convenience function để lấy logger Usage: from src.config.logging_config import get_logger logger = get_logger(__name__) """ return logger_setup.get_logger(name) def setup_logging(**kwargs): """ Convenience function để setup logging Usage: from src.config.logging_config import setup_logging setup_logging(log_level="DEBUG") """ return logger_setup.setup_logging(**kwargs)