Add dedicated logging for ID collisions in ingestion_processor.py

Implement a new method to log ID collisions into a separate file (logs/id_collisions.log) for manual analysis. This update captures relevant metadata in JSONL format, enhancing traceability during the ingestion process. The logging occurs when a conflict is detected between existing and new files sharing the same note_id, improving error handling and diagnostics.
This commit is contained in:
Lars 2026-01-12 09:04:36 +01:00
parent ec9b3c68af
commit c42a76b3d7

View File

@ -91,6 +91,58 @@ class IngestionService:
except Exception as e: except Exception as e:
logger.warning(f"DB initialization warning: {e}") logger.warning(f"DB initialization warning: {e}")
def _log_id_collision(
self,
note_id: str,
existing_path: str,
conflicting_path: str,
action: str = "ERROR"
) -> None:
"""
WP-24c v4.5.10: Loggt ID-Kollisionen in eine dedizierte Log-Datei.
Schreibt alle ID-Kollisionen in logs/id_collisions.log für manuelle Analyse.
Format: JSONL (eine Kollision pro Zeile) mit allen relevanten Metadaten.
Args:
note_id: Die doppelte note_id
existing_path: Pfad der bereits vorhandenen Datei
conflicting_path: Pfad der kollidierenden Datei
action: Gewählte Aktion (z.B. "ERROR", "SKIPPED")
"""
import json
from datetime import datetime
# Erstelle Log-Verzeichnis falls nicht vorhanden
log_dir = "logs"
if not os.path.exists(log_dir):
os.makedirs(log_dir)
log_file = os.path.join(log_dir, "id_collisions.log")
# Erstelle Log-Eintrag mit allen relevanten Informationen
log_entry = {
"timestamp": datetime.now().isoformat(),
"note_id": note_id,
"existing_file": {
"path": existing_path,
"filename": os.path.basename(existing_path) if existing_path else None
},
"conflicting_file": {
"path": conflicting_path,
"filename": os.path.basename(conflicting_path) if conflicting_path else None
},
"action": action,
"collection_prefix": self.prefix
}
# Schreibe als JSONL (eine Zeile pro Eintrag)
try:
with open(log_file, "a", encoding="utf-8") as f:
f.write(json.dumps(log_entry, ensure_ascii=False) + "\n")
except Exception as e:
logger.warning(f"⚠️ Konnte ID-Kollision nicht in Log-Datei schreiben: {e}")
def _persist_rejected_edges(self, note_id: str, rejected_edges: List[Dict[str, Any]]) -> None: def _persist_rejected_edges(self, note_id: str, rejected_edges: List[Dict[str, Any]]) -> None:
""" """
WP-24c v4.5.9: Persistiert abgelehnte Kanten für Audit-Zwecke. WP-24c v4.5.9: Persistiert abgelehnte Kanten für Audit-Zwecke.
@ -274,11 +326,19 @@ class IngestionService:
old_path = old_payload.get("path", "") old_path = old_payload.get("path", "")
if old_path and old_path != normalized_file_path: if old_path and old_path != normalized_file_path:
# ID-Kollision erkannt: Zwei verschiedene Dateien haben dieselbe note_id # ID-Kollision erkannt: Zwei verschiedene Dateien haben dieselbe note_id
# Logge die Kollision in dedizierte Log-Datei
self._log_id_collision(
note_id=note_id,
existing_path=old_path,
conflicting_path=normalized_file_path,
action="ERROR"
)
logger.error( logger.error(
f"❌ [ID-KOLLISION] Kritischer Fehler: Die note_id '{note_id}' wird bereits von einer anderen Datei verwendet!\n" f"❌ [ID-KOLLISION] Kritischer Fehler: Die note_id '{note_id}' wird bereits von einer anderen Datei verwendet!\n"
f" Bereits vorhanden: '{old_path}'\n" f" Bereits vorhanden: '{old_path}'\n"
f" Konflikt mit: '{normalized_file_path}'\n" f" Konflikt mit: '{normalized_file_path}'\n"
f" Lösung: Bitte ändern Sie die 'id' im Frontmatter einer der beiden Dateien, um eine eindeutige ID zu gewährleisten." f" Lösung: Bitte ändern Sie die 'id' im Frontmatter einer der beiden Dateien, um eine eindeutige ID zu gewährleisten.\n"
f" Details wurden in logs/id_collisions.log gespeichert."
) )
return {**result, "status": "error", "error": "id_collision", "note_id": note_id, "existing_path": old_path, "conflicting_path": normalized_file_path} return {**result, "status": "error", "error": "id_collision", "note_id": note_id, "existing_path": old_path, "conflicting_path": normalized_file_path}