Files
rpa_vision_v3/diagnostic_backend_vwb_performance.py
Dom a27b74cf22 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>
2026-01-29 11:23:51 +01:00

547 lines
16 KiB
Python

#!/usr/bin/env python3
"""
Diagnostic de Performance du Backend Visual Workflow Builder
Auteur : Dom, Alice, Kiro - 08 janvier 2026
Ce script diagnostique les problèmes de performance et d'erreurs
au démarrage du backend Visual Workflow Builder.
"""
import os
import sys
import time
import traceback
import importlib.util
from pathlib import Path
from typing import List, Dict, Any, Optional
def print_section(title: str):
"""Affiche une section avec formatage."""
print(f"\n{'='*60}")
print(f" {title}")
print(f"{'='*60}")
def print_subsection(title: str):
"""Affiche une sous-section."""
print(f"\n{'-'*40}")
print(f" {title}")
print(f"{'-'*40}")
def check_python_version():
"""Vérifie la version de Python."""
print_subsection("Version Python")
version = sys.version_info
print(f"Version Python: {version.major}.{version.minor}.{version.micro}")
if version.major < 3 or (version.major == 3 and version.minor < 8):
print("❌ ERREUR: Python 3.8+ requis")
return False
else:
print("✅ Version Python compatible")
return True
def check_backend_structure():
"""Vérifie la structure du backend."""
print_subsection("Structure du Backend")
backend_path = Path("visual_workflow_builder/backend")
if not backend_path.exists():
print("❌ ERREUR: Répertoire backend introuvable")
return False
required_files = [
"app.py",
"models.py",
"requirements.txt",
".env",
"api/workflows.py"
]
missing_files = []
for file in required_files:
file_path = backend_path / file
if file_path.exists():
print(f"{file}")
else:
print(f"{file} - MANQUANT")
missing_files.append(file)
return len(missing_files) == 0
def check_dependencies():
"""Vérifie les dépendances Python."""
print_subsection("Dépendances Python")
# Lire requirements.txt
req_path = Path("visual_workflow_builder/backend/requirements.txt")
if not req_path.exists():
print("❌ requirements.txt introuvable")
return False
with open(req_path, 'r') as f:
requirements = f.read().splitlines()
# Filtrer les commentaires et lignes vides
packages = []
for line in requirements:
line = line.strip()
if line and not line.startswith('#'):
# Extraire le nom du package (avant ==, >=, etc.)
package_name = line.split('==')[0].split('>=')[0].split('<=')[0].strip()
packages.append(package_name)
missing_packages = []
for package in packages:
try:
__import__(package.replace('-', '_'))
print(f"{package}")
except ImportError:
print(f"{package} - NON INSTALLÉ")
missing_packages.append(package)
if missing_packages:
print(f"\n⚠️ Packages manquants: {', '.join(missing_packages)}")
print("Commande pour installer:")
print("cd visual_workflow_builder/backend && pip install -r requirements.txt")
return False
return True
def check_core_rpa_imports():
"""Vérifie les imports du core RPA Vision V3."""
print_subsection("Imports Core RPA Vision V3")
core_modules = [
"core.capture.screen_capturer",
"core.detection.ui_detector",
"core.embedding.fusion_engine"
]
available_modules = []
missing_modules = []
for module in core_modules:
try:
spec = importlib.util.find_spec(module)
if spec is not None:
print(f"{module}")
available_modules.append(module)
else:
print(f"{module} - MODULE INTROUVABLE")
missing_modules.append(module)
except Exception as e:
print(f"{module} - ERREUR: {e}")
missing_modules.append(module)
if missing_modules:
print(f"\n⚠️ Modules Core RPA manquants: {len(missing_modules)}/{len(core_modules)}")
print("Ces modules sont optionnels mais causent des ralentissements au démarrage")
return len(missing_modules) == 0
def check_optional_blueprints():
"""Vérifie les blueprints optionnels."""
print_subsection("Blueprints Optionnels")
backend_path = Path("visual_workflow_builder/backend")
optional_blueprints = [
"api/self_healing.py",
"api/visual_targets.py",
"api/element_detection.py",
"api/analytics.py",
"api/templates.py",
"api/executions.py",
"api/import_export.py",
"api/websocket_handlers.py"
]
available_blueprints = []
missing_blueprints = []
for blueprint in optional_blueprints:
blueprint_path = backend_path / blueprint
if blueprint_path.exists():
print(f"{blueprint}")
available_blueprints.append(blueprint)
else:
print(f"{blueprint} - MANQUANT")
missing_blueprints.append(blueprint)
print(f"\nBluprints disponibles: {len(available_blueprints)}/{len(optional_blueprints)}")
return available_blueprints, missing_blueprints
def check_database_setup():
"""Vérifie la configuration de la base de données."""
print_subsection("Configuration Base de Données")
# Vérifier le répertoire data
data_path = Path("data")
if not data_path.exists():
print("⚠️ Répertoire 'data' manquant - sera créé automatiquement")
data_path.mkdir(exist_ok=True)
else:
print("✅ Répertoire 'data' existe")
# Vérifier le répertoire workflows
workflows_path = data_path / "workflows"
if not workflows_path.exists():
print("⚠️ Répertoire 'data/workflows' manquant - sera créé automatiquement")
workflows_path.mkdir(exist_ok=True)
else:
print("✅ Répertoire 'data/workflows' existe")
return True
def test_minimal_import():
"""Test d'import minimal du backend."""
print_subsection("Test d'Import Minimal")
try:
# Changer vers le répertoire backend
original_cwd = os.getcwd()
backend_path = Path("visual_workflow_builder/backend")
os.chdir(backend_path)
# Ajouter le répertoire au path
sys.path.insert(0, str(backend_path.absolute()))
start_time = time.time()
# Test d'import des modèles
print("Import des modèles...")
import models
print("✅ models.py importé")
# Test d'import des services
print("Import des services...")
from services import serialization
print("✅ services.serialization importé")
# Test d'import de l'API workflows
print("Import de l'API workflows...")
from api import workflows
print("✅ api.workflows importé")
import_time = time.time() - start_time
print(f"\n✅ Import minimal réussi en {import_time:.2f}s")
# Restaurer le répertoire
os.chdir(original_cwd)
sys.path.remove(str(backend_path.absolute()))
return True, import_time
except Exception as e:
print(f"❌ ERREUR lors de l'import: {e}")
traceback.print_exc()
# Restaurer le répertoire
os.chdir(original_cwd)
if str(backend_path.absolute()) in sys.path:
sys.path.remove(str(backend_path.absolute()))
return False, 0
def analyze_app_py():
"""Analyse le fichier app.py pour identifier les goulots d'étranglement."""
print_subsection("Analyse de app.py")
app_path = Path("visual_workflow_builder/backend/app.py")
if not app_path.exists():
print("❌ app.py introuvable")
return
with open(app_path, 'r', encoding='utf-8') as f:
content = f.read()
# Analyser les imports lourds
heavy_imports = [
"core.capture.screen_capturer",
"core.detection.ui_detector",
"core.embedding.fusion_engine"
]
print("Imports lourds détectés:")
for import_name in heavy_imports:
if import_name in content:
print(f"⚠️ {import_name} - peut ralentir le démarrage")
# Analyser les blueprints optionnels
optional_imports = [
"api.self_healing",
"api.visual_targets",
"api.element_detection",
"api.analytics",
"api.templates",
"api.executions",
"api.import_export"
]
print("\nBluprints optionnels chargés:")
for blueprint in optional_imports:
if blueprint in content:
print(f"⚠️ {blueprint} - chargement conditionnel")
def generate_lightweight_app():
"""Génère une version allégée de app.py."""
print_subsection("Génération d'une Version Allégée")
lightweight_app = '''#!/usr/bin/env python3
"""
Visual Workflow Builder - Backend Flask Application (Version Allégée)
Auteur : Dom, Alice, Kiro - 08 janvier 2026
Version optimisée pour un démarrage rapide avec uniquement les fonctionnalités essentielles.
"""
from flask import Flask
from flask_cors import CORS
import os
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Initialize Flask app
app = Flask(__name__)
# Configuration minimale
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'dev-secret-key-change-in-production')
app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024 # 10MB max upload
# Enable CORS
CORS(app, resources={
r"/api/*": {
"origins": os.getenv('CORS_ORIGINS', 'http://localhost:3000').split(','),
"methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
"allow_headers": ["Content-Type", "Authorization"]
}
})
# Import et register uniquement les blueprints essentiels
try:
from api.workflows import workflows_bp
app.register_blueprint(workflows_bp, url_prefix='/api/workflows')
print("✅ Blueprint workflows chargé")
except ImportError as e:
print(f"❌ Erreur chargement workflows: {e}")
try:
from api.errors import error_response
except ImportError:
def error_response(code, message):
return {"error": message}, code
# Health check endpoint
@app.route('/health')
def health_check():
"""Health check endpoint pour monitoring"""
return {'status': 'healthy', 'version': '1.0.0-lightweight'}
@app.route('/')
def index():
"""Page d'accueil du backend"""
return {
'message': 'Visual Workflow Builder Backend (Version Allégée)',
'version': '1.0.0-lightweight',
'endpoints': ['/health', '/api/workflows']
}
# Global error handlers
@app.errorhandler(404)
def not_found(error):
return error_response(404, "Resource not found")
@app.errorhandler(500)
def internal_error(error):
return error_response(500, "Internal server error")
if __name__ == '__main__':
port = int(os.getenv('PORT', 5002))
debug = os.getenv('FLASK_ENV') == 'development'
print(f"🚀 Démarrage du backend allégé sur le port {port}")
print(f"🔧 Mode debug: {debug}")
app.run(
host='0.0.0.0',
port=port,
debug=debug,
use_reloader=debug
)
'''
# Écrire le fichier
lightweight_path = Path("visual_workflow_builder/backend/app_lightweight.py")
with open(lightweight_path, 'w', encoding='utf-8') as f:
f.write(lightweight_app)
print(f"✅ Version allégée créée: {lightweight_path}")
print("Pour utiliser la version allégée:")
print("cd visual_workflow_builder/backend && python app_lightweight.py")
def generate_startup_script():
"""Génère un script de démarrage optimisé."""
print_subsection("Script de Démarrage Optimisé")
startup_script = '''#!/bin/bash
# Script de démarrage optimisé du backend Visual Workflow Builder
# Auteur : Dom, Alice, Kiro - 08 janvier 2026
echo "🚀 Démarrage du Backend Visual Workflow Builder"
echo "================================================"
# Détecter python ou python3
if command -v python3 > /dev/null; then
PYTHON_CMD=python3
elif command -v python > /dev/null; then
PYTHON_CMD=python
else
echo "❌ Erreur: Python n'est pas installé"
exit 1
fi
echo "🐍 Utilisation de: $PYTHON_CMD"
# Vérifier si nous sommes dans le bon répertoire
if [ ! -f "app.py" ]; then
echo "❌ Erreur: app.py introuvable. Exécutez depuis visual_workflow_builder/backend/"
exit 1
fi
# Créer les répertoires nécessaires
echo "📁 Création des répertoires..."
mkdir -p ../../data/workflows
mkdir -p logs
# Vérifier les dépendances critiques
echo "🔍 Vérification des dépendances..."
$PYTHON_CMD -c "import flask, flask_cors; print('✅ Dépendances de base OK')" || {
echo "❌ Dépendances manquantes. Installation..."
pip install flask flask-cors python-dotenv PyYAML
}
# Choix du mode de démarrage
echo ""
echo "Choisissez le mode de démarrage:"
echo "1) Mode normal (toutes les fonctionnalités)"
echo "2) Mode allégé (démarrage rapide)"
echo "3) Mode debug (développement)"
echo ""
read -p "Votre choix (1-3): " choice
case $choice in
1)
echo "🚀 Démarrage en mode normal..."
export FLASK_ENV=production
$PYTHON_CMD app.py
;;
2)
echo "⚡ Démarrage en mode allégé..."
export FLASK_ENV=production
$PYTHON_CMD app_lightweight.py
;;
3)
echo "🔧 Démarrage en mode debug..."
export FLASK_ENV=development
export FLASK_DEBUG=1
$PYTHON_CMD app.py
;;
*)
echo "❌ Choix invalide. Démarrage en mode normal..."
$PYTHON_CMD app.py
;;
esac
'''
# Écrire le script
script_path = Path("visual_workflow_builder/backend/start_optimized.sh")
with open(script_path, 'w', encoding='utf-8') as f:
f.write(startup_script)
# Rendre exécutable
os.chmod(script_path, 0o755)
print(f"✅ Script optimisé créé: {script_path}")
print("Pour utiliser le script optimisé:")
print("cd visual_workflow_builder/backend && ./start_optimized.sh")
def main():
"""Fonction principale de diagnostic."""
print_section("DIAGNOSTIC BACKEND VISUAL WORKFLOW BUILDER")
print("Auteur : Dom, Alice, Kiro - 08 janvier 2026")
# Vérifications de base
issues = []
if not check_python_version():
issues.append("Version Python incompatible")
if not check_backend_structure():
issues.append("Structure backend incomplète")
if not check_dependencies():
issues.append("Dépendances manquantes")
# Vérifications avancées
check_database_setup()
core_available = check_core_rpa_imports()
if not core_available:
issues.append("Modules Core RPA manquants (ralentissement)")
available_bp, missing_bp = check_optional_blueprints()
if len(missing_bp) > len(available_bp):
issues.append("Nombreux blueprints manquants")
# Test d'import
import_success, import_time = test_minimal_import()
if not import_success:
issues.append("Échec de l'import minimal")
elif import_time > 5.0:
issues.append(f"Import lent ({import_time:.2f}s)")
# Analyse du code
analyze_app_py()
# Résumé
print_section("RÉSUMÉ DU DIAGNOSTIC")
if not issues:
print("✅ Aucun problème critique détecté")
print(f"⚡ Temps d'import: {import_time:.2f}s")
else:
print("⚠️ Problèmes détectés:")
for i, issue in enumerate(issues, 1):
print(f" {i}. {issue}")
# Solutions
print_section("SOLUTIONS RECOMMANDÉES")
if "Dépendances manquantes" in issues:
print("1. Installer les dépendances:")
print(" cd visual_workflow_builder/backend")
print(" pip install -r requirements.txt")
if "Modules Core RPA manquants" in issues or import_time > 3.0:
print("2. Utiliser la version allégée pour un démarrage rapide:")
generate_lightweight_app()
print("3. Script de démarrage optimisé:")
generate_startup_script()
if import_time > 5.0:
print("4. Optimisations supplémentaires:")
print(" - Désactiver les blueprints non utilisés")
print(" - Utiliser un environnement virtuel dédié")
print(" - Vérifier les imports circulaires")
print_section("DIAGNOSTIC TERMINÉ")
print("Pour plus d'aide, consultez la documentation dans docs/")
if __name__ == "__main__":
main()