这是一个批量整理提交,包含以下主要改动: 1. 删除多处冗余的空行和未使用的导入 2. 修复文件末尾缺少换行符的问题 3. 调整部分模块的导入顺序与代码排版 4. 修复部分配置默认值与策略逻辑 5. 新增多个功能模块与辅助工具 6. 完善异常处理与日志记录 7. 修复速率限制、消息缓存、权限校验等逻辑bug 8. 废弃部分旧有API与配置项并添加警告提示
80 lines
3.2 KiB
Python
80 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
import time
|
|
from collections import deque
|
|
from typing import Any
|
|
|
|
|
|
class NextcloudTalkMetrics:
|
|
def __init__(self, max_latency_samples: int = 100):
|
|
self._max_latency_samples = max_latency_samples
|
|
self._send_latencies: deque[float] = deque(maxlen=max_latency_samples)
|
|
self._receive_latencies: deque[float] = deque(maxlen=max_latency_samples)
|
|
self._send_count: int = 0
|
|
self._receive_count: int = 0
|
|
self._send_error_count: int = 0
|
|
self._receive_error_count: int = 0
|
|
self._circuit_breaker_trips: int = 0
|
|
self._started_at: float = time.time()
|
|
|
|
def record_send_success(self, latency_s: float) -> None:
|
|
self._send_latencies.append(latency_s)
|
|
self._send_count += 1
|
|
|
|
def record_send_error(self) -> None:
|
|
self._send_error_count += 1
|
|
|
|
def record_receive_success(self, latency_s: float) -> None:
|
|
self._receive_latencies.append(latency_s)
|
|
self._receive_count += 1
|
|
|
|
def record_receive_error(self) -> None:
|
|
self._receive_error_count += 1
|
|
|
|
def record_circuit_breaker_trip(self) -> None:
|
|
self._circuit_breaker_trips += 1
|
|
|
|
def snapshot(self) -> dict[str, Any]:
|
|
uptime_s = time.time() - self._started_at
|
|
|
|
send_latencies = list(self._send_latencies)
|
|
recv_latencies = list(self._receive_latencies)
|
|
|
|
avg_send = sum(send_latencies) / len(send_latencies) if send_latencies else None
|
|
avg_recv = sum(recv_latencies) / len(recv_latencies) if recv_latencies else None
|
|
|
|
return {
|
|
"uptime_seconds": round(uptime_s, 1),
|
|
"send": {
|
|
"count": self._send_count,
|
|
"error_count": self._send_error_count,
|
|
"avg_latency_ms": round(avg_send * 1000, 1) if avg_send is not None else None,
|
|
"p50_latency_ms": round(_percentile(send_latencies, 50) * 1000, 1) if send_latencies else None,
|
|
"p95_latency_ms": round(_percentile(send_latencies, 95) * 1000, 1) if send_latencies else None,
|
|
"p99_latency_ms": round(_percentile(send_latencies, 99) * 1000, 1) if send_latencies else None,
|
|
},
|
|
"receive": {
|
|
"count": self._receive_count,
|
|
"error_count": self._receive_error_count,
|
|
"avg_latency_ms": round(avg_recv * 1000, 1) if avg_recv is not None else None,
|
|
"p50_latency_ms": round(_percentile(recv_latencies, 50) * 1000, 1) if recv_latencies else None,
|
|
"p95_latency_ms": round(_percentile(recv_latencies, 95) * 1000, 1) if recv_latencies else None,
|
|
"p99_latency_ms": round(_percentile(recv_latencies, 99) * 1000, 1) if recv_latencies else None,
|
|
},
|
|
"circuit_breaker": {
|
|
"trip_count": self._circuit_breaker_trips,
|
|
},
|
|
}
|
|
|
|
|
|
def _percentile(data: list[float], percentile: float) -> float:
|
|
if not data:
|
|
return 0.0
|
|
sorted_data = sorted(data)
|
|
k = (len(sorted_data) - 1) * percentile / 100.0
|
|
f = int(k)
|
|
c = k - f
|
|
if f + 1 < len(sorted_data):
|
|
return sorted_data[f] + c * (sorted_data[f + 1] - sorted_data[f])
|
|
return sorted_data[f]
|