Enhance monitoring configuration by adding status update interval and alert delays for CPU, RAM, and disk metrics. Update Makefile to include dependency checks for testing, and modify requirements to include requests library. Refactor message sender and metrics collector for improved logging and alert handling.
This commit is contained in:
@@ -18,6 +18,9 @@ class MessageSender:
|
||||
self.group_for_logs = os.getenv('GROUP_MONITORING_FOR_LOGS')
|
||||
self.important_logs = os.getenv('IMPORTANT_MONITORING_LOGS')
|
||||
|
||||
# Интервал отправки статуса в минутах (по умолчанию 2 минуты)
|
||||
self.status_update_interval_minutes = int(os.getenv('STATUS_UPDATE_INTERVAL_MINUTES', 2))
|
||||
|
||||
# Создаем экземпляр сборщика метрик
|
||||
self.metrics_collector = MetricsCollector()
|
||||
|
||||
@@ -30,6 +33,8 @@ class MessageSender:
|
||||
logger.warning("GROUP_MONITORING_FOR_LOGS не установлен в переменных окружения")
|
||||
if not self.important_logs:
|
||||
logger.warning("IMPORTANT_MONITORING_LOGS не установлен в переменных окружения")
|
||||
|
||||
logger.info(f"Интервал отправки статуса установлен: {self.status_update_interval_minutes} минут")
|
||||
|
||||
async def send_telegram_message(self, chat_id: str, message: str) -> bool:
|
||||
"""Отправка сообщения в Telegram через прямое обращение к API"""
|
||||
@@ -60,18 +65,29 @@ class MessageSender:
|
||||
return False
|
||||
|
||||
def should_send_status(self) -> bool:
|
||||
"""Проверка, нужно ли отправить статус (каждые 4 часа в 00 минут)"""
|
||||
"""Проверка, нужно ли отправить статус (каждые N минут)"""
|
||||
now = datetime.now()
|
||||
|
||||
# Проверяем, что сейчас 00 минут часа и час кратен 4 (0, 4, 8, 12, 16, 20)
|
||||
if now.minute == 0 and now.hour % 4 == 0:
|
||||
# Проверяем, не отправляли ли мы уже статус в этот час
|
||||
if (self.last_status_time is None or
|
||||
self.last_status_time.hour != now.hour or
|
||||
self.last_status_time.day != now.day):
|
||||
self.last_status_time = now
|
||||
return True
|
||||
# Логируем для диагностики
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if self.last_status_time is None:
|
||||
logger.info(f"should_send_status: last_status_time is None, отправляем статус")
|
||||
self.last_status_time = now
|
||||
return True
|
||||
|
||||
# Вычисляем разницу в минутах
|
||||
time_diff_minutes = (now - self.last_status_time).total_seconds() / 60
|
||||
logger.info(f"should_send_status: прошло {time_diff_minutes:.1f} минут с последней отправки, нужно {self.status_update_interval_minutes} минут")
|
||||
|
||||
# Проверяем, что прошло N минут с последней отправки
|
||||
if time_diff_minutes >= self.status_update_interval_minutes:
|
||||
logger.info(f"should_send_status: отправляем статус (прошло {time_diff_minutes:.1f} минут)")
|
||||
self.last_status_time = now
|
||||
return True
|
||||
|
||||
logger.info(f"should_send_status: статус не отправляем (прошло {time_diff_minutes:.1f} минут)")
|
||||
return False
|
||||
|
||||
def should_send_startup_status(self) -> bool:
|
||||
@@ -87,23 +103,73 @@ class MessageSender:
|
||||
else:
|
||||
return "🚨"
|
||||
|
||||
def _get_cpu_emoji(self, cpu_percent: float) -> str:
|
||||
"""Получение эмодзи для CPU"""
|
||||
if cpu_percent < 50:
|
||||
return "🟢"
|
||||
elif cpu_percent < 80:
|
||||
return "⚠️"
|
||||
else:
|
||||
return "🚨"
|
||||
|
||||
def _get_memory_emoji(self, memory_percent: float) -> str:
|
||||
"""Получение эмодзи для памяти (RAM/Swap)"""
|
||||
if memory_percent < 60:
|
||||
return "🟢"
|
||||
elif memory_percent < 85:
|
||||
return "⚠️"
|
||||
else:
|
||||
return "🚨"
|
||||
|
||||
def _get_load_average_emoji(self, load_avg: float, cpu_count: int) -> str:
|
||||
"""Получение эмодзи для Load Average"""
|
||||
# Load Average считается нормальным если < 1.0 на ядро
|
||||
# Критичным если > 2.0 на ядро
|
||||
load_per_core = load_avg / cpu_count
|
||||
if load_per_core < 1.0:
|
||||
return "🟢"
|
||||
elif load_per_core < 2.0:
|
||||
return "⚠️"
|
||||
else:
|
||||
return "🚨"
|
||||
|
||||
def _get_io_wait_emoji(self, io_wait_percent: float) -> str:
|
||||
"""Получение эмодзи для IO Wait"""
|
||||
# IO Wait считается нормальным если < 5%
|
||||
# Критичным если > 20%
|
||||
if io_wait_percent < 5:
|
||||
return "🟢"
|
||||
elif io_wait_percent < 20:
|
||||
return "⚠️"
|
||||
else:
|
||||
return "🚨"
|
||||
|
||||
def get_status_message(self, system_info: Dict) -> str:
|
||||
"""Формирование сообщения со статусом сервера"""
|
||||
try:
|
||||
voice_bot_status, voice_bot_uptime = self.metrics_collector.check_process_status('voice_bot')
|
||||
helper_bot_status, helper_bot_uptime = self.metrics_collector.check_process_status('helper_bot')
|
||||
|
||||
# Получаем эмодзи для дискового пространства
|
||||
# Получаем эмодзи для всех метрик
|
||||
cpu_emoji = self._get_cpu_emoji(system_info['cpu_percent'])
|
||||
ram_emoji = self._get_memory_emoji(system_info['ram_percent'])
|
||||
swap_emoji = self._get_memory_emoji(system_info['swap_percent'])
|
||||
la_emoji = self._get_load_average_emoji(system_info['load_avg_1m'], system_info['cpu_count'])
|
||||
io_wait_emoji = self._get_io_wait_emoji(system_info['io_wait_percent'])
|
||||
disk_emoji = self._get_disk_space_emoji(system_info['disk_percent'])
|
||||
|
||||
message = f"""🖥 **Статус Сервера** | <code>{system_info['current_time']}</code>
|
||||
# Определяем уровень мониторинга
|
||||
monitoring_level = system_info.get('monitoring_level', 'unknown')
|
||||
level_emoji = "🖥️" if monitoring_level == 'host' else "📦"
|
||||
level_text = "Хост" if monitoring_level == 'host' else "Контейнер"
|
||||
|
||||
message = f"""{level_emoji} **Статус {level_text}** | <code>{system_info['current_time']}</code>
|
||||
---------------------------------
|
||||
**📊 Общая нагрузка:**
|
||||
CPU: <b>{system_info['cpu_percent']}%</b> | LA: <b>{system_info['load_avg_1m']} / {system_info['cpu_count']}</b> | IO Wait: <b>{system_info['disk_percent']}%</b>
|
||||
CPU: <b>{system_info['cpu_percent']}%</b> {cpu_emoji} | LA: <b>{system_info['load_avg_1m']} / {system_info['cpu_count']}</b> {la_emoji} | IO Wait: <b>{system_info['io_wait_percent']}%</b> {io_wait_emoji}
|
||||
|
||||
**💾 Память:**
|
||||
RAM: <b>{system_info['ram_used']}/{system_info['ram_total']} GB</b> ({system_info['ram_percent']}%)
|
||||
Swap: <b>{system_info['swap_used']}/{system_info['swap_total']} GB</b> ({system_info['swap_percent']}%)
|
||||
RAM: <b>{system_info['ram_used']}/{system_info['ram_total']} GB</b> ({system_info['ram_percent']}%) {ram_emoji}
|
||||
Swap: <b>{system_info['swap_used']}/{system_info['swap_total']} GB</b> ({system_info['swap_percent']}%) {swap_emoji}
|
||||
|
||||
**🗂️ Дисковое пространство:**
|
||||
Диск (/): <b>{system_info['disk_used']}/{system_info['disk_total']} GB</b> ({system_info['disk_percent']}%) {disk_emoji}
|
||||
@@ -113,10 +179,10 @@ Read: <b>{system_info['disk_read_speed']}</b> | Write: <b>{system_info['disk_wri
|
||||
Диск загружен: <b>{system_info['disk_io_percent']}%</b>
|
||||
|
||||
**🤖 Процессы:**
|
||||
{voice_bot_status} voice-bot - {voice_bot_uptime}
|
||||
{helper_bot_status} helper-bot - {helper_bot_uptime}
|
||||
---------------------------------
|
||||
⏰ Uptime сервера: {system_info['system_uptime']}"""
|
||||
⏰ Uptime сервера: {system_info['system_uptime']}
|
||||
🔍 Уровень мониторинга: {level_text} ({monitoring_level})"""
|
||||
|
||||
return message
|
||||
|
||||
@@ -127,6 +193,17 @@ Read: <b>{system_info['disk_read_speed']}</b> | Write: <b>{system_info['disk_wri
|
||||
def get_alert_message(self, metric_name: str, current_value: float, details: str) -> str:
|
||||
"""Формирование сообщения об алерте"""
|
||||
try:
|
||||
# Получаем информацию о задержке для данного метрика
|
||||
delay_info = ""
|
||||
if hasattr(self.metrics_collector, 'alert_delays'):
|
||||
metric_type = metric_name.lower().replace('использование ', '').replace('заполнение диска (/)', 'disk')
|
||||
if 'cpu' in metric_type:
|
||||
delay_info = f"⏱️ Задержка срабатывания: {self.metrics_collector.alert_delays['cpu']} сек"
|
||||
elif 'память' in metric_type or 'ram' in metric_type:
|
||||
delay_info = f"⏱️ Задержка срабатывания: {self.metrics_collector.alert_delays['ram']} сек"
|
||||
elif 'диск' in metric_type or 'disk' in metric_type:
|
||||
delay_info = f"⏱️ Задержка срабатывания: {self.metrics_collector.alert_delays['disk']} сек"
|
||||
|
||||
message = f"""🚨 **ALERT: Высокая нагрузка на сервере!**
|
||||
---------------------------------
|
||||
**Показатель:** {metric_name}
|
||||
@@ -136,6 +213,8 @@ Read: <b>{system_info['disk_read_speed']}</b> | Write: <b>{system_info['disk_wri
|
||||
**Детали:**
|
||||
{details}
|
||||
|
||||
{delay_info}
|
||||
|
||||
**Сервер:** `{self.metrics_collector.os_type.upper()}`
|
||||
**Время:** `{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}`
|
||||
---------------------------------"""
|
||||
|
||||
Reference in New Issue
Block a user