# @title utils/logger.py import logging import sys from datetime import datetime from pathlib import Path from typing import Optional, Dict, Any, Callable class SpotMakerLogger: """ Logger dla aplikacji SpotMaker. Obsługuje: - Logowanie do pliku i konsoli - Śledzenie postępu dla GUI - Logowanie szczegółowe dla każdego modułu """ def __init__(self, log_dir: str = "logs"): self.log_dir = Path(log_dir) self.log_dir.mkdir(parents=True, exist_ok=True) # Inicjalizacja głównego loggera self.logger = logging.getLogger('SpotMaker') self.logger.setLevel(logging.DEBUG) # Format logów formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) # Handler dla pliku file_handler = logging.FileHandler( self.log_dir / f"spotmaker_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log", encoding='utf-8' ) file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(formatter) # Handler dla konsoli console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(logging.INFO) console_handler.setFormatter(formatter) self.logger.addHandler(file_handler) self.logger.addHandler(console_handler) # Stan dla GUI self.current_progress: Dict[str, float] = {} self.current_status: Dict[str, str] = {} # Callback dla aktualizacji UI self.update_ui_callback: Optional[Callable] = None def log(self, module: str, message: str, level: str = "info") -> None: """ Loguje wiadomość z określonego modułu. Args: module: Nazwa modułu (np. 'video_gen', 'audio_gen') message: Treść wiadomości level: Poziom logowania ('debug', 'info', 'warning', 'error', 'critical') """ log_method = getattr(self.logger, level.lower()) formatted_msg = f"[{module}] {message}" log_method(formatted_msg) # Aktualizacja interfejsu jeśli zdefiniowano callback if self.update_ui_callback: self.update_ui_callback(formatted_msg) def update_progress(self, module: str, progress: float, status: Optional[str] = None) -> Dict[str, Any]: """ Aktualizuje postęp operacji dla danego modułu. Args: module: Nazwa modułu progress: Wartość postępu (0-100) status: Opcjonalny status tekstowy Returns: Dict zawierający aktualny stan dla GUI """ self.current_progress[module] = min(max(progress, 0), 100) if status: self.current_status[module] = status self.log(module, f"Status: {status} | Postęp: {progress:.1f}%") return { 'progress': self.current_progress, 'status': self.current_status } def get_module_progress(self, module: str) -> float: """Zwraca aktualny postęp dla danego modułu.""" return self.current_progress.get(module, 0.0) def get_module_status(self, module: str) -> str: """Zwraca aktualny status dla danego modułu.""" return self.current_status.get(module, "Nieaktywny") def reset_module(self, module: str) -> None: """Resetuje postęp i status dla danego modułu.""" self.current_progress[module] = 0.0 self.current_status[module] = "Zresetowano" self.log(module, "Zresetowano stan modułu") def format_error(self, module: str, error: Exception) -> str: """ Formatuje błąd do logowania. Args: module: Nazwa modułu error: Obiekt wyjątku Returns: Sformatowana wiadomość błędu """ error_msg = f"[{module}] Błąd: {str(error)}" self.logger.error(error_msg) return error_msg def set_ui_callback(self, callback_fn: Callable[[str], None]) -> None: """Ustawia funkcję callback do aktualizacji interfejsu.""" self.update_ui_callback = callback_fn