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 <noreply@anthropic.com>
This commit is contained in:
user
2026-02-15 21:48:47 +01:00
parent 210d3539f1
commit 18789bbc63

View File

@@ -2,19 +2,17 @@
from __future__ import annotations from __future__ import annotations
import threading
import time import time
class Metrics: class Metrics:
"""Thread-safe connection metrics. """Connection metrics.
Counters use a lock for consistency but tolerate minor races All access runs on the single asyncio event-loop thread,
on hot paths (bytes_in/bytes_out) for performance. so no locking is needed.
""" """
def __init__(self) -> None: def __init__(self) -> None:
self._lock = threading.Lock()
self.connections: int = 0 self.connections: int = 0
self.success: int = 0 self.success: int = 0
self.failed: int = 0 self.failed: int = 0
@@ -26,24 +24,24 @@ class Metrics:
def summary(self) -> str: def summary(self) -> str:
"""One-line log-friendly summary.""" """One-line log-friendly summary."""
with self._lock: uptime = time.monotonic() - self.started
uptime = time.monotonic() - self.started h, rem = divmod(int(uptime), 3600)
h, rem = divmod(int(uptime), 3600) m, s = divmod(rem, 60)
m, s = divmod(rem, 60) return (
return ( f"conn={self.connections} ok={self.success} fail={self.failed} "
f"conn={self.connections} ok={self.success} fail={self.failed} " f"retries={self.retries} active={self.active} "
f"retries={self.retries} active={self.active} " f"in={_human_bytes(self.bytes_in)} out={_human_bytes(self.bytes_out)} "
f"in={_human_bytes(self.bytes_in)} out={_human_bytes(self.bytes_out)} " f"up={h}h{m:02d}m{s:02d}s"
f"up={h}h{m:02d}m{s:02d}s" )
)
def _human_bytes(n: int) -> str: def _human_bytes(n: int) -> str:
"""Format byte count in human-readable form.""" """Format byte count in human-readable form."""
value = float(n)
for unit in ("B", "K", "M", "G", "T"): for unit in ("B", "K", "M", "G", "T"):
if abs(n) < 1024: if abs(value) < 1024:
if unit == "B": if unit == "B":
return f"{n}{unit}" return f"{int(value)}{unit}"
return f"{n:.1f}{unit}" return f"{value:.1f}{unit}"
n /= 1024 # type: ignore[assignment] value /= 1024
return f"{n:.1f}P" return f"{value:.1f}P"