v1.0 - Version stable: multi-PC, détection UI-DETR-1, 3 modes exécution
- Frontend v4 accessible sur réseau local (192.168.1.40) - Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard) - Ollama GPU fonctionnel - Self-healing interactif - Dashboard confiance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
296
diagnostic_backend_complet.py
Normal file
296
diagnostic_backend_complet.py
Normal file
@@ -0,0 +1,296 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Diagnostic et réparation complète du backend VWB
|
||||
Auteur : Dom, Alice, Kiro - 8 janvier 2026
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import requests
|
||||
import time
|
||||
import json
|
||||
import psutil
|
||||
from pathlib import Path
|
||||
|
||||
class DiagnosticBackend:
|
||||
"""Classe pour diagnostiquer et réparer le backend VWB"""
|
||||
|
||||
def __init__(self):
|
||||
self.backend_port = 5002
|
||||
self.backend_url = f'http://localhost:{self.backend_port}'
|
||||
self.backend_path = 'visual_workflow_builder/backend'
|
||||
self.venv_path = './venv_v3'
|
||||
|
||||
def verifier_environnement(self):
|
||||
"""Vérifier l'environnement Python et les dépendances"""
|
||||
print("🔍 Vérification de l'environnement...")
|
||||
|
||||
# Vérifier Python
|
||||
try:
|
||||
python_version = sys.version_info
|
||||
print(f" ✅ Python {python_version.major}.{python_version.minor}.{python_version.micro}")
|
||||
except Exception as e:
|
||||
print(f" ❌ Problème Python: {e}")
|
||||
return False
|
||||
|
||||
# Vérifier l'environnement virtuel
|
||||
if os.path.exists(self.venv_path):
|
||||
print(f" ✅ Environnement virtuel trouvé: {self.venv_path}")
|
||||
else:
|
||||
print(f" ❌ Environnement virtuel manquant: {self.venv_path}")
|
||||
return False
|
||||
|
||||
# Vérifier les dépendances critiques
|
||||
dependances_critiques = ['flask', 'flask_cors', 'flask_socketio', 'requests']
|
||||
for dep in dependances_critiques:
|
||||
try:
|
||||
__import__(dep)
|
||||
print(f" ✅ Dépendance {dep} disponible")
|
||||
except ImportError:
|
||||
print(f" ❌ Dépendance {dep} manquante")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def nettoyer_processus_existants(self):
|
||||
"""Nettoyer les processus backend existants"""
|
||||
print("🧹 Nettoyage des processus existants...")
|
||||
|
||||
processus_tues = 0
|
||||
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
|
||||
try:
|
||||
cmdline = ' '.join(proc.info['cmdline'] or [])
|
||||
if 'visual_workflow_builder/backend/app.py' in cmdline:
|
||||
print(f" 🔪 Arrêt du processus PID {proc.info['pid']}")
|
||||
proc.terminate()
|
||||
processus_tues += 1
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
||||
continue
|
||||
|
||||
if processus_tues > 0:
|
||||
print(f" ✅ {processus_tues} processus arrêtés")
|
||||
time.sleep(2) # Attendre que les processus se terminent
|
||||
else:
|
||||
print(" ℹ️ Aucun processus backend en cours")
|
||||
|
||||
return True
|
||||
|
||||
def verifier_fichiers_backend(self):
|
||||
"""Vérifier l'intégrité des fichiers backend"""
|
||||
print("📁 Vérification des fichiers backend...")
|
||||
|
||||
fichiers_critiques = [
|
||||
'visual_workflow_builder/backend/app.py',
|
||||
'visual_workflow_builder/backend/api/__init__.py',
|
||||
'visual_workflow_builder/backend/api/workflows.py',
|
||||
'visual_workflow_builder/backend/api/screen_capture.py',
|
||||
]
|
||||
|
||||
for fichier in fichiers_critiques:
|
||||
if os.path.exists(fichier):
|
||||
taille = os.path.getsize(fichier)
|
||||
print(f" ✅ {fichier} ({taille} bytes)")
|
||||
else:
|
||||
print(f" ❌ {fichier} manquant")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def demarrer_backend(self):
|
||||
"""Démarrer le backend en mode diagnostic"""
|
||||
print("🚀 Démarrage du backend...")
|
||||
|
||||
# Commande pour démarrer le backend
|
||||
cmd = [
|
||||
f'{self.venv_path}/bin/python',
|
||||
'visual_workflow_builder/backend/app.py'
|
||||
]
|
||||
|
||||
try:
|
||||
# Démarrer en arrière-plan
|
||||
process = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
cwd='.',
|
||||
env=dict(os.environ, FLASK_ENV='development')
|
||||
)
|
||||
|
||||
print(f" 🔄 Processus démarré (PID: {process.pid})")
|
||||
|
||||
# Attendre que le serveur démarre
|
||||
for tentative in range(10):
|
||||
try:
|
||||
response = requests.get(f'{self.backend_url}/health', timeout=2)
|
||||
if response.status_code == 200:
|
||||
print(f" ✅ Backend démarré avec succès sur le port {self.backend_port}")
|
||||
return process
|
||||
except requests.exceptions.ConnectionError:
|
||||
pass
|
||||
|
||||
print(f" ⏳ Tentative {tentative + 1}/10...")
|
||||
time.sleep(2)
|
||||
|
||||
# Si on arrive ici, le démarrage a échoué
|
||||
stdout, stderr = process.communicate(timeout=5)
|
||||
print(f" ❌ Échec du démarrage")
|
||||
print(f" 📝 STDOUT: {stdout.decode()}")
|
||||
print(f" 📝 STDERR: {stderr.decode()}")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Erreur lors du démarrage: {e}")
|
||||
return None
|
||||
|
||||
def tester_endpoints(self):
|
||||
"""Tester tous les endpoints critiques"""
|
||||
print("🧪 Test des endpoints critiques...")
|
||||
|
||||
endpoints = [
|
||||
('/health', 'GET', None),
|
||||
('/api/workflows/', 'GET', None),
|
||||
('/api/screen-capture/', 'POST', {}),
|
||||
]
|
||||
|
||||
resultats = {}
|
||||
for endpoint, methode, data in endpoints:
|
||||
try:
|
||||
url = f'{self.backend_url}{endpoint}'
|
||||
if methode == 'GET':
|
||||
response = requests.get(url, timeout=10)
|
||||
elif methode == 'POST':
|
||||
response = requests.post(url, json=data, timeout=10)
|
||||
|
||||
resultats[endpoint] = {
|
||||
'status': response.status_code,
|
||||
'success': response.status_code < 400
|
||||
}
|
||||
|
||||
status_icon = "✅" if response.status_code < 400 else "❌"
|
||||
print(f" {status_icon} {methode} {endpoint}: {response.status_code}")
|
||||
|
||||
except Exception as e:
|
||||
resultats[endpoint] = {
|
||||
'status': 'ERREUR',
|
||||
'success': False,
|
||||
'error': str(e)
|
||||
}
|
||||
print(f" ❌ {methode} {endpoint}: ERREUR - {e}")
|
||||
|
||||
return resultats
|
||||
|
||||
def generer_rapport(self, resultats_tests):
|
||||
"""Générer un rapport de diagnostic"""
|
||||
print("\n" + "=" * 60)
|
||||
print("📊 RAPPORT DE DIAGNOSTIC BACKEND")
|
||||
print("=" * 60)
|
||||
|
||||
total_tests = len(resultats_tests)
|
||||
tests_reussis = sum(1 for r in resultats_tests.values() if r['success'])
|
||||
taux_reussite = (tests_reussis / total_tests) * 100 if total_tests > 0 else 0
|
||||
|
||||
print(f"📈 Taux de réussite: {tests_reussis}/{total_tests} ({taux_reussite:.1f}%)")
|
||||
|
||||
if taux_reussite == 100:
|
||||
print("🎉 Backend entièrement fonctionnel !")
|
||||
statut = "EXCELLENT"
|
||||
elif taux_reussite >= 70:
|
||||
print("⚠️ Backend partiellement fonctionnel")
|
||||
statut = "ACCEPTABLE"
|
||||
else:
|
||||
print("🚨 Backend défaillant")
|
||||
statut = "CRITIQUE"
|
||||
|
||||
# Sauvegarder le rapport
|
||||
rapport = {
|
||||
'timestamp': time.time(),
|
||||
'statut': statut,
|
||||
'taux_reussite': taux_reussite,
|
||||
'tests': resultats_tests,
|
||||
'recommandations': self.generer_recommandations(resultats_tests)
|
||||
}
|
||||
|
||||
with open('diagnostic_backend_rapport.json', 'w', encoding='utf-8') as f:
|
||||
json.dump(rapport, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"📄 Rapport sauvegardé: diagnostic_backend_rapport.json")
|
||||
return statut
|
||||
|
||||
def generer_recommandations(self, resultats_tests):
|
||||
"""Générer des recommandations basées sur les résultats"""
|
||||
recommandations = []
|
||||
|
||||
for endpoint, resultat in resultats_tests.items():
|
||||
if not resultat['success']:
|
||||
if endpoint == '/health':
|
||||
recommandations.append("Vérifier la configuration Flask de base")
|
||||
elif endpoint == '/api/workflows/':
|
||||
recommandations.append("Vérifier la base de données et les modèles")
|
||||
elif endpoint == '/api/screen-capture/':
|
||||
recommandations.append("Vérifier les dépendances de capture d'écran")
|
||||
|
||||
if not recommandations:
|
||||
recommandations.append("Backend fonctionnel - aucune action requise")
|
||||
|
||||
return recommandations
|
||||
|
||||
def executer_diagnostic_complet(self):
|
||||
"""Exécuter le diagnostic complet"""
|
||||
print("🏥 DIAGNOSTIC COMPLET DU BACKEND VWB")
|
||||
print("=" * 50)
|
||||
|
||||
# Étape 1: Vérifier l'environnement
|
||||
if not self.verifier_environnement():
|
||||
print("❌ Environnement défaillant - arrêt du diagnostic")
|
||||
return False
|
||||
|
||||
# Étape 2: Nettoyer les processus existants
|
||||
self.nettoyer_processus_existants()
|
||||
|
||||
# Étape 3: Vérifier les fichiers
|
||||
if not self.verifier_fichiers_backend():
|
||||
print("❌ Fichiers backend manquants - arrêt du diagnostic")
|
||||
return False
|
||||
|
||||
# Étape 4: Démarrer le backend
|
||||
process = self.demarrer_backend()
|
||||
if not process:
|
||||
print("❌ Impossible de démarrer le backend")
|
||||
return False
|
||||
|
||||
try:
|
||||
# Étape 5: Tester les endpoints
|
||||
resultats_tests = self.tester_endpoints()
|
||||
|
||||
# Étape 6: Générer le rapport
|
||||
statut = self.generer_rapport(resultats_tests)
|
||||
|
||||
return statut in ['EXCELLENT', 'ACCEPTABLE']
|
||||
|
||||
finally:
|
||||
# Nettoyer le processus de test
|
||||
if process and process.poll() is None:
|
||||
print("🧹 Nettoyage du processus de test...")
|
||||
process.terminate()
|
||||
|
||||
def main():
|
||||
"""Fonction principale"""
|
||||
diagnostic = DiagnosticBackend()
|
||||
|
||||
try:
|
||||
succes = diagnostic.executer_diagnostic_complet()
|
||||
exit_code = 0 if succes else 1
|
||||
|
||||
print(f"\n🏁 Diagnostic terminé (code de sortie: {exit_code})")
|
||||
return exit_code
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n⚠️ Diagnostic interrompu par l'utilisateur")
|
||||
return 2
|
||||
except Exception as e:
|
||||
print(f"\n❌ Erreur critique lors du diagnostic: {e}")
|
||||
return 3
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user