64 lines
2.5 KiB
Python
64 lines
2.5 KiB
Python
"""运行指标收集(线程安全,零依赖)。"""
|
|
from __future__ import annotations
|
|
|
|
import threading
|
|
from collections import Counter, deque
|
|
from typing import Any, Deque, Dict
|
|
|
|
|
|
class Stats:
|
|
def __init__(self, window: int = 1000):
|
|
self._lock = threading.Lock()
|
|
self.requests = 0
|
|
self.domain_counter: Counter = Counter()
|
|
self.difficulty_counter: Counter = Counter()
|
|
self.upgraded = 0
|
|
self.cache_hits = 0
|
|
self.cache_levels: Counter = Counter()
|
|
self.errors = 0
|
|
self.latencies: Deque[float] = deque(maxlen=window)
|
|
self.cost_total = 0.0
|
|
self.model_usage: Counter = Counter()
|
|
|
|
def record(self, latency_ms: float, domain: str, difficulty: str,
|
|
upgraded: bool, cache_hit: bool, cache_level: str | None,
|
|
cost_est: float, model_used: str):
|
|
with self._lock:
|
|
self.requests += 1
|
|
self.domain_counter[domain] += 1
|
|
self.difficulty_counter[difficulty] += 1
|
|
if upgraded:
|
|
self.upgraded += 1
|
|
if cache_hit:
|
|
self.cache_hits += 1
|
|
if cache_level:
|
|
self.cache_levels[cache_level] += 1
|
|
self.latencies.append(latency_ms)
|
|
self.cost_total += cost_est
|
|
self.model_usage[model_used] += 1
|
|
|
|
def record_error(self):
|
|
with self._lock:
|
|
self.errors += 1
|
|
|
|
def summary(self) -> Dict[str, Any]:
|
|
with self._lock:
|
|
n = self.requests
|
|
lat = list(self.latencies)
|
|
avg_lat = sum(lat) / len(lat) if lat else 0.0
|
|
p99 = sorted(lat)[int(len(lat) * 0.99) - 1] if len(lat) >= 100 else (max(lat) if lat else 0.0)
|
|
return {
|
|
"total_requests": n,
|
|
"domain_distribution": dict(self.domain_counter),
|
|
"difficulty_distribution": dict(self.difficulty_counter),
|
|
"fallback_rate": round(self.upgraded / n, 4) if n else 0.0,
|
|
"upgraded_requests": self.upgraded,
|
|
"cache_hit_rate": round(self.cache_hits / n, 4) if n else 0.0,
|
|
"cache_levels": dict(self.cache_levels),
|
|
"avg_latency_ms": round(avg_lat, 3),
|
|
"p99_latency_ms": round(p99, 3),
|
|
"total_cost_est_usd": round(self.cost_total, 6),
|
|
"model_usage": dict(self.model_usage),
|
|
"errors": self.errors,
|
|
}
|
|
|