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