improved logging

This commit is contained in:
Ayzen
2026-06-06 00:52:52 +03:00
parent af6005d68f
commit aea49f6128
65 changed files with 1206 additions and 240 deletions
@@ -2,6 +2,7 @@
from __future__ import annotations
import logging
import mmap
from pathlib import Path
import struct
@@ -16,6 +17,8 @@ from python_app.orchestration.shm.decoder import (
decode_trace_collection,
)
logger = logging.getLogger(__name__)
_HEADER_SIZE: Final[int] = 64
_SLOT_HEADER_SIZE: Final[int] = 16
_MAGIC: Final[bytes] = b"RDRRING2"
@@ -43,6 +46,12 @@ class ShmRingReader:
# A fail-fast open (absent/incompatible ring) must not leak the fd/mapping.
self.close()
raise
logger.debug(
"Opened SHM ring reader %s (capacity=%d, slot_size=%d bytes)",
self._ring_name,
self.capacity,
self.slot_size_bytes,
)
def close(self) -> None:
"""Close mmap and file handle."""
@@ -50,6 +59,7 @@ class ShmRingReader:
self._mmap.close()
self._mmap = None
self._file.close()
logger.debug("Closed SHM ring reader %s", self._ring_name)
def pop_payload(self) -> bytes | None:
"""Read next payload from ring, or `None` if no unread payload exists."""
@@ -68,6 +78,7 @@ class ShmRingReader:
sequence = self._read_u64(slot_offset + 8)
if sequence != read_seq + 1:
# Producer overwrote this slot before we read it. Resync to latest.
logger.debug("Ring %s: slot lapped before read, resyncing to write_seq=%d", self._ring_name, write_seq)
self._write_u64(32, write_seq)
return None
@@ -75,6 +86,12 @@ class ShmRingReader:
# Bound payload_size against the slot before slicing so a torn/garbage size
# can never read out of the slot region; resync and skip on violation.
if payload_size > self.slot_size_bytes:
logger.debug(
"Ring %s: payload_size %d exceeds slot %d, resyncing",
self._ring_name,
payload_size,
self.slot_size_bytes,
)
self._write_u64(32, write_seq)
return None
@@ -84,6 +101,7 @@ class ShmRingReader:
# Re-read the slot sequence after the copy; if it changed, the producer
# overwrote this slot mid-copy and the payload is torn — discard and resync.
if self._read_u64(slot_offset + 8) != read_seq + 1:
logger.debug("Ring %s: slot overwritten mid-copy, discarding torn payload", self._ring_name)
self._write_u64(32, write_seq)
return None
@@ -158,6 +176,7 @@ class ShmRingReader:
return 0
dropped = int(write_seq - read_seq)
self._write_u64(32, write_seq)
logger.debug("Ring %s: dropped %d unread payload(s)", self._ring_name, dropped)
return dropped
@property
@@ -2,12 +2,15 @@
from __future__ import annotations
import logging
import mmap
import os
from pathlib import Path
import struct
from typing import Final
logger = logging.getLogger(__name__)
_HEADER_SIZE: Final[int] = 64
_SLOT_HEADER_SIZE: Final[int] = 16
_MAGIC: Final[bytes] = b"RDRRING2"
@@ -58,17 +61,26 @@ class ShmRingWriter:
# Wrong-sized stale segment: drop it entirely and recreate, so the file
# and any future mapping agree on geometry instead of being truncated
# under a producer/consumer that still expects the old layout.
if not created:
logger.info("Ring %s: stale segment with wrong size, recreating", self._ring_name)
self._file.truncate(self._mapped_size)
created = True
self._mmap = mmap.mmap(self._file.fileno(), self._mapped_size)
if created:
self._initialize_header()
logger.debug(
"Created SHM ring writer %s (capacity=%d, slot_size=%d bytes)",
self._ring_name,
self._capacity,
self._slot_size_bytes,
)
return
# Size matched but the header geometry/magic does not: the owner recreates
# rather than diverge. Unlink and reopen as a brand-new ring.
if not self._header_matches():
logger.warning("Ring %s: header/geometry mismatch on existing segment, recreating", self._ring_name)
self._mmap.close()
self._file.close()
self._unlink_if_present()
@@ -77,6 +89,8 @@ class ShmRingWriter:
self._file.truncate(self._mapped_size)
self._mmap = mmap.mmap(self._file.fileno(), self._mapped_size)
self._initialize_header()
else:
logger.debug("Reusing existing SHM ring writer %s", self._ring_name)
def _unlink_if_present(self) -> None:
"""Remove the backing /dev/shm file if it exists (owner-only operation)."""
@@ -89,6 +103,7 @@ class ShmRingWriter:
"""Close mmap and file handle."""
self._mmap.close()
self._file.close()
logger.debug("Closed SHM ring writer %s", self._ring_name)
def push(self, payload: bytes) -> bool:
"""Push one payload with overwrite-oldest semantics on overflow."""
@@ -98,6 +113,10 @@ class ShmRingWriter:
write_seq = self._read_u64(24)
read_seq = self._read_u64(32)
if max(0, write_seq - read_seq) >= self._capacity:
# Ring full: the consumer is not keeping up, so the oldest unread slot is
# overwritten (overwrite-oldest). Logged at DEBUG to avoid flooding the
# log when a backlog persists across many pushes.
logger.debug("Ring %s: full, overwriting oldest unread slot", self._ring_name)
# Advance the consumer cursor past the slot we are about to overwrite, but
# re-read it first and move it only forward: a concurrent reader may have
# already advanced it, and clobbering that backward would re-deliver an