From bf63c7c1a95635dbd6b6609efc49d57a7e695650 Mon Sep 17 00:00:00 2001 From: malmert Date: Sun, 3 May 2026 19:52:49 +0200 Subject: [PATCH] try overload fix timestamp null error --- backend/src/utilities/database.py | 21 +++++++++++++++++++++ backend/src/utilities/ebpf_bridge_events.py | 3 +++ backend/src/utilities/packet_tracker.py | 18 +++++++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/backend/src/utilities/database.py b/backend/src/utilities/database.py index 5780363..e38eb16 100644 --- a/backend/src/utilities/database.py +++ b/backend/src/utilities/database.py @@ -20,6 +20,10 @@ from src.Models.packets import PacketDBModel logger = logging.getLogger("packet_capture") +def _utcnow() -> datetime: + return datetime.now(timezone.utc) + + def _db_text(value: Any) -> Any: if value is None: return None @@ -168,6 +172,9 @@ def _derive_flow_id(payload: Dict[str, Any]) -> Optional[str]: def _attach_derived_fields(payload: Dict[str, Any]) -> None: + if payload.get("timestamp") in (None, ""): + payload["timestamp"] = _utcnow() + flow_id = _derive_flow_id(payload) if flow_id is not None: current_flow_id = payload.get("flow_id") @@ -228,6 +235,20 @@ class DatabasePool: max_size=self._max_size, ) async with self._pool.acquire() as conn: + await conn.execute( + """ + DO $$ + BEGIN + IF to_regclass('packets') IS NOT NULL THEN + UPDATE packets + SET timestamp = COALESCE(updated_at, NOW()) + WHERE timestamp IS NULL; + END IF; + END $$; + """ + ) + await conn.execute("ALTER TABLE IF EXISTS packets ALTER COLUMN timestamp SET DEFAULT NOW()") + await conn.execute("ALTER TABLE IF EXISTS packets ALTER COLUMN timestamp SET NOT NULL") await conn.execute( """ ALTER TABLE IF EXISTS packets diff --git a/backend/src/utilities/ebpf_bridge_events.py b/backend/src/utilities/ebpf_bridge_events.py index c7b5ce2..e96e5bb 100644 --- a/backend/src/utilities/ebpf_bridge_events.py +++ b/backend/src/utilities/ebpf_bridge_events.py @@ -13,6 +13,7 @@ import signal import socket import subprocess import sys +from datetime import datetime, timezone from pathlib import Path from typing import Iterable @@ -504,6 +505,8 @@ def _build_payload(event: Event) -> dict[str, object] | None: payload: dict[str, object] = { "event_type": _event_name(int(event.event_type)), + "timestamp": datetime.now(timezone.utc).isoformat(), + "kernel_ts_ns": int(event.ts_ns), "iface": iface, "skb_mark": int(event.skb_mark) or None, "length": int(event.length), diff --git a/backend/src/utilities/packet_tracker.py b/backend/src/utilities/packet_tracker.py index 18461e6..c87a4cf 100644 --- a/backend/src/utilities/packet_tracker.py +++ b/backend/src/utilities/packet_tracker.py @@ -53,6 +53,18 @@ def _parse_observation_timestamp(value: Any) -> datetime: return datetime.max.replace(tzinfo=timezone.utc) +def _coerce_payload_timestamp(value: Any) -> datetime: + if isinstance(value, datetime): + return value if value.tzinfo is not None else value.replace(tzinfo=timezone.utc) + if value not in (None, ""): + try: + parsed = datetime.fromisoformat(str(value).replace("Z", "+00:00")) + return parsed if parsed.tzinfo is not None else parsed.replace(tzinfo=timezone.utc) + except Exception: + pass + return _utcnow() + + def _bridge_af_packet_observation_groups(payload: Dict[str, Any]) -> Dict[str, set[str]]: groups: Dict[str, set[str]] = {} observations = payload.get("capture_observations") or [] @@ -269,6 +281,10 @@ class PacketTracker: payload["skb_mark"] = event.get("skb_mark") or payload.get("skb_mark") payload["telemetry_metadata"] = event payload["last_observed_at"] = now_ts + event_timestamp = _coerce_payload_timestamp(event.get("timestamp")) + current_timestamp = payload.get("timestamp") + if current_timestamp in (None, "") or event_timestamp < _coerce_payload_timestamp(current_timestamp): + payload["timestamp"] = event_timestamp self._add_capture_source(payload, "telemetry") self._add_capture_observation( payload, @@ -336,7 +352,7 @@ class PacketTracker: return { "correlation_key": correlation_key, "payload": { - "timestamp": None, + "timestamp": _utcnow(), "correlation_key": correlation_key, "correlation_source": None, "packet_id": None,