Files
myfirstprogram/utils/analytics.py
T
2025-10-04 16:59:38 +03:00

264 lines
10 KiB
Python

from collections import Counter
import re
from datetime import datetime
import tempfile
import json
def analyze_bot_logs(log_file_path="bot.log"):
"""
Анализирует логи бота и создает детальную статистику
"""
try:
with open(log_file_path, 'r', encoding='utf-8') as log:
lines = log.readlines()
except FileNotFoundError:
return {"error": "Лог файл не найден"}
except Exception as e:
return {"error": f"Ошибка чтения файла: {str(e)}"}
if not lines:
return {"error": "Лог файл пуст"}
# Основные счетчики
stats = {
'total_lines': len(lines),
'time_period': {},
'log_levels': Counter(),
'activities': Counter(),
'errors': Counter(),
'warnings': Counter(),
'user_commands': Counter(),
'groups': Counter(),
'restarts': 0,
'schedule_checks': 0,
'schedule_changes': 0,
'schedule_failures': 0,
'network_errors': 0,
'browser_errors': 0,
'telegram_errors': Counter(),
'performance': {
'avg_handling_time': 0,
'fastest_handling': float('inf'),
'slowest_handling': 0,
'handling_count': 0
}
}
# Временные метрики
start_time = None
end_time = None
handling_times = []
# Регулярные выражения для парсинга
timestamp_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})'
log_level_pattern = r'\[(INFO|WARNING|ERROR)\]'
handling_time_pattern = r'Duration (\d+) ms'
command_pattern = r'Команда /rasp от ([\d-]+), группа=([^,]+), дата=(\d+)'
schedule_pattern = r'Проверяем расписание для ([^ ]+) на (\d{2}\.\d{2}\.\d{4})'
for line in lines:
# Извлекаем временную метку
timestamp_match = re.search(timestamp_pattern, line)
if timestamp_match:
timestamp = timestamp_match.group(1)
if not start_time:
start_time = timestamp
end_time = timestamp
# Уровень логирования
level_match = re.search(log_level_pattern, line)
if level_match:
level = level_match.group(1)
stats['log_levels'][level] += 1
# Время обработки сообщений
time_match = re.search(handling_time_pattern, line)
if time_match and 'is handled' in line:
handling_time = int(time_match.group(1))
handling_times.append(handling_time)
stats['performance']['handling_count'] += 1
stats['performance']['slowest_handling'] = max(
stats['performance']['slowest_handling'], handling_time
)
stats['performance']['fastest_handling'] = min(
stats['performance']['fastest_handling'], handling_time
)
# Команды пользователей
cmd_match = re.search(command_pattern, line)
if cmd_match:
user_id, group, date_offset = cmd_match.groups()
stats['user_commands'][group] += 1
stats['groups'][group] += 1
# Проверки расписания
if 'Проверяем расписание' in line:
stats['schedule_checks'] += 1
sched_match = re.search(schedule_pattern, line)
if sched_match:
group, date = sched_match.groups()
stats['groups'][group] += 1
# Изменения расписания
if 'Изменения найдены' in line:
stats['schedule_changes'] += 1
# Ошибки расписания
if 'Не удалось получить расписание' in line:
stats['schedule_failures'] += 1
# Перезапуски бота
if 'Бот запускается' in line:
stats['restarts'] += 1
# Сетевые ошибки
if 'Failed to fetch updates' in line:
stats['network_errors'] += 1
# Ошибки браузера
if 'TargetClosedError' in line or 'BrowserContext.close' in line:
stats['browser_errors'] += 1
# Ошибки Telegram API
if 'Telegram server says' in line:
error_msg = line.split('Telegram server says - ')[-1].split(':')[0]
stats['telegram_errors'][error_msg] += 1
# Сбор ошибок и предупреждений
if '[ERROR]' in line:
error_msg = line.split('[ERROR]')[-1].strip()
stats['errors'][error_msg[:100]] += 1
if '[WARNING]' in line:
warning_msg = line.split('[WARNING]')[-1].strip()
stats['warnings'][warning_msg[:100]] += 1
# Расчет средней скорости обработки
if handling_times:
stats['performance']['avg_handling_time'] = sum(handling_times) / len(handling_times)
# Период работы
if start_time and end_time:
stats['time_period'] = {
'start': start_time,
'end': end_time,
'duration_hours': calculate_duration_hours(start_time, end_time)
}
# Дополнительные метрики
stats['success_rate'] = calculate_success_rate(stats)
stats['uptime_percentage'] = calculate_uptime_percentage(stats)
stats['schedule_success_rate'] = calculate_schedule_success_rate(stats)
return stats
def calculate_duration_hours(start_str, end_str):
"""Вычисляет продолжительность в часах"""
try:
fmt = '%Y-%m-%d %H:%M:%S'
start = datetime.strptime(start_str, fmt)
end = datetime.strptime(end_str, fmt)
return round((end - start).total_seconds() / 3600, 2)
except:
return 0
def calculate_success_rate(stats):
"""Рассчитывает процент успешных операций"""
total_operations = stats['performance']['handling_count'] + sum(stats['errors'].values())
if total_operations == 0:
return 0
success_rate = (stats['performance']['handling_count'] / total_operations) * 100
return round(success_rate, 2)
def calculate_uptime_percentage(stats):
"""Рассчитывает процент времени работы"""
if stats['time_period'].get('duration_hours', 0) == 0:
return 0
# Предполагаем, что каждый перезапуск занимает ~10 секунд
restart_downtime = stats['restarts'] * 10 / 3600
total_hours = stats['time_period']['duration_hours']
uptime_hours = total_hours - restart_downtime
uptime_percentage = (uptime_hours / total_hours) * 100
return round(uptime_percentage, 2)
def calculate_schedule_success_rate(stats):
"""Рассчитывает процент успешных проверок расписания"""
total_checks = stats['schedule_checks']
if total_checks == 0:
return 0
successful_checks = total_checks - stats['schedule_failures']
success_rate = (successful_checks / total_checks) * 100
return round(success_rate, 2)
def create_statistics_text(stats):
"""Создает текстовый отчет статистики"""
if 'error' in stats:
return f"❌ Ошибка анализа логов: {stats['error']}"
text = "📊 СТАТИСТИКА РАБОТЫ БОТА\n"
text += "=" * 40 + "\n\n"
# Основная информация
text += "📈 ОБЩАЯ ИНФОРМАЦИЯ:\n"
text += f"• Период: {stats['time_period'].get('start', 'N/A')} - {stats['time_period'].get('end', 'N/A')}\n"
text += f"• Длительность: {stats['time_period'].get('duration_hours', 0)} ч\n"
text += f"• Строк в логе: {stats['total_lines']:,}\n\n"
# Производительность
text += "⚡ ПРОИЗВОДИТЕЛЬНОСТЬ:\n"
text += f"• Среднее время: {stats['performance']['avg_handling_time']:.0f} мс\n"
text += f"• Сообщений обработано: {stats['performance']['handling_count']}\n"
text += f"• Успешных операций: {stats['success_rate']}%\n\n"
# Статус работы
text += "🔄 СТАТУС РАБОТЫ:\n"
text += f"• Перезапусков: {stats['restarts']}\n"
text += f"• Uptime: {stats['uptime_percentage']}%\n\n"
# Расписание
text += "📅 РАСПИСАНИЕ:\n"
text += f"• Проверок: {stats['schedule_checks']}\n"
text += f"• Изменений: {stats['schedule_changes']}\n"
text += f"• Ошибок: {stats['schedule_failures']}\n"
text += f"• Успешных проверок: {stats['schedule_success_rate']}%\n\n"
# Ошибки
text += "🚨 ОШИБКИ:\n"
text += f"• Всего ошибок: {sum(stats['errors'].values())}\n"
text += f"• Предупреждений: {sum(stats['warnings'].values())}\n"
text += f"• Сетевых: {stats['network_errors']}\n"
text += f"• Браузера: {stats['browser_errors']}\n\n"
# Пользователи
text += "👥 АКТИВНОСТЬ:\n"
text += f"• Команд: {sum(stats['user_commands'].values())}\n"
text += f"• Групп: {len(stats['groups'])}\n"
# Топ групп
if stats['groups']:
text += "• Топ групп:\n"
for group, count in stats['groups'].most_common(3):
text += f" - {group}: {count}\n"
return text
def create_statistics_file(stats):
"""Создает временный файл с полной статистикой"""
if 'error' in stats:
return None
# Создаем временный файл
with tempfile.NamedTemporaryFile(mode='w', encoding='utf-8',
suffix='.json', delete=False) as f:
json.dump(stats, f, ensure_ascii=False, indent=2, default=str)
temp_filename = f.name
return temp_filename