Редактировать stats.py
This commit is contained in:
@@ -1,151 +1,87 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
Административные команды: !stats, !status, !clean.
|
Административные команды: !stats, !status, !clean.
|
||||||
- !stats – статистика работы бота (сообщения, файлы, AI-запросы, ошибки, uptime).
|
Используют RAGClient.
|
||||||
- !status – проверка состояния сервисов (GigaChat, PostgreSQL, Qdrant, диск).
|
|
||||||
- !clean – очистка временной директории.
|
|
||||||
|
|
||||||
Изменения для PostgreSQL:
|
|
||||||
- Замена `conn.ping()` на `conn.execute("SELECT 1")` в команде !status.
|
|
||||||
- Обновлены тексты сообщений (MariaDB → PostgreSQL).
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from core.commands.base import Command
|
from core.commands.base import Command
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class StatsCommand(Command):
|
class StatsCommand(Command):
|
||||||
"""Показывает статистику работы бота (только для администраторов)."""
|
|
||||||
|
|
||||||
name = "!stats"
|
name = "!stats"
|
||||||
aliases = ["/stats", "!статистика", "/статистика", "!стат", "/стат"]
|
aliases = ["/stats"]
|
||||||
permission = "admin"
|
permission = "admin"
|
||||||
|
|
||||||
async def execute(self, msg, args: str, user_jid: str, room_jid: str = None):
|
async def execute(self, msg, args: str, user_jid: str, room_jid: str = None):
|
||||||
"""
|
|
||||||
Выводит:
|
|
||||||
- uptime бота
|
|
||||||
- количество обработанных сообщений
|
|
||||||
- количество AI-запросов
|
|
||||||
- количество обработанных файлов
|
|
||||||
- количество ошибок
|
|
||||||
- количество документов в базе знаний (с учётом контекста)
|
|
||||||
"""
|
|
||||||
if not self.check_permission(user_jid):
|
if not self.check_permission(user_jid):
|
||||||
reply = msg.reply("⛔ Нет прав.")
|
reply = msg.reply("⛔ Нет прав.")
|
||||||
if reply:
|
if reply: reply.send()
|
||||||
reply.send() # исправлено
|
|
||||||
else:
|
|
||||||
logger.error("Не удалось отправить сообщение о недостатке прав (stats)")
|
|
||||||
return
|
return
|
||||||
|
try:
|
||||||
# Время работы бота
|
stats = await self.bot.rag_client.get_stats()
|
||||||
uptime = datetime.now() - self.bot.start_time
|
uptime = datetime.now() - self.bot.start_time
|
||||||
|
|
||||||
# Получение метрик из MetricsHandler
|
|
||||||
stats = self.bot.metrics_handler.get()
|
|
||||||
|
|
||||||
# Количество доступных документов в БЗ (личные/комнатные + глобальные)
|
|
||||||
sources = await self.bot.kb.get_available_sources(user_jid, room_jid)
|
|
||||||
|
|
||||||
response = (
|
response = (
|
||||||
f"📊 **Статистика бота {self.bot.config.name}**\n"
|
f"📊 Статистика бота {self.bot.config.name}\n"
|
||||||
f"⏱ Uptime: {str(uptime).split('.')[0]}\n"
|
f"⏱ Uptime: {str(uptime).split('.')[0]}\n"
|
||||||
f"💬 Сообщений: {stats.get('messages_total', 0)}\n"
|
f"📚 Документов в БЗ: {stats.get('documents', 0)}\n"
|
||||||
f"🤖 AI запросов: {stats.get('ai_requests', 0)}\n"
|
f"⏱ Время работы сервера: {stats.get('uptime', 0):.0f} сек"
|
||||||
f"📁 Файлов обработано: {stats.get('files_processed', 0)}\n"
|
|
||||||
f"❌ Ошибок: {stats.get('errors_total', 0)}\n"
|
|
||||||
f"📚 Документов в БЗ: {len(sources)}"
|
|
||||||
)
|
)
|
||||||
reply = msg.reply(response)
|
reply = msg.reply(response)
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception(f"Ошибка в !stats: {e}")
|
||||||
|
reply = msg.reply(f"❌ Ошибка получения статистики: {e}")
|
||||||
if reply:
|
if reply:
|
||||||
reply.send() # исправлено
|
reply.send()
|
||||||
else:
|
|
||||||
logger.error("Не удалось отправить статистику")
|
|
||||||
|
|
||||||
def get_help(self) -> str:
|
def get_help(self) -> str:
|
||||||
return "Показывает статистику работы бота (админ)."
|
return "Показывает статистику (админ)."
|
||||||
|
|
||||||
|
|
||||||
class StatusCommand(Command):
|
class StatusCommand(Command):
|
||||||
"""Проверяет состояние всех внешних сервисов (административная команда)."""
|
|
||||||
|
|
||||||
name = "!status"
|
name = "!status"
|
||||||
aliases = ["/status", "!статус", "/статус"]
|
aliases = ["/status"]
|
||||||
permission = "admin"
|
permission = "admin"
|
||||||
|
|
||||||
async def execute(self, msg, args: str, user_jid: str, room_jid: str = None):
|
async def execute(self, msg, args: str, user_jid: str, room_jid: str = None):
|
||||||
if not self.check_permission(user_jid):
|
if not self.check_permission(user_jid):
|
||||||
reply = msg.reply("⛔ Нет прав.")
|
reply = msg.reply("⛔ Нет прав.")
|
||||||
if reply:
|
if reply: reply.send()
|
||||||
reply.send() # исправлено
|
|
||||||
else:
|
|
||||||
logger.error("Не удалось отправить сообщение о недостатке прав (stats)")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# --- GigaChat ---
|
|
||||||
try:
|
try:
|
||||||
# Простой запрос для проверки доступности API
|
health = await self.bot.rag_client.health_check()
|
||||||
await self.bot.giga.chat([], "ping", system_prompt=None, file_id=None, temperature=0.1)
|
if health:
|
||||||
ai_status = "✅ GigaChat Online"
|
status = "✅ Все сервисы работают"
|
||||||
except Exception as e:
|
|
||||||
ai_status = f"❌ GigaChat Offline: {e}"
|
|
||||||
|
|
||||||
# --- PostgreSQL (asyncpg) ---
|
|
||||||
try:
|
|
||||||
async with self.bot.db.pool.acquire() as conn:
|
|
||||||
# В asyncpg нет метода ping(), используем SELECT 1
|
|
||||||
await conn.execute("SELECT 1")
|
|
||||||
db_status = "✅ PostgreSQL Online"
|
|
||||||
except Exception as e:
|
|
||||||
db_status = f"❌ PostgreSQL Error: {e}"
|
|
||||||
|
|
||||||
# --- Qdrant ---
|
|
||||||
try:
|
|
||||||
self.bot.qdrant.client.get_collection(self.bot.qdrant.collection_name)
|
|
||||||
qd_status = "✅ Qdrant Online"
|
|
||||||
except Exception as e:
|
|
||||||
qd_status = f"❌ Qdrant Error: {e}"
|
|
||||||
|
|
||||||
# --- Дисковое пространство (временная директория) ---
|
|
||||||
total, used, free = shutil.disk_usage(self.bot.config.temp_dir)
|
|
||||||
disk_info = f"💾 Диск: {used // (2**20)}MB / {total // (2**20)}MB"
|
|
||||||
|
|
||||||
full_status = f"🛰 **СТАТУС БОТА**\n{ai_status}\n{db_status}\n{qd_status}\n{disk_info}"
|
|
||||||
reply = msg.reply(full_status)
|
|
||||||
if reply:
|
|
||||||
reply.send() # исправлено
|
|
||||||
else:
|
else:
|
||||||
logger.error("Не удалось отправить статус")
|
status = "⚠️ Некоторые сервисы недоступны"
|
||||||
|
reply = msg.reply(f"🛰 Статус бота: {status}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception(f"Ошибка в !status: {e}")
|
||||||
|
reply = msg.reply(f"❌ Ошибка проверки статуса: {e}")
|
||||||
|
if reply:
|
||||||
|
reply.send()
|
||||||
|
|
||||||
def get_help(self) -> str:
|
def get_help(self) -> str:
|
||||||
return "Проверяет состояние сервисов (GigaChat, PostgreSQL, Qdrant, диск) – админ."
|
return "Проверяет состояние сервисов (админ)."
|
||||||
|
|
||||||
|
|
||||||
class CleanCommand(Command):
|
class CleanCommand(Command):
|
||||||
"""Очищает временную директорию бота (temp_dir)."""
|
|
||||||
|
|
||||||
name = "!clean"
|
name = "!clean"
|
||||||
aliases = ["/clean", "!очистка", "/очистка"]
|
aliases = ["/clean"]
|
||||||
permission = "admin"
|
permission = "admin"
|
||||||
|
|
||||||
async def execute(self, msg, args: str, user_jid: str, room_jid: str = None):
|
async def execute(self, msg, args: str, user_jid: str, room_jid: str = None):
|
||||||
if not self.check_permission(user_jid):
|
if not self.check_permission(user_jid):
|
||||||
reply = msg.reply("⛔ Нет прав.")
|
reply = msg.reply("⛔ Нет прав.")
|
||||||
if reply:
|
if reply: reply.send()
|
||||||
reply.send() # исправлено
|
|
||||||
else:
|
|
||||||
logger.error("Не удалось отправить сообщение о недостатке прав (stats)")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
count = 0
|
|
||||||
temp_dir = self.bot.config.temp_dir
|
temp_dir = self.bot.config.temp_dir
|
||||||
|
count = 0
|
||||||
for f in os.listdir(temp_dir):
|
for f in os.listdir(temp_dir):
|
||||||
try:
|
try:
|
||||||
p = os.path.join(temp_dir, f)
|
p = os.path.join(temp_dir, f)
|
||||||
@@ -154,13 +90,11 @@ class CleanCommand(Command):
|
|||||||
elif os.path.isdir(p):
|
elif os.path.isdir(p):
|
||||||
shutil.rmtree(p)
|
shutil.rmtree(p)
|
||||||
count += 1
|
count += 1
|
||||||
except Exception:
|
except:
|
||||||
pass
|
pass
|
||||||
reply = msg.reply(f"🧹 Удалено объектов из temp_dir: {count}")
|
reply = msg.reply(f"🧹 Удалено объектов из temp_dir: {count}")
|
||||||
if reply:
|
if reply:
|
||||||
reply.send() # исправлено
|
reply.send()
|
||||||
else:
|
|
||||||
logger.error("Не удалось отправить отчёт об очистке")
|
|
||||||
|
|
||||||
def get_help(self) -> str:
|
def get_help(self) -> str:
|
||||||
return "Очищает временную директорию бота (админ)."
|
return "Очищает временную директорию (админ)."
|
||||||
Reference in New Issue
Block a user