Spaces:
Sleeping
Sleeping
| """Структурированное логирование и метрики.""" | |
| import time | |
| import logging | |
| import json | |
| from typing import Dict, Any, Optional | |
| from functools import wraps | |
| from contextlib import contextmanager | |
| import psutil | |
| import torch | |
| from config.settings import config | |
| class StructuredLogger: | |
| """Структурированный логгер с метриками.""" | |
| def __init__(self, name: str): | |
| self.logger = logging.getLogger(name) | |
| self._metrics_enabled = config.ENABLE_METRICS | |
| def log_request(self, method: str, endpoint: str, **kwargs) -> None: | |
| """Логирует API запрос.""" | |
| self._log_structured("request", { | |
| "method": method, | |
| "endpoint": endpoint, | |
| **kwargs | |
| }) | |
| def log_response(self, method: str, endpoint: str, status_code: int, | |
| duration_ms: float, **kwargs) -> None: | |
| """Логирует API ответ.""" | |
| self._log_structured("response", { | |
| "method": method, | |
| "endpoint": endpoint, | |
| "status_code": status_code, | |
| "duration_ms": duration_ms, | |
| **kwargs | |
| }) | |
| def log_audio_processing(self, operation: str, file_size_bytes: int, | |
| duration_seconds: float, sample_rate: int, | |
| processing_time_ms: float, **kwargs) -> None: | |
| """Логирует обработку аудио.""" | |
| metrics = {} | |
| if self._metrics_enabled: | |
| metrics.update(self._get_system_metrics()) | |
| self._log_structured("audio_processing", { | |
| "operation": operation, | |
| "file_size_bytes": file_size_bytes, | |
| "duration_seconds": duration_seconds, | |
| "sample_rate": sample_rate, | |
| "processing_time_ms": processing_time_ms, | |
| "realtime_factor": duration_seconds * 1000 / processing_time_ms if processing_time_ms > 0 else 0, | |
| **metrics, | |
| **kwargs | |
| }) | |
| def log_model_load(self, model_name: str, load_time_ms: float, | |
| success: bool, **kwargs) -> None: | |
| """Логирует загрузку модели.""" | |
| self._log_structured("model_load", { | |
| "model": model_name, | |
| "load_time_ms": load_time_ms, | |
| "success": success, | |
| **kwargs | |
| }) | |
| def log_error(self, error_type: str, error_message: str, **kwargs) -> None: | |
| """Логирует ошибку.""" | |
| self._log_structured("error", { | |
| "error_type": error_type, | |
| "error_message": error_message, | |
| **kwargs | |
| }) | |
| def _log_structured(self, event_type: str, data: Dict[str, Any]) -> None: | |
| """Логирует структурированное сообщение.""" | |
| log_entry = { | |
| "timestamp": time.time(), | |
| "event": event_type, | |
| "service": config.APP_NAME.lower().replace(" ", "_"), | |
| **data | |
| } | |
| if config.DEBUG: | |
| self.logger.info(json.dumps(log_entry, indent=2)) | |
| else: | |
| self.logger.info(json.dumps(log_entry)) | |
| def _get_system_metrics(self) -> Dict[str, Any]: | |
| """Собирает системные метрики.""" | |
| try: | |
| # CPU и память | |
| cpu_percent = psutil.cpu_percent() | |
| memory = psutil.virtual_memory() | |
| metrics = { | |
| "cpu_percent": cpu_percent, | |
| "memory_percent": memory.percent, | |
| "memory_used_mb": memory.used / 1024 / 1024, | |
| } | |
| # GPU метрики если доступно | |
| if torch.cuda.is_available(): | |
| metrics.update({ | |
| "gpu_available": True, | |
| "gpu_memory_allocated_mb": torch.cuda.memory_allocated() / 1024 / 1024, | |
| "gpu_memory_reserved_mb": torch.cuda.memory_reserved() / 1024 / 1024, | |
| }) | |
| else: | |
| metrics["gpu_available"] = False | |
| return metrics | |
| except Exception as e: | |
| self.logger.warning("Failed to collect system metrics: %s", e) | |
| return {"metrics_error": str(e)} | |
| def timing_logger(operation: str = "operation"): | |
| """Декоратор для логирования времени выполнения.""" | |
| def decorator(func): | |
| def wrapper(*args, **kwargs): | |
| start_time = time.time() | |
| try: | |
| result = func(*args, **kwargs) | |
| duration_ms = (time.time() - start_time) * 1000 | |
| logger = StructuredLogger(func.__module__) | |
| logger.logger.debug( | |
| "%s completed in %.2fms", operation, duration_ms | |
| ) | |
| return result | |
| except Exception as e: | |
| duration_ms = (time.time() - start_time) * 1000 | |
| logger = StructuredLogger(func.__module__) | |
| logger.log_error( | |
| f"{operation}_error", | |
| str(e), | |
| duration_ms=duration_ms | |
| ) | |
| raise | |
| return wrapper | |
| return decorator | |
| def log_context(operation: str, **context_data): | |
| """Контекстный менеджер для логирования операций.""" | |
| start_time = time.time() | |
| logger = StructuredLogger(__name__) | |
| try: | |
| logger.logger.debug("Starting %s", operation) | |
| yield logger | |
| duration_ms = (time.time() - start_time) * 1000 | |
| logger.logger.debug("%s completed in %.2fms", operation, duration_ms) | |
| except Exception as e: | |
| duration_ms = (time.time() - start_time) * 1000 | |
| logger.log_error(f"{operation}_error", str(e), duration_ms=duration_ms, **context_data) | |
| raise | |
| # Глобальные логгеры | |
| request_logger = StructuredLogger("request") | |
| processing_logger = StructuredLogger("processing") | |
| model_logger = StructuredLogger("models") | |