ForcePilot/backend/package/yuxi/channels/adapters/nextcloudtalk/metrics.py
Kris 1f78c44b03 refactor: 整理并清理项目中的冗余代码与格式问题
这是一个批量整理提交,包含以下主要改动:
1.  删除多处冗余的空行和未使用的导入
2.  修复文件末尾缺少换行符的问题
3.  调整部分模块的导入顺序与代码排版
4.  修复部分配置默认值与策略逻辑
5.  新增多个功能模块与辅助工具
6.  完善异常处理与日志记录
7.  修复速率限制、消息缓存、权限校验等逻辑bug
8.  废弃部分旧有API与配置项并添加警告提示
2026-05-12 14:51:53 +08:00

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]