import re from pathlib import Path class LogParser: def __init__(self): # Bekannte Fehlermuster self.patterns = { "import_error": r"ImportError: No module named ['\"]([^'\"]+)['\"]", "syntax_error": r"SyntaxError: (.+)", "indentation_error": r"IndentationError: (.+)", "name_error": r"NameError: name ['\"]([^'\"]+)['\"] is not defined", "type_error": r"TypeError: (.+)", "attribute_error": r"AttributeError: (.+)", "key_error": r"KeyError: ['\"]([^'\"]+)['\"]", "index_error": r"IndexError: (.+)", "value_error": r"ValueError: (.+)", "zero_division": r"ZeroDivisionError: (.+)", "file_not_found": r"FileNotFoundError: (.+)", "permission_error": r"PermissionError: (.+)", "connection_error": r"ConnectionError: (.+)", "timeout_error": r"TimeoutError: (.+)", "memory_error": r"MemoryError: (.+)", "cuda_error": r"CUDA out of memory", "oom_error": r"OutOfMemoryError|OOM", "runtime_error": r"RuntimeError: (.+)", "assertion_error": r"AssertionError: (.+)", "modulenotfound": r"ModuleNotFoundError: No module named ['\"]([^'\"]+)['\"]" } def parse_log_file(self, log_path): """Liest und parst eine Log-Datei""" log_path = Path(log_path) if not log_path.exists(): return {"error": "Datei nicht gefunden"} with open(log_path, 'r') as f: content = f.read() return self.parse_log_content(content) def parse_log_content(self, content): """Extrahiert Fehler aus Log-Text""" result = { "errors": [], "warnings": [], "traceback": [], "summary": "" } lines = content.split('\n') in_traceback = False traceback_lines = [] for line in lines: # Traceback erkennen if "Traceback (most recent call last)" in line: in_traceback = True traceback_lines = [line] continue if in_traceback: traceback_lines.append(line) if line.startswith(" "): continue else: # Fehler gefunden error_info = self._extract_error(line) if error_info: result["errors"].append(error_info) result["traceback"] = "\n".join(traceback_lines[-10:]) # Letzte 10 Zeilen in_traceback = False continue # Warnungen if "warning" in line.lower(): result["warnings"].append(line.strip()) # Einzelfehler (ohne Traceback) error_info = self._extract_error(line) if error_info and not in_traceback: result["errors"].append(error_info) # Zusammenfassung erstellen result["summary"] = self._create_summary(result) return result def _extract_error(self, line): """Extrahiert Fehlertyp und -nachricht""" for error_type, pattern in self.patterns.items(): match = re.search(pattern, line, re.IGNORECASE) if match: return { "type": error_type, "message": match.group(0), "detail": match.group(1) if match.groups() else "", "line": line.strip() } return None def _create_summary(self, result): """Erstellt prägnante Zusammenfassung""" errors = result["errors"] if not errors: return "Keine eindeutigen Fehler gefunden." main_error = errors[0] summary = f"❌ {main_error['type']}: {main_error['detail']}" if len(errors) > 1: summary += f"\n⚠️ +{len(errors)-1} weitere Fehler" if result["warnings"]: summary += f"\n⚠️ {len(result['warnings'])} Warnungen" return summary def extract_relevant_context(self, content, max_lines=20): """Extrahiert relevante Zeilen um Fehler herum""" lines = content.split('\n') error_indices = [] for i, line in enumerate(lines): if self._extract_error(line): error_indices.append(i) if not error_indices: return content[:500] # Erste 500 Zeichen # Kontext um ersten Fehler start = max(0, error_indices[0] - 10) end = min(len(lines), error_indices[0] + 10) return "\n".join(lines[start:end])