Refactor Docker and configuration files for improved structure and functionality
- Updated `.dockerignore` to include additional development and temporary files, enhancing build efficiency. - Modified `.gitignore` to remove unnecessary entries and streamline ignored files. - Enhanced `docker-compose.yml` with health checks, resource limits, and improved environment variable handling for better service management. - Refactored `Dockerfile.bot` to utilize a multi-stage build for optimized image size and security. - Improved `Makefile` with new commands for deployment, migration, and backup, along with enhanced help documentation. - Updated `requirements.txt` to include new dependencies for environment variable management. - Refactored metrics handling in the bot to ensure proper initialization and collection.
This commit is contained in:
@@ -8,12 +8,17 @@ from aiogram import BaseMiddleware
|
||||
from aiogram.types import TelegramObject, Message, CallbackQuery
|
||||
from aiogram.enums import ChatType
|
||||
import time
|
||||
import logging
|
||||
from ..utils.metrics import metrics
|
||||
|
||||
|
||||
class MetricsMiddleware(BaseMiddleware):
|
||||
"""Middleware for automatic metrics collection in aiogram handlers."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
async def __call__(
|
||||
self,
|
||||
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
|
||||
@@ -22,11 +27,33 @@ class MetricsMiddleware(BaseMiddleware):
|
||||
) -> Any:
|
||||
"""Process event and collect metrics."""
|
||||
|
||||
# Record basic event metrics
|
||||
# Добавляем логирование для диагностики
|
||||
self.logger.info(f"📊 MetricsMiddleware called for event type: {type(event).__name__}")
|
||||
|
||||
# Extract command info before execution
|
||||
command_info = None
|
||||
if isinstance(event, Message):
|
||||
self.logger.info(f"📊 Processing Message event")
|
||||
await self._record_message_metrics(event)
|
||||
if event.text and event.text.startswith('/'):
|
||||
command_info = {
|
||||
'command': event.text.split()[0][1:], # Remove '/' and get command name
|
||||
'user_type': "user" if event.from_user else "unknown",
|
||||
'handler_type': "message_handler"
|
||||
}
|
||||
elif isinstance(event, CallbackQuery):
|
||||
self.logger.info(f"📊 Processing CallbackQuery event")
|
||||
await self._record_callback_metrics(event)
|
||||
if event.data:
|
||||
parts = event.data.split(':', 1)
|
||||
if parts:
|
||||
command_info = {
|
||||
'command': parts[0],
|
||||
'user_type': "user" if event.from_user else "unknown",
|
||||
'handler_type': "callback_handler"
|
||||
}
|
||||
else:
|
||||
self.logger.info(f"📊 Processing unknown event type: {type(event).__name__}")
|
||||
|
||||
# Execute handler with timing
|
||||
start_time = time.time()
|
||||
@@ -36,6 +63,7 @@ class MetricsMiddleware(BaseMiddleware):
|
||||
|
||||
# Record successful execution
|
||||
handler_name = self._get_handler_name(handler)
|
||||
self.logger.info(f"📊 Recording successful execution: {handler_name}")
|
||||
metrics.record_method_duration(
|
||||
handler_name,
|
||||
duration,
|
||||
@@ -43,6 +71,15 @@ class MetricsMiddleware(BaseMiddleware):
|
||||
"success"
|
||||
)
|
||||
|
||||
# Record command with success status if applicable
|
||||
if command_info:
|
||||
metrics.record_command(
|
||||
command_info['command'],
|
||||
command_info['handler_type'],
|
||||
command_info['user_type'],
|
||||
"success"
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
@@ -50,6 +87,7 @@ class MetricsMiddleware(BaseMiddleware):
|
||||
|
||||
# Record error and timing
|
||||
handler_name = self._get_handler_name(handler)
|
||||
self.logger.error(f"📊 Recording error execution: {handler_name}, error: {type(e).__name__}")
|
||||
metrics.record_method_duration(
|
||||
handler_name,
|
||||
duration,
|
||||
@@ -61,15 +99,39 @@ class MetricsMiddleware(BaseMiddleware):
|
||||
"handler",
|
||||
handler_name
|
||||
)
|
||||
|
||||
# Record command with error status if applicable
|
||||
if command_info:
|
||||
metrics.record_command(
|
||||
command_info['command'],
|
||||
command_info['handler_type'],
|
||||
command_info['user_type'],
|
||||
"error"
|
||||
)
|
||||
|
||||
raise
|
||||
|
||||
def _get_handler_name(self, handler: Callable) -> str:
|
||||
"""Extract handler name efficiently."""
|
||||
if hasattr(handler, '__name__'):
|
||||
# Проверяем различные способы получения имени хендлера
|
||||
if hasattr(handler, '__name__') and handler.__name__ != '<lambda>':
|
||||
return handler.__name__
|
||||
elif hasattr(handler, '__qualname__'):
|
||||
elif hasattr(handler, '__qualname__') and handler.__qualname__ != '<lambda>':
|
||||
return handler.__qualname__
|
||||
return "unknown"
|
||||
elif hasattr(handler, 'callback') and hasattr(handler.callback, '__name__'):
|
||||
return handler.callback.__name__
|
||||
elif hasattr(handler, 'view') and hasattr(handler.view, '__name__'):
|
||||
return handler.view.__name__
|
||||
else:
|
||||
# Пытаемся получить имя из строкового представления
|
||||
handler_str = str(handler)
|
||||
if 'function' in handler_str:
|
||||
# Извлекаем имя функции из строки
|
||||
import re
|
||||
match = re.search(r'function\s+(\w+)', handler_str)
|
||||
if match:
|
||||
return match.group(1)
|
||||
return "unknown"
|
||||
|
||||
async def _record_message_metrics(self, message: Message):
|
||||
"""Record message metrics efficiently."""
|
||||
@@ -101,23 +163,10 @@ class MetricsMiddleware(BaseMiddleware):
|
||||
|
||||
# Record message processing
|
||||
metrics.record_message(message_type, chat_type, "message_handler")
|
||||
|
||||
# Record command if applicable
|
||||
if message.text and message.text.startswith('/'):
|
||||
command = message.text.split()[0][1:] # Remove '/' and get command name
|
||||
user_type = "user" if message.from_user else "unknown"
|
||||
metrics.record_command(command, "message_handler", user_type)
|
||||
|
||||
async def _record_callback_metrics(self, callback: CallbackQuery):
|
||||
"""Record callback metrics efficiently."""
|
||||
metrics.record_message("callback_query", "callback", "callback_handler")
|
||||
|
||||
if callback.data:
|
||||
parts = callback.data.split(':', 1)
|
||||
if parts:
|
||||
command = parts[0]
|
||||
user_type = "user" if callback.from_user else "unknown"
|
||||
metrics.record_command(command, "callback_handler", user_type)
|
||||
|
||||
|
||||
class DatabaseMetricsMiddleware(BaseMiddleware):
|
||||
|
||||
Reference in New Issue
Block a user