straceanalyse.py aktualisiert
This commit is contained in:
166
straceanalyse.py
166
straceanalyse.py
@@ -22,22 +22,22 @@ class ShopPerformanceAnalyzer:
|
||||
'file_paths': Counter(),
|
||||
'errors': Counter()
|
||||
}
|
||||
self.debug = False # Weniger Output bei vielen Prozessen
|
||||
self.debug = False
|
||||
self.output_dir = f"/root/shop_analysis_{domain}_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
||||
|
||||
def get_php_fpm_pids(self):
|
||||
"""Finde alle PHP-FPM PIDs für den Shop"""
|
||||
"""Finde alle PHP-FPM PIDs fuer den Shop"""
|
||||
try:
|
||||
cmd = f"ps aux | grep 'php-fpm: pool {self.domain}' | grep -v grep | awk '{{print $2}}'"
|
||||
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
||||
pids = [int(pid) for pid in result.stdout.strip().split('\n') if pid]
|
||||
return pids
|
||||
except Exception as e:
|
||||
print(f"❌ Fehler beim Finden der PIDs: {e}")
|
||||
print(f"Fehler beim Finden der PIDs: {e}")
|
||||
return []
|
||||
|
||||
def run_strace(self, pid, duration=5):
|
||||
"""Führe strace auf einem Prozess aus"""
|
||||
"""Fuehre strace auf einem Prozess aus"""
|
||||
try:
|
||||
cmd = [
|
||||
'strace',
|
||||
@@ -137,10 +137,10 @@ class ShopPerformanceAnalyzer:
|
||||
|
||||
os.makedirs(self.output_dir, exist_ok=True)
|
||||
|
||||
# 1. Komplette Liste (sortiert nach Häufigkeit)
|
||||
# 1. Komplette Liste (sortiert nach Haeufigkeit)
|
||||
list_file = os.path.join(self.output_dir, 'missing_files_all.txt')
|
||||
with open(list_file, 'w') as f:
|
||||
f.write(f"# Fehlende Dateien für {self.domain}\n")
|
||||
f.write(f"# Fehlende Dateien fuer {self.domain}\n")
|
||||
f.write(f"# Erstellt: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
|
||||
f.write(f"# Total: {len(self.results['missing_files'])} Dateien\n")
|
||||
f.write(f"# Zugriffe: {sum(self.results['missing_files'].values())}\n")
|
||||
@@ -192,7 +192,7 @@ class ShopPerformanceAnalyzer:
|
||||
f.write(f'SHOP_ROOT="/var/www/vhosts/{self.domain}/httpdocs"\n')
|
||||
f.write('PLACEHOLDER="$SHOP_ROOT/gfx/keinBild.gif"\n\n')
|
||||
f.write('if [ ! -f "$PLACEHOLDER" ]; then\n')
|
||||
f.write(' echo "❌ Fehler: Placeholder nicht gefunden: $PLACEHOLDER"\n')
|
||||
f.write(' echo "Fehler: Placeholder nicht gefunden: $PLACEHOLDER"\n')
|
||||
f.write(' exit 1\n')
|
||||
f.write('fi\n\n')
|
||||
f.write('echo "Erstelle fehlende Dateien..."\n')
|
||||
@@ -217,9 +217,9 @@ class ShopPerformanceAnalyzer:
|
||||
f.write(f'fi\n')
|
||||
|
||||
f.write('\necho ""\n')
|
||||
f.write('echo "✅ Fertig!"\n')
|
||||
f.write('echo "Fertig!"\n')
|
||||
f.write('echo " Erstellt: $CREATED Platzhalter"\n')
|
||||
f.write('echo " Übersprungen: $SKIPPED (existieren bereits)"\n')
|
||||
f.write('echo " Uebersprungen: $SKIPPED (existieren bereits)"\n')
|
||||
f.write(f'echo " Total Dateien: {len(image_files)}"\n')
|
||||
|
||||
os.chmod(script_file, 0o755)
|
||||
@@ -257,11 +257,11 @@ class ShopPerformanceAnalyzer:
|
||||
with open(manufacturer_file, 'w') as f:
|
||||
f.write(f"# Hersteller IDs mit fehlenden Bildern\n")
|
||||
f.write(f"# Total: {len(manufacturer_ids)} Hersteller\n")
|
||||
f.write(f"# Verwendung: Im JTL-Shop Admin diese Hersteller prüfen\n\n")
|
||||
f.write(f"# Verwendung: Im JTL-Shop Admin diese Hersteller pruefen\n\n")
|
||||
for mid in sorted(manufacturer_ids, key=int):
|
||||
f.write(f"{mid}\n")
|
||||
|
||||
# 6. Nur Dateipfade (für weitere Verarbeitung)
|
||||
# 6. Nur Dateipfade (fuer weitere Verarbeitung)
|
||||
paths_only_file = os.path.join(self.output_dir, 'missing_files_paths_only.txt')
|
||||
with open(paths_only_file, 'w') as f:
|
||||
for filepath in self.results['missing_files'].keys():
|
||||
@@ -272,36 +272,36 @@ class ShopPerformanceAnalyzer:
|
||||
def generate_report(self):
|
||||
"""Generiere Analyse-Report"""
|
||||
print("\n" + "="*80)
|
||||
print(f"🔍 PERFORMANCE ANALYSE: {self.domain}")
|
||||
print(f"📅 {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print(f"PERFORMANCE ANALYSE: {self.domain}")
|
||||
print(f"Datum: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print("="*80 + "\n")
|
||||
|
||||
total_syscalls = sum(self.results['syscalls'].values())
|
||||
|
||||
if total_syscalls == 0:
|
||||
print("⚠️ WARNUNG: Keine Syscalls aufgezeichnet!")
|
||||
print(" Mögliche Gründe:")
|
||||
print("WARNUNG: Keine Syscalls aufgezeichnet!")
|
||||
print(" Moegliche Gruende:")
|
||||
print(" - Prozesse sind gerade idle (wenig Traffic)")
|
||||
print(" - Strace hat keine Berechtigung")
|
||||
print(" - Prozesse wurden zwischen Analyse beendet\n")
|
||||
print(" Versuche: python3 script.py spiel-und-modellbau.com 10\n")
|
||||
return
|
||||
|
||||
print("📊 SYSCALL STATISTIK")
|
||||
print("SYSCALL STATISTIK")
|
||||
print("-" * 80)
|
||||
for syscall, count in self.results['syscalls'].most_common(15):
|
||||
percentage = (count / total_syscalls * 100) if total_syscalls > 0 else 0
|
||||
bar = '█' * int(percentage / 2)
|
||||
bar = '#' * int(percentage / 2)
|
||||
print(f" {syscall:20s}: {count:6d} ({percentage:5.1f}%) {bar}")
|
||||
print()
|
||||
|
||||
# Fehlende Dateien
|
||||
missing_count = len(self.results['missing_files'])
|
||||
if missing_count > 0:
|
||||
print("❌ FEHLENDE DATEIEN (ENOENT)")
|
||||
print("FEHLENDE DATEIEN (ENOENT)")
|
||||
print("-" * 80)
|
||||
print(f" ⚠️ {missing_count} verschiedene Dateien nicht gefunden!")
|
||||
print(f" ⚠️ {sum(self.results['missing_files'].values())} Zugriffe auf nicht-existierende Dateien!\n")
|
||||
print(f" WARNUNG: {missing_count} verschiedene Dateien nicht gefunden!")
|
||||
print(f" WARNUNG: {sum(self.results['missing_files'].values())} Zugriffe auf nicht-existierende Dateien!\n")
|
||||
|
||||
# Kategorien
|
||||
categories = defaultdict(int)
|
||||
@@ -319,7 +319,7 @@ class ShopPerformanceAnalyzer:
|
||||
|
||||
print(" Kategorien:")
|
||||
for category, count in sorted(categories.items(), key=lambda x: x[1], reverse=True):
|
||||
print(f" • {category:25s}: {count:4d} Dateien")
|
||||
print(f" * {category:25s}: {count:4d} Dateien")
|
||||
print()
|
||||
|
||||
print(" Top 15 fehlende Dateien:")
|
||||
@@ -328,13 +328,13 @@ class ShopPerformanceAnalyzer:
|
||||
print(f" [{count:3d}x] {short_path}")
|
||||
|
||||
if len(self.results['missing_files']) > 15:
|
||||
print(f"\n ℹ️ ... und {len(self.results['missing_files'])-15} weitere")
|
||||
print(f" ℹ️ Vollständige Liste siehe Export-Dateien!")
|
||||
print(f"\n INFO: ... und {len(self.results['missing_files'])-15} weitere")
|
||||
print(f" INFO: Vollstaendige Liste siehe Export-Dateien!")
|
||||
print()
|
||||
|
||||
# Errors
|
||||
if self.results['errors']:
|
||||
print("⚠️ FEHLER")
|
||||
print("FEHLER")
|
||||
print("-" * 80)
|
||||
for error, count in self.results['errors'].items():
|
||||
print(f" {error:20s}: {count:6d}x")
|
||||
@@ -342,19 +342,19 @@ class ShopPerformanceAnalyzer:
|
||||
|
||||
# MySQL Queries
|
||||
if self.results['mysql_queries']:
|
||||
print("🗄️ MYSQL QUERIES")
|
||||
print("MYSQL QUERIES")
|
||||
print("-" * 80)
|
||||
query_counter = Counter(self.results['mysql_queries'])
|
||||
print(f" Total Queries: {len(self.results['mysql_queries'])}")
|
||||
print(f" Unique Queries: {len(query_counter)}")
|
||||
print("\n Häufigste Queries:")
|
||||
print("\n Haeufigste Queries:")
|
||||
for query, count in query_counter.most_common(10):
|
||||
print(f" [{count:3d}x] {query[:70]}...")
|
||||
print()
|
||||
|
||||
# File Paths
|
||||
if self.results['file_paths']:
|
||||
print("📁 HÄUFIGSTE DATEIZUGRIFFE")
|
||||
print("HAEUFIGSTE DATEIZUGRIFFE")
|
||||
print("-" * 80)
|
||||
for path, count in self.results['file_paths'].most_common(15):
|
||||
print(f" [{count:3d}x] {path}")
|
||||
@@ -362,7 +362,7 @@ class ShopPerformanceAnalyzer:
|
||||
|
||||
# Redis
|
||||
if self.results['redis_operations']:
|
||||
print("🔴 REDIS OPERATIONEN")
|
||||
print("REDIS OPERATIONEN")
|
||||
print("-" * 80)
|
||||
total_redis = sum(self.results['redis_operations'].values())
|
||||
for op, count in self.results['redis_operations'].most_common():
|
||||
@@ -372,29 +372,29 @@ class ShopPerformanceAnalyzer:
|
||||
|
||||
# Slow Operations
|
||||
if self.results['slow_operations']:
|
||||
print("🐌 LANGSAME OPERATIONEN")
|
||||
print("LANGSAME OPERATIONEN")
|
||||
print("-" * 80)
|
||||
slow_counter = Counter(self.results['slow_operations'])
|
||||
for op, count in slow_counter.items():
|
||||
print(f" ⚠️ {op}: {count}x")
|
||||
print(f" WARNUNG: {op}: {count}x")
|
||||
print()
|
||||
|
||||
# Export fehlende Dateien
|
||||
if missing_count > 0:
|
||||
print("="*80)
|
||||
print("💾 EXPORTIERE FEHLENDE DATEIEN")
|
||||
print("EXPORTIERE FEHLENDE DATEIEN")
|
||||
print("="*80 + "\n")
|
||||
|
||||
export_dir = self.export_missing_files()
|
||||
if export_dir:
|
||||
print(f"✅ Dateien exportiert nach: {export_dir}\n")
|
||||
print(f"Dateien exportiert nach: {export_dir}\n")
|
||||
print(" Erstellt:")
|
||||
print(f" 📄 missing_files_all.txt - Komplette Liste (sortiert nach Häufigkeit)")
|
||||
print(f" 📁 missing_files_by_category.txt - Nach Kategorie gruppiert")
|
||||
print(f" 📊 missing_files.csv - CSV für Excel")
|
||||
print(f" 🔧 create_placeholders.sh - Bash Script (ausführbar)")
|
||||
print(f" 🏷️ missing_manufacturer_ids.txt - Hersteller IDs")
|
||||
print(f" 📝 missing_files_paths_only.txt - Nur Pfade (für Scripts)\n")
|
||||
print(f" missing_files_all.txt - Komplette Liste (sortiert nach Haeufigkeit)")
|
||||
print(f" missing_files_by_category.txt - Nach Kategorie gruppiert")
|
||||
print(f" missing_files.csv - CSV fuer Excel")
|
||||
print(f" create_placeholders.sh - Bash Script (ausfuehrbar)")
|
||||
print(f" missing_manufacturer_ids.txt - Hersteller IDs")
|
||||
print(f" missing_files_paths_only.txt - Nur Pfade (fuer Scripts)\n")
|
||||
|
||||
print(" Quick-Fix:")
|
||||
print(f" bash {export_dir}/create_placeholders.sh\n")
|
||||
@@ -405,7 +405,7 @@ class ShopPerformanceAnalyzer:
|
||||
def generate_recommendations(self, total_syscalls, missing_count):
|
||||
"""Generiere Handlungsempfehlungen"""
|
||||
print("="*80)
|
||||
print("💡 HANDLUNGSEMPFEHLUNGEN FÜR DEN KUNDEN")
|
||||
print("HANDLUNGSEMPFEHLUNGEN FUER DEN KUNDEN")
|
||||
print("="*80 + "\n")
|
||||
|
||||
recommendations = []
|
||||
@@ -418,10 +418,10 @@ class ShopPerformanceAnalyzer:
|
||||
if manufacturer_missing > 0:
|
||||
recommendations.append({
|
||||
'priority': priority,
|
||||
'severity': '🔥 KRITISCH',
|
||||
'severity': 'KRITISCH',
|
||||
'problem': f'{manufacturer_missing} Hersteller-Bilder fehlen',
|
||||
'impact': f'Jedes fehlende Bild = 6-8 stat() Calls. Bei {sum(v for k,v in self.results["missing_files"].items() if "manufacturer" in k)} Zugriffen!',
|
||||
'solution': '1. JTL-Shop Admin einloggen\n2. Bilder → Hersteller-Bilder → "Fehlende generieren"\n3. ODER: Bash Script ausführen (siehe Export)',
|
||||
'solution': '1. JTL-Shop Admin einloggen\n2. Bilder -> Hersteller-Bilder -> "Fehlende generieren"\n3. ODER: Bash Script ausfuehren (siehe Export)',
|
||||
'files': [f"{self.output_dir}/create_placeholders.sh",
|
||||
f"{self.output_dir}/missing_manufacturer_ids.txt"]
|
||||
})
|
||||
@@ -430,10 +430,10 @@ class ShopPerformanceAnalyzer:
|
||||
if product_missing > 0:
|
||||
recommendations.append({
|
||||
'priority': priority,
|
||||
'severity': '⚠️ WICHTIG',
|
||||
'severity': 'WICHTIG',
|
||||
'problem': f'{product_missing} Produkt-Bilder fehlen',
|
||||
'impact': 'Erhöhte I/O Last',
|
||||
'solution': 'JTL-Shop Admin → Bilder → "Bildcache regenerieren"'
|
||||
'impact': 'Erhoehte I/O Last',
|
||||
'solution': 'JTL-Shop Admin -> Bilder -> "Bildcache regenerieren"'
|
||||
})
|
||||
priority += 1
|
||||
|
||||
@@ -442,11 +442,11 @@ class ShopPerformanceAnalyzer:
|
||||
if stat_calls > 500:
|
||||
recommendations.append({
|
||||
'priority': priority,
|
||||
'severity': '⚠️ WICHTIG',
|
||||
'severity': 'WICHTIG',
|
||||
'problem': f'{stat_calls} Filesystem stat() Calls',
|
||||
'impact': 'Filesystem-Thrashing, langsame Response-Times',
|
||||
'solution': 'PHP Realpath Cache erhöhen in PHP-Einstellungen',
|
||||
'technical': 'Plesk → Domain → PHP Settings:\nrealpath_cache_size = 4096K\nrealpath_cache_ttl = 600'
|
||||
'solution': 'PHP Realpath Cache erhoehen in PHP-Einstellungen',
|
||||
'technical': 'Plesk -> Domain -> PHP Settings:\nrealpath_cache_size = 4096K\nrealpath_cache_ttl = 600'
|
||||
})
|
||||
priority += 1
|
||||
|
||||
@@ -454,20 +454,20 @@ class ShopPerformanceAnalyzer:
|
||||
if imagemagick_count > 3:
|
||||
recommendations.append({
|
||||
'priority': priority,
|
||||
'severity': '🔥 KRITISCH',
|
||||
'severity': 'KRITISCH',
|
||||
'problem': f'ImageMagick wird {imagemagick_count}x aufgerufen',
|
||||
'impact': 'CPU-intensive Bildverarbeitung bei jedem Request!',
|
||||
'solution': '1. Bild-Cache in JTL-Shop aktivieren\n2. Alle Bildgrößen vorher generieren\n3. Prüfen ob Bilder wirklich vorhanden sind'
|
||||
'solution': '1. Bild-Cache in JTL-Shop aktivieren\n2. Alle Bildgroessen vorher generieren\n3. Pruefen ob Bilder wirklich vorhanden sind'
|
||||
})
|
||||
priority += 1
|
||||
|
||||
if len(self.results['mysql_queries']) > 50:
|
||||
recommendations.append({
|
||||
'priority': priority,
|
||||
'severity': '⚠️ WICHTIG',
|
||||
'severity': 'WICHTIG',
|
||||
'problem': f'{len(self.results["mysql_queries"])} MySQL Queries',
|
||||
'impact': 'N+1 Query Problem, Database Overhead',
|
||||
'solution': 'JTL-Shop: System → Cache → Object Cache aktivieren (Redis)'
|
||||
'solution': 'JTL-Shop: System -> Cache -> Object Cache aktivieren (Redis)'
|
||||
})
|
||||
priority += 1
|
||||
|
||||
@@ -475,41 +475,41 @@ class ShopPerformanceAnalyzer:
|
||||
if eagain_count > 100:
|
||||
recommendations.append({
|
||||
'priority': priority,
|
||||
'severity': '⚠️ WICHTIG',
|
||||
'severity': 'WICHTIG',
|
||||
'problem': f'{eagain_count}x EAGAIN',
|
||||
'impact': 'Redis/MySQL Verbindungen überlastet',
|
||||
'solution': 'Redis Connection Pool erhöhen oder PHP-FPM Worker erhöhen'
|
||||
'impact': 'Redis/MySQL Verbindungen ueberlastet',
|
||||
'solution': 'Redis Connection Pool erhoehen oder PHP-FPM Worker erhoehen'
|
||||
})
|
||||
priority += 1
|
||||
|
||||
if recommendations:
|
||||
for rec in recommendations:
|
||||
print(f"{rec['severity']} PRIORITÄT {rec['priority']}: {rec['problem']}")
|
||||
print(f" 📊 Impact: {rec['impact']}")
|
||||
print(f" ✅ Lösung: {rec['solution']}")
|
||||
print(f"[{rec['severity']}] PRIORITAET {rec['priority']}: {rec['problem']}")
|
||||
print(f" Impact: {rec['impact']}")
|
||||
print(f" Loesung: {rec['solution']}")
|
||||
if 'files' in rec:
|
||||
print(f" 📁 Dateien:")
|
||||
print(f" Dateien:")
|
||||
for file in rec['files']:
|
||||
print(f" • {file}")
|
||||
print(f" * {file}")
|
||||
if 'technical' in rec:
|
||||
lines = rec['technical'].split('\n')
|
||||
print(f" 🔧 Technisch:")
|
||||
print(f" Technisch:")
|
||||
for line in lines:
|
||||
print(f" {line}")
|
||||
print()
|
||||
else:
|
||||
print("✅ Keine kritischen Probleme gefunden!\n")
|
||||
print("Keine kritischen Probleme gefunden!\n")
|
||||
|
||||
print("="*80)
|
||||
print("📋 ZUSAMMENFASSUNG")
|
||||
print("ZUSAMMENFASSUNG")
|
||||
print("="*80)
|
||||
print(f" • Total Syscalls: {total_syscalls}")
|
||||
print(f" • Fehlende Dateien: {missing_count}")
|
||||
print(f" • MySQL Queries: {len(self.results['mysql_queries'])}")
|
||||
print(f" • Redis Operations: {sum(self.results['redis_operations'].values())}")
|
||||
print(f" • Handlungsempfehlungen: {len(recommendations)}")
|
||||
print(f" * Total Syscalls: {total_syscalls}")
|
||||
print(f" * Fehlende Dateien: {missing_count}")
|
||||
print(f" * MySQL Queries: {len(self.results['mysql_queries'])}")
|
||||
print(f" * Redis Operations: {sum(self.results['redis_operations'].values())}")
|
||||
print(f" * Handlungsempfehlungen: {len(recommendations)}")
|
||||
if missing_count > 0:
|
||||
print(f"\n 📁 Export-Verzeichnis: {self.output_dir}")
|
||||
print(f"\n Export-Verzeichnis: {self.output_dir}")
|
||||
print()
|
||||
|
||||
def main():
|
||||
@@ -533,27 +533,27 @@ def main():
|
||||
duration = int(sys.argv[2]) if len(sys.argv) > 2 else 5
|
||||
max_processes = int(sys.argv[3]) if len(sys.argv) > 3 else None
|
||||
|
||||
print(f"\n🚀 Starte Performance-Analyse für: {domain}")
|
||||
print(f"⏱️ Analyse-Dauer: {duration} Sekunden pro Prozess")
|
||||
print(f"\nStarte Performance-Analyse fuer: {domain}")
|
||||
print(f"Analyse-Dauer: {duration} Sekunden pro Prozess")
|
||||
if max_processes:
|
||||
print(f"🔢 Max Prozesse: {max_processes}")
|
||||
print(f"Max Prozesse: {max_processes}")
|
||||
else:
|
||||
print(f"🔢 Prozesse: ALLE gefundenen PHP-FPM Worker")
|
||||
print(f"Prozesse: ALLE gefundenen PHP-FPM Worker")
|
||||
print()
|
||||
|
||||
analyzer = ShopPerformanceAnalyzer(domain)
|
||||
|
||||
pids = analyzer.get_php_fpm_pids()
|
||||
if not pids:
|
||||
print("❌ Keine PHP-FPM Prozesse gefunden!")
|
||||
print("Keine PHP-FPM Prozesse gefunden!")
|
||||
sys.exit(1)
|
||||
|
||||
# Limit anwenden falls gesetzt
|
||||
if max_processes and len(pids) > max_processes:
|
||||
print(f"✅ {len(pids)} PHP-FPM Prozesse gefunden (analysiere {max_processes})")
|
||||
print(f"{len(pids)} PHP-FPM Prozesse gefunden (analysiere {max_processes})")
|
||||
pids = pids[:max_processes]
|
||||
else:
|
||||
print(f"✅ {len(pids)} PHP-FPM Prozesse gefunden (analysiere alle)")
|
||||
print(f"{len(pids)} PHP-FPM Prozesse gefunden (analysiere alle)")
|
||||
|
||||
print(f" PIDs: {pids}\n")
|
||||
|
||||
@@ -562,7 +562,7 @@ def main():
|
||||
analyzed = 0
|
||||
failed = 0
|
||||
|
||||
print("🔄 Analyse läuft...")
|
||||
print("Analyse laeuft...")
|
||||
print("-" * 80)
|
||||
|
||||
for i, pid in enumerate(pids, 1):
|
||||
@@ -570,7 +570,7 @@ def main():
|
||||
percent = int((i / total) * 100)
|
||||
bar_length = 40
|
||||
filled = int((percent / 100) * bar_length)
|
||||
bar = '█' * filled + '░' * (bar_length - filled)
|
||||
bar = '#' * filled + '-' * (bar_length - filled)
|
||||
|
||||
print(f"\r[{bar}] {percent:3d}% | PID {pid:6d} ({i}/{total})", end='', flush=True)
|
||||
|
||||
@@ -581,17 +581,17 @@ def main():
|
||||
else:
|
||||
failed += 1
|
||||
|
||||
print(f"\r[{'█' * bar_length}] 100% | Fertig!{' ' * 30}")
|
||||
print(f"\r[{'#' * bar_length}] 100% | Fertig!{' ' * 30}")
|
||||
print("-" * 80)
|
||||
print(f"\n✅ Analyse abgeschlossen!")
|
||||
print(f" • Erfolgreich analysiert: {analyzed}/{total}")
|
||||
print(f"\nAnalyse abgeschlossen!")
|
||||
print(f" * Erfolgreich analysiert: {analyzed}/{total}")
|
||||
if failed > 0:
|
||||
print(f" • Idle/Keine Daten: {failed}")
|
||||
print(f" * Idle/Keine Daten: {failed}")
|
||||
print()
|
||||
|
||||
if analyzed == 0:
|
||||
print("⚠️ Konnte kesine Daten sammeln!")
|
||||
print(" Shop hat gerade wenig Traffic. Versuche später nochmal oder erhöhe duration.\n")
|
||||
print("Konnte keine Daten sammeln!")
|
||||
print(" Shop hat gerade wenig Traffic. Versuche spaeter nochmal oder erhoehe duration.\n")
|
||||
sys.exit(1)
|
||||
|
||||
analyzer.generate_report()
|
||||
|
||||
Reference in New Issue
Block a user