add logging

This commit is contained in:
awe
2026-01-29 17:05:47 +03:00
parent 23cff76dd2
commit 508c835368

View File

@ -222,10 +222,11 @@ class SerialLineSource:
class SerialChunkReader: class SerialChunkReader:
"""Быстрое неблокирующее чтение чанков из serial/raw TTY для максимального дренажа буфера.""" """Быстрое неблокирующее чтение чанков из serial/raw TTY для максимального дренажа буфера."""
def __init__(self, src: SerialLineSource): def __init__(self, src: SerialLineSource, error_counter: Optional[list] = None):
self._src = src self._src = src
self._ser = src._pyserial self._ser = src._pyserial
self._fd: Optional[int] = None self._fd: Optional[int] = None
self._error_counter = error_counter # Список с 1 элементом для передачи по ссылке
if self._ser is not None: if self._ser is not None:
# Неблокирующий режим для быстрой откачки # Неблокирующий режим для быстрой откачки
try: try:
@ -248,11 +249,15 @@ class SerialChunkReader:
try: try:
n = int(getattr(self._ser, "in_waiting", 0)) n = int(getattr(self._ser, "in_waiting", 0))
except Exception: except Exception:
if self._error_counter:
self._error_counter[0] += 1
n = 0 n = 0
if n > 0: if n > 0:
try: try:
return self._ser.read(n) return self._ser.read(n)
except Exception: except Exception:
if self._error_counter:
self._error_counter[0] += 1
return b"" return b""
return b"" return b""
if self._fd is None: if self._fd is None:
@ -269,6 +274,8 @@ class SerialChunkReader:
except BlockingIOError: except BlockingIOError:
break break
except Exception: except Exception:
if self._error_counter:
self._error_counter[0] += 1
break break
return bytes(out) return bytes(out)
@ -297,6 +304,12 @@ class SweepReader(threading.Thread):
self._n_valid_hist = deque() self._n_valid_hist = deque()
# Счетчик потерь данных (выброшенных свипов из-за переполнения очереди) # Счетчик потерь данных (выброшенных свипов из-за переполнения очереди)
self._dropped_sweeps: int = 0 self._dropped_sweeps: int = 0
# Диагностика потери точек внутри свипа
self._total_lines_received: int = 0 # Всего принято строк с данными
self._total_parse_errors: int = 0 # Ошибок парсинга строк
self._total_empty_lines: int = 0 # Пустых строк
self._max_buf_size: int = 0 # Максимальный размер буфера парсинга
self._read_errors: int = 0 # Ошибок чтения из порта
def _finalize_current(self, xs, ys): def _finalize_current(self, xs, ys):
if not xs: if not xs:
@ -381,6 +394,10 @@ class SweepReader(threading.Thread):
"std": std, "std": std,
"dt_ms": dt_ms, "dt_ms": dt_ms,
"dropped": self._dropped_sweeps, "dropped": self._dropped_sweeps,
"lines": self._total_lines_received,
"parse_err": self._total_parse_errors,
"read_err": self._read_errors,
"max_buf": self._max_buf_size,
} }
# Кладём готовый свип (если очередь полна — выбрасываем самый старый) # Кладём готовый свип (если очередь полна — выбрасываем самый старый)
@ -412,12 +429,19 @@ class SweepReader(threading.Thread):
try: try:
# Быстрый неблокирующий дренаж порта с разбором по байтам # Быстрый неблокирующий дренаж порта с разбором по байтам
chunk_reader = SerialChunkReader(self._src) # Передаем счетчик ошибок чтения как список для изменения по ссылке
error_counter = [0]
chunk_reader = SerialChunkReader(self._src, error_counter)
buf = bytearray() buf = bytearray()
while not self._stop.is_set(): while not self._stop.is_set():
data = chunk_reader.read_available() data = chunk_reader.read_available()
# Обновляем счетчик ошибок чтения
self._read_errors = error_counter[0]
if data: if data:
buf += data buf += data
# Отслеживаем максимальный размер буфера парсинга
if len(buf) > self._max_buf_size:
self._max_buf_size = len(buf)
else: else:
# Короткая уступка CPU, если нет новых данных (уменьшена до 0.1ms) # Короткая уступка CPU, если нет новых данных (уменьшена до 0.1ms)
time.sleep(0.0001) time.sleep(0.0001)
@ -433,6 +457,7 @@ class SweepReader(threading.Thread):
if line.endswith(b"\r"): if line.endswith(b"\r"):
line = line[:-1] line = line[:-1]
if not line: if not line:
self._total_empty_lines += 1
continue continue
if line.startswith(b"Sweep_start"): if line.startswith(b"Sweep_start"):
@ -449,9 +474,17 @@ class SweepReader(threading.Thread):
x = int(parts[1], 10) x = int(parts[1], 10)
y = int(parts[2], 10) # поддержка знака: "+…" и "-…" y = int(parts[2], 10) # поддержка знака: "+…" и "-…"
except Exception: except Exception:
self._total_parse_errors += 1
continue continue
xs.append(x) xs.append(x)
ys.append(y) ys.append(y)
self._total_lines_received += 1
else:
# Строка не в формате "s X Y"
self._total_parse_errors += 1
else:
# Строка слишком короткая
self._total_parse_errors += 1
# Защита от переполнения буфера при отсутствии переводов строки (снижен порог) # Защита от переполнения буфера при отсутствии переводов строки (снижен порог)
if len(buf) > 262144: if len(buf) > 262144: