#!/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()