228 lines
7.7 KiB
Python
228 lines
7.7 KiB
Python
"""
|
||
Утилиты для контекстного логирования
|
||
"""
|
||
from typing import Any, Optional, Dict, Union
|
||
from aiogram.types import Message, CallbackQuery, User
|
||
|
||
from services.infrastructure.logger import get_logger
|
||
|
||
|
||
class LoggingContext:
|
||
"""Контекст для логирования с дополнительной информацией"""
|
||
|
||
def __init__(self, module_name: str):
|
||
self.logger = get_logger(module_name)
|
||
self.context_data = {}
|
||
|
||
def add_context(self, key: str, value: Any) -> 'LoggingContext':
|
||
"""Добавить данные в контекст"""
|
||
self.context_data[key] = value
|
||
return self
|
||
|
||
def log_info(self, message: str, **kwargs):
|
||
"""Логирование с контекстом"""
|
||
context_str = self._format_context()
|
||
full_message = f"{message}{context_str}"
|
||
self.logger.info(full_message, **kwargs)
|
||
|
||
def log_warning(self, message: str, **kwargs):
|
||
"""Логирование предупреждения с контекстом"""
|
||
context_str = self._format_context()
|
||
full_message = f"{message}{context_str}"
|
||
self.logger.warning(full_message, **kwargs)
|
||
|
||
def log_error(self, message: str, **kwargs):
|
||
"""Логирование ошибки с контекстом"""
|
||
context_str = self._format_context()
|
||
full_message = f"{message}{context_str}"
|
||
self.logger.error(full_message, **kwargs)
|
||
|
||
def _format_context(self) -> str:
|
||
"""Форматирование контекстных данных"""
|
||
if not self.context_data:
|
||
return ""
|
||
|
||
context_parts = [f"{k}={v}" for k, v in self.context_data.items()]
|
||
return f" | {', '.join(context_parts)}"
|
||
|
||
|
||
def get_logging_context(module_name: str) -> LoggingContext:
|
||
"""Получить контекст логирования для модуля"""
|
||
return LoggingContext(module_name)
|
||
|
||
|
||
def log_user_action(
|
||
logger,
|
||
action: str,
|
||
user: Union[User, Message, CallbackQuery, int],
|
||
additional_info: Optional[Dict[str, Any]] = None
|
||
):
|
||
"""
|
||
Логирование действий пользователя
|
||
|
||
Args:
|
||
logger: Логгер
|
||
action: Действие пользователя
|
||
user: Объект пользователя, сообщение, callback или user_id
|
||
additional_info: Дополнительная информация
|
||
"""
|
||
user_id = _extract_user_id(user)
|
||
user_info = _extract_user_info(user)
|
||
|
||
context_parts = [f"user_id={user_id}"]
|
||
if user_info:
|
||
context_parts.append(f"user_info={user_info}")
|
||
|
||
if additional_info:
|
||
for key, value in additional_info.items():
|
||
context_parts.append(f"{key}={value}")
|
||
|
||
context_str = f" | {', '.join(context_parts)}" if context_parts else ""
|
||
logger.info(f"👤 {action}{context_str}")
|
||
|
||
|
||
def log_business_operation(
|
||
logger,
|
||
operation: str,
|
||
entity_type: str,
|
||
entity_id: Optional[Union[int, str]] = None,
|
||
additional_info: Optional[Dict[str, Any]] = None
|
||
):
|
||
"""
|
||
Логирование бизнес-операций
|
||
|
||
Args:
|
||
logger: Логгер
|
||
operation: Операция (create, update, delete, etc.)
|
||
entity_type: Тип сущности (question, user, etc.)
|
||
entity_id: ID сущности
|
||
additional_info: Дополнительная информация
|
||
"""
|
||
context_parts = [f"operation={operation}", f"entity_type={entity_type}"]
|
||
|
||
if entity_id is not None:
|
||
context_parts.append(f"entity_id={entity_id}")
|
||
|
||
if additional_info:
|
||
for key, value in additional_info.items():
|
||
context_parts.append(f"{key}={value}")
|
||
|
||
context_str = f" | {', '.join(context_parts)}"
|
||
logger.info(f"📊 Бизнес-операция: {operation} {entity_type}{context_str}")
|
||
|
||
|
||
def log_fsm_event(
|
||
logger,
|
||
event: str,
|
||
state: Optional[str] = None,
|
||
user_id: Optional[int] = None,
|
||
additional_info: Optional[Dict[str, Any]] = None
|
||
):
|
||
"""
|
||
Логирование FSM событий
|
||
|
||
Args:
|
||
logger: Логгер
|
||
event: Событие FSM
|
||
state: Текущее состояние
|
||
user_id: ID пользователя
|
||
additional_info: Дополнительная информация
|
||
"""
|
||
context_parts = [f"event={event}"]
|
||
|
||
if state:
|
||
context_parts.append(f"state={state}")
|
||
|
||
if user_id:
|
||
context_parts.append(f"user_id={user_id}")
|
||
|
||
if additional_info:
|
||
for key, value in additional_info.items():
|
||
context_parts.append(f"{key}={value}")
|
||
|
||
context_str = f" | {', '.join(context_parts)}"
|
||
logger.info(f"🔄 FSM: {event}{context_str}")
|
||
|
||
|
||
def log_performance(
|
||
logger,
|
||
operation: str,
|
||
duration: float,
|
||
additional_info: Optional[Dict[str, Any]] = None
|
||
):
|
||
"""
|
||
Логирование производительности
|
||
|
||
Args:
|
||
logger: Логгер
|
||
operation: Операция
|
||
duration: Время выполнения в секундах
|
||
additional_info: Дополнительная информация
|
||
"""
|
||
context_parts = [f"duration={duration:.3f}s"]
|
||
|
||
if additional_info:
|
||
for key, value in additional_info.items():
|
||
context_parts.append(f"{key}={value}")
|
||
|
||
context_str = f" | {', '.join(context_parts)}"
|
||
logger.info(f"⏱️ Производительность: {operation}{context_str}")
|
||
|
||
|
||
def _extract_user_id(user: Union[User, Message, CallbackQuery, int]) -> int:
|
||
"""Извлечение user_id из различных объектов"""
|
||
if isinstance(user, int):
|
||
return user
|
||
elif isinstance(user, User):
|
||
return user.id
|
||
elif isinstance(user, (Message, CallbackQuery)):
|
||
return user.from_user.id
|
||
else:
|
||
return 0
|
||
|
||
|
||
def _extract_user_info(user: Union[User, Message, CallbackQuery, int]) -> Optional[str]:
|
||
"""Извлечение информации о пользователе"""
|
||
if isinstance(user, int):
|
||
return None
|
||
elif isinstance(user, User):
|
||
return f"{user.first_name or ''} {user.last_name or ''}".strip() or user.username or "Unknown"
|
||
elif isinstance(user, (Message, CallbackQuery)):
|
||
user_obj = user.from_user
|
||
return f"{user_obj.first_name or ''} {user_obj.last_name or ''}".strip() or user_obj.username or "Unknown"
|
||
else:
|
||
return None
|
||
|
||
|
||
# Удобные функции для быстрого логирования
|
||
def log_question_created(logger, question_id: int, from_user_id: int, to_user_id: int):
|
||
"""Логирование создания вопроса"""
|
||
log_business_operation(
|
||
logger, "create", "question", question_id,
|
||
{"from_user_id": from_user_id, "to_user_id": to_user_id}
|
||
)
|
||
|
||
|
||
def log_question_answered(logger, question_id: int, user_id: int):
|
||
"""Логирование ответа на вопрос"""
|
||
log_business_operation(
|
||
logger, "answer", "question", question_id,
|
||
{"user_id": user_id}
|
||
)
|
||
|
||
|
||
def log_user_created(logger, user_id: int, username: Optional[str] = None):
|
||
"""Логирование создания пользователя"""
|
||
additional_info = {"username": username} if username else None
|
||
log_business_operation(
|
||
logger, "create", "user", user_id, additional_info
|
||
)
|
||
|
||
|
||
def log_user_blocked(logger, user_id: int, reason: Optional[str] = None):
|
||
"""Логирование блокировки пользователя"""
|
||
additional_info = {"reason": reason} if reason else None
|
||
log_business_operation(
|
||
logger, "block", "user", user_id, additional_info
|
||
)
|