From e210eaaf86eae94d1131b1c1fd4d4a7b15dcfb9e Mon Sep 17 00:00:00 2001 From: Mika Date: Sun, 18 Jan 2026 17:11:11 +0000 Subject: [PATCH] Add marker_analysis/src/marker_analysis/core.py --- marker_analysis/src/marker_analysis/core.py | 63 +++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 marker_analysis/src/marker_analysis/core.py diff --git a/marker_analysis/src/marker_analysis/core.py b/marker_analysis/src/marker_analysis/core.py new file mode 100644 index 0000000..7d8d3ea --- /dev/null +++ b/marker_analysis/src/marker_analysis/core.py @@ -0,0 +1,63 @@ +from __future__ import annotations +import logging +from typing import List, Dict +from pydantic import BaseModel, Field, ValidationError + +logger = logging.getLogger(__name__) + + +class MarkerData(BaseModel): + """Repräsentiert ein einzelnes Marker-Ereignis aus der eBPF-Instrumentierung.""" + + marker_id: str = Field(..., description="Eindeutige ID des Marker-Ereignisses.") + timestamp: float = Field(..., description="Zeitstempel des Ereignisses in Sekunden.") + status: str = Field(..., description="Status, z. B. 'write_pre', 'write_post', 'read_between_steps'.") + + +class MarkerValidationError(Exception): + """Wird ausgelöst, wenn Marker-Daten ungültig sind.""" + pass + + +def validate_markers(marker_data: List[MarkerData]) -> Dict[str, int | float]: + """Validiert Marker-Daten auf Konsistenz (write_pre/write_post Paare).""" + + assert isinstance(marker_data, list), "marker_data muss eine Liste von MarkerData sein" + + try: + validated_markers = [MarkerData(**m.dict()) if isinstance(m, MarkerData) else MarkerData(**m) for m in marker_data] + except ValidationError as e: + logger.error("Validierung der MarkerData fehlgeschlagen: %s", e) + raise MarkerValidationError(f"Ungültige Marker-Daten: {e}") from e + + write_pre = {} + write_post = set() + retry_free_reads = 0 + + for m in validated_markers: + match m.status: + case 'write_pre': + write_pre[m.marker_id] = m.timestamp + case 'write_post': + write_post.add(m.marker_id) + case 'read_between_steps': + retry_free_reads += 1 + case _: + logger.debug("Unbekannter Markerstatus ignoriert: %s", m.status) + + valid_pairs = sum(1 for mid in write_pre if mid in write_post) + missing_post = sum(1 for mid in write_pre if mid not in write_post) + + total_events = len(validated_markers) + ratio_complete = valid_pairs / max(len(write_pre), 1) + + result = { + 'total_events': total_events, + 'valid_write_pairs': valid_pairs, + 'missing_post_markers': missing_post, + 'retry_free_reads': retry_free_reads, + 'pair_completion_ratio': round(ratio_complete, 3), + } + + logger.info("Marker-Validierung abgeschlossen: %s", result) + return result