Add new file
This commit is contained in:
166
core/commands/stats.py
Normal file
166
core/commands/stats.py
Normal file
@@ -0,0 +1,166 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Административные команды: !stats, !status, !clean.
|
||||
- !stats – статистика работы бота (сообщения, файлы, AI-запросы, ошибки, uptime).
|
||||
- !status – проверка состояния сервисов (GigaChat, PostgreSQL, Qdrant, диск).
|
||||
- !clean – очистка временной директории.
|
||||
|
||||
Изменения для PostgreSQL:
|
||||
- Замена `conn.ping()` на `conn.execute("SELECT 1")` в команде !status.
|
||||
- Обновлены тексты сообщений (MariaDB → PostgreSQL).
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from core.commands.base import Command
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StatsCommand(Command):
|
||||
"""Показывает статистику работы бота (только для администраторов)."""
|
||||
|
||||
name = "!stats"
|
||||
aliases = ["/stats", "!статистика", "/статистика", "!стат", "/стат"]
|
||||
permission = "admin"
|
||||
|
||||
async def execute(self, msg, args: str, user_jid: str, room_jid: str = None):
|
||||
"""
|
||||
Выводит:
|
||||
- uptime бота
|
||||
- количество обработанных сообщений
|
||||
- количество AI-запросов
|
||||
- количество обработанных файлов
|
||||
- количество ошибок
|
||||
- количество документов в базе знаний (с учётом контекста)
|
||||
"""
|
||||
if not self.check_permission(user_jid):
|
||||
reply = msg.reply("⛔ Нет прав.")
|
||||
if reply:
|
||||
reply.send() # исправлено
|
||||
else:
|
||||
logger.error("Не удалось отправить сообщение о недостатке прав (stats)")
|
||||
return
|
||||
|
||||
# Время работы бота
|
||||
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 = (
|
||||
f"📊 **Статистика бота {self.bot.config.name}**\n"
|
||||
f"⏱ Uptime: {str(uptime).split('.')[0]}\n"
|
||||
f"💬 Сообщений: {stats.get('messages_total', 0)}\n"
|
||||
f"🤖 AI запросов: {stats.get('ai_requests', 0)}\n"
|
||||
f"📁 Файлов обработано: {stats.get('files_processed', 0)}\n"
|
||||
f"❌ Ошибок: {stats.get('errors_total', 0)}\n"
|
||||
f"📚 Документов в БЗ: {len(sources)}"
|
||||
)
|
||||
reply = msg.reply(response)
|
||||
if reply:
|
||||
reply.send() # исправлено
|
||||
else:
|
||||
logger.error("Не удалось отправить статистику")
|
||||
|
||||
def get_help(self) -> str:
|
||||
return "Показывает статистику работы бота (админ)."
|
||||
|
||||
|
||||
class StatusCommand(Command):
|
||||
"""Проверяет состояние всех внешних сервисов (административная команда)."""
|
||||
|
||||
name = "!status"
|
||||
aliases = ["/status", "!статус", "/статус"]
|
||||
permission = "admin"
|
||||
|
||||
async def execute(self, msg, args: str, user_jid: str, room_jid: str = None):
|
||||
if not self.check_permission(user_jid):
|
||||
reply = msg.reply("⛔ Нет прав.")
|
||||
if reply:
|
||||
reply.send() # исправлено
|
||||
else:
|
||||
logger.error("Не удалось отправить сообщение о недостатке прав (stats)")
|
||||
return
|
||||
|
||||
# --- GigaChat ---
|
||||
try:
|
||||
# Простой запрос для проверки доступности API
|
||||
await self.bot.giga.chat([], "ping", system_prompt=None, file_id=None, temperature=0.1)
|
||||
ai_status = "✅ GigaChat Online"
|
||||
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:
|
||||
logger.error("Не удалось отправить статус")
|
||||
|
||||
def get_help(self) -> str:
|
||||
return "Проверяет состояние сервисов (GigaChat, PostgreSQL, Qdrant, диск) – админ."
|
||||
|
||||
|
||||
class CleanCommand(Command):
|
||||
"""Очищает временную директорию бота (temp_dir)."""
|
||||
|
||||
name = "!clean"
|
||||
aliases = ["/clean", "!очистка", "/очистка"]
|
||||
permission = "admin"
|
||||
|
||||
async def execute(self, msg, args: str, user_jid: str, room_jid: str = None):
|
||||
if not self.check_permission(user_jid):
|
||||
reply = msg.reply("⛔ Нет прав.")
|
||||
if reply:
|
||||
reply.send() # исправлено
|
||||
else:
|
||||
logger.error("Не удалось отправить сообщение о недостатке прав (stats)")
|
||||
return
|
||||
|
||||
count = 0
|
||||
temp_dir = self.bot.config.temp_dir
|
||||
for f in os.listdir(temp_dir):
|
||||
try:
|
||||
p = os.path.join(temp_dir, f)
|
||||
if os.path.isfile(p):
|
||||
os.unlink(p)
|
||||
elif os.path.isdir(p):
|
||||
shutil.rmtree(p)
|
||||
count += 1
|
||||
except Exception:
|
||||
pass
|
||||
reply = msg.reply(f"🧹 Удалено объектов из temp_dir: {count}")
|
||||
if reply:
|
||||
reply.send() # исправлено
|
||||
else:
|
||||
logger.error("Не удалось отправить отчёт об очистке")
|
||||
|
||||
def get_help(self) -> str:
|
||||
return "Очищает временную директорию бота (админ)."
|
||||
Reference in New Issue
Block a user