Идея Реализация визуальной платформы(сайта), проверяющей работоспособность сервисов (скажем, для ТСа на мероприятии). Фотокарточка интерфейса Логика реализованной программы Сервер: Запрос сервера к апи сервисов Автоапдейт раз в 5 минут Клиент: Запрос статуса сервисов Отображение статусов Обновление страницы раз в 5 мин Установка и запуск Сервер: Python 3 requirements.txt Flask==2.0.2 requests==2.26.0 Code Flask==2.0.2 requests==2.26.0 Дерево: templates: admin.html app.py app.py from flask import Flask, render_template import requests import threading import time from datetime import datetime app = Flask(__name__) # Список сервисов, разделённых по категориям services = { 'ТГ Боты': { 'Бот ТГ_1': 'http://adres_servera:port/status', }, 'Сайты': { 'Сайт 1': 'http://adres_servera:port/status', 'Сайт 2': 'http://adres_servera:port/status', }, } # Переменные для хранения статусов и времени последнего обновления service_statuses = {} last_updated = datetime.now() def check_service_status(url): try: response = requests.get(url, timeout=0.1) if response.status_code == 200: return response.json().get('status', 'Unknown') else: return 'Service down' except requests.exceptions.RequestException: return 'Not online' def update_service_statuses(): global last_updated while True: for category, services_dict in services.items(): service_statuses[category] = {name: check_service_status(url) for name, url in services_dict.items()} last_updated = datetime.now() time.sleep(300) # Проверка каждые 5 минут @app.route('/admin') def admin(): # Подсчет времени до следующего обновления now = datetime.now() time_since_update = now - last_updated remaining_time = 300 - time_since_update.total_seconds() minutes, seconds = divmod(remaining_time, 60) return render_template('admin.html', service_statuses=service_statuses, minutes=int(minutes), seconds=int(seconds)) if __name__ == '__main__': # Запускаем поток для обновления статусов сервисов threading.Thread(target=update_service_statuses, daemon=True).start() app.run(host='0.0.0.0', port=8080) Python from flask import Flask, render_template import requests import threading import time from datetime import datetime app = Flask(__name__) # Список сервисов, разделённых по категориям services = { 'ТГ Боты': { 'Бот ТГ_1': 'http://adres_servera:port/status', }, 'Сайты': { 'Сайт 1': 'http://adres_servera:port/status', 'Сайт 2': 'http://adres_servera:port/status', }, } # Переменные для хранения статусов и времени последнего обновления service_statuses = {} last_updated = datetime.now() def check_service_status(url): try: response = requests.get(url, timeout=0.1) if response.status_code == 200: return response.json().get('status', 'Unknown') else: return 'Service down' except requests.exceptions.RequestException: return 'Not online' def update_service_statuses(): global last_updated while True: for category, services_dict in services.items(): service_statuses[category] = {name: check_service_status(url) for name, url in services_dict.items()} last_updated = datetime.now() time.sleep(300) # Проверка каждые 5 минут @app.route('/admin') def admin(): # Подсчет времени до следующего обновления now = datetime.now() time_since_update = now - last_updated remaining_time = 300 - time_since_update.total_seconds() minutes, seconds = divmod(remaining_time, 60) return render_template('admin.html', service_statuses=service_statuses, minutes=int(minutes), seconds=int(seconds)) if __name__ == '__main__': # Запускаем поток для обновления статусов сервисов threading.Thread(target=update_service_statuses, daemon=True).start() app.run(host='0.0.0.0', port=8080) Сервисы и категории указываются по подобию примеру(10-18 стр.) admin.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Admin Panel - Service Status</title> <style> body { font-family: Arial, sans-serif; } table { width: 50%; margin: 20px auto; border-collapse: collapse; } th, td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; } th { background-color: #f2f2f2; } .status-ok { color: green; } .status-error { color: red; } .status-not-online { color: darkorange; } h2 { text-align: center; color: #333; } #timer { text-align: center; font-size: 1.2em; margin-top: 20px; } </style> </head> <body> <h1 style="text-align: center;">Service Status Dashboard</h1> {% for category, statuses in service_statuses.items() %} <h2>{{ category }}</h2> <table> <tr> <th>Service Name</th> <th>Status</th> </tr> {% for service_name, status in statuses.items() %} <tr> <td>{{ service_name }}</td> <td class="{% if status == 'running' %}status-ok{% else %}{% if status == 'Not online' %}status-not-online{% else %}status-error{% endif %}{% endif %}"> {{ status }} </td> </tr> {% endfor %} </table> {% endfor %} <div id="timer"></div> <script> // Получаем оставшееся время до следующего обновления let totalTime = {{ minutes }} * 60 + {{ seconds }}; let endTime = Date.now() + totalTime * 1000; function updateTimer() { let now = Date.now(); let remainingTime = Math.max(0, Math.floor((endTime - now) / 1000)); let minutes = Math.floor(remainingTime / 60); let seconds = remainingTime % 60; // Обновляем отображение таймера document.getElementById("timer").innerHTML = "Next update in: " + minutes + " min " + seconds + " sec"; if (remainingTime <= 0) { // Перезагружаем страницу, когда таймер завершится location.reload(); } else { // Запускаем обновление снова через 1 секунду setTimeout(updateTimer, 1000); } } // Запускаем таймер updateTimer(); </script> </body> </html> HTML <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Admin Panel - Service Status</title> <style> body { font-family: Arial, sans-serif; } table { width: 50%; margin: 20px auto; border-collapse: collapse; } th, td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; } th { background-color: #f2f2f2; } .status-ok { color: green; } .status-error { color: red; } .status-not-online { color: darkorange; } h2 { text-align: center; color: #333; } #timer { text-align: center; font-size: 1.2em; margin-top: 20px; } </style> </head> <body> <h1 style="text-align: center;">Service Status Dashboard</h1> {% for category, statuses in service_statuses.items() %} <h2>{{ category }}</h2> <table> <tr> <th>Service Name</th> <th>Status</th> </tr> {% for service_name, status in statuses.items() %} <tr> <td>{{ service_name }}</td> <td class="{% if status == 'running' %}status-ok{% else %}{% if status == 'Not online' %}status-not-online{% else %}status-error{% endif %}{% endif %}"> {{ status }} </td> </tr> {% endfor %} </table> {% endfor %} <div id="timer"></div> <script> // Получаем оставшееся время до следующего обновления let totalTime = {{ minutes }} * 60 + {{ seconds }}; let endTime = Date.now() + totalTime * 1000; function updateTimer() { let now = Date.now(); let remainingTime = Math.max(0, Math.floor((endTime - now) / 1000)); let minutes = Math.floor(remainingTime / 60); let seconds = remainingTime % 60; // Обновляем отображение таймера document.getElementById("timer").innerHTML = "Next update in: " + minutes + " min " + seconds + " sec"; if (remainingTime <= 0) { // Перезагружаем страницу, когда таймер завершится location.reload(); } else { // Запускаем обновление снова через 1 секунду setTimeout(updateTimer, 1000); } } // Запускаем таймер updateTimer(); </script> </body> </html> После запуска страница доступна по адресу: http://127.0.0.1:8080/admin Апи, необходимое к добавлению в дочерние проекты: Импорт зависимостей from flask import Flask, jsonify import threading Python from flask import Flask, jsonify import threading Функция, ответственная за страницу статуса # Flask API для проверки статуса app = Flask(__name__) @app.route('/status', methods=['GET']) def status(): try: # Проверка статуса твоего приложения return jsonify({"status": "running"}), 200 except Exception as e: return jsonify({"status": "error", "message": str(e)}), 500 # Функция для запуска Flask в отдельном потоке def run_flask(): app.run(host='0.0.0.0', port={ВАШ_ПОРТ}) Python # Flask API для проверки статуса app = Flask(__name__) @app.route('/status', methods=['GET']) def status(): try: # Проверка статуса твоего приложения return jsonify({"status": "running"}), 200 except Exception as e: return jsonify({"status": "error", "message": str(e)}), 500 # Функция для запуска Flask в отдельном потоке def run_flask(): app.run(host='0.0.0.0', port={ВАШ_ПОРТ}) {ВАШ_ПОРТ} нужно заменить на ваш номер порта) Запуск страницы в многопоточном режиме # Запуск Flask API в отдельном потоке flask_thread = threading.Thread(target=run_flask) flask_thread.start() Python # Запуск Flask API в отдельном потоке flask_thread = threading.Thread(target=run_flask) flask_thread.start() Будущее проекта Из ближайших планов: Внедрение API, не требующего отклика дочерних проектов Реализация автоматических оповещений в мессенджеры Доработка визуала сайта Создание ***** падения проетов и статистик
derkown, интересно было бы видеть реализацию с тг ботом на aiogram. чтоб типа мидлваря было как у i18n
а чем графана + прометей + экспортер не устроили? Там можно рисовать красивые дашборды с метриками по каждому проекту.