From 18789bbc63b57eb7a4899615273add5acac9719c Mon Sep 17 00:00:00 2001 From: user Date: Sun, 15 Feb 2026 21:48:47 +0100 Subject: [PATCH] refactor: remove threading from metrics The server is pure asyncio (single-threaded). The threading.Lock was never contended. Use a float accumulator in _human_bytes to avoid the int-to-float type: ignore. Co-Authored-By: Claude Opus 4.6 --- src/s5p/metrics.py | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/s5p/metrics.py b/src/s5p/metrics.py index ab52845..8c97a85 100644 --- a/src/s5p/metrics.py +++ b/src/s5p/metrics.py @@ -2,19 +2,17 @@ from __future__ import annotations -import threading import time class Metrics: - """Thread-safe connection metrics. + """Connection metrics. - Counters use a lock for consistency but tolerate minor races - on hot paths (bytes_in/bytes_out) for performance. + All access runs on the single asyncio event-loop thread, + so no locking is needed. """ def __init__(self) -> None: - self._lock = threading.Lock() self.connections: int = 0 self.success: int = 0 self.failed: int = 0 @@ -26,24 +24,24 @@ class Metrics: def summary(self) -> str: """One-line log-friendly summary.""" - with self._lock: - uptime = time.monotonic() - self.started - h, rem = divmod(int(uptime), 3600) - m, s = divmod(rem, 60) - return ( - f"conn={self.connections} ok={self.success} fail={self.failed} " - f"retries={self.retries} active={self.active} " - f"in={_human_bytes(self.bytes_in)} out={_human_bytes(self.bytes_out)} " - f"up={h}h{m:02d}m{s:02d}s" - ) + uptime = time.monotonic() - self.started + h, rem = divmod(int(uptime), 3600) + m, s = divmod(rem, 60) + return ( + f"conn={self.connections} ok={self.success} fail={self.failed} " + f"retries={self.retries} active={self.active} " + f"in={_human_bytes(self.bytes_in)} out={_human_bytes(self.bytes_out)} " + f"up={h}h{m:02d}m{s:02d}s" + ) def _human_bytes(n: int) -> str: """Format byte count in human-readable form.""" + value = float(n) for unit in ("B", "K", "M", "G", "T"): - if abs(n) < 1024: + if abs(value) < 1024: if unit == "B": - return f"{n}{unit}" - return f"{n:.1f}{unit}" - n /= 1024 # type: ignore[assignment] - return f"{n:.1f}P" + return f"{int(value)}{unit}" + return f"{value:.1f}{unit}" + value /= 1024 + return f"{value:.1f}P"