8000 feat: 增加统计 qps api · TTB-Network/python-openbmclapi@874c532 · GitHub
[go: up one dir, main page]

Skip to content

Commit 874c532

Browse files
committed
feat: 增加统计 qps api
1 parent 01998b4 commit 874c532

File tree

4 files changed

+55
-3
lines changed

4 files changed

+55
-3
lines changed

core/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ def access_log(request: fastapi.Request, response: fastapi.Response, total_time:
226226
)
227227

228228
@web.app.middleware("http")
229-
async def auth_middleware(request: fastapi.Request, call_next):
229+
async def access_log_middleware(request: fastapi.Request, call_next):
230+
web.query_per_second_statistics.add()
230231
start_time = runtime.get_perf_counter_ns()
231232
try:
232233
result = await call_next(request)

core/dashboard.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from collections import defaultdict
2-
from typing import Any
2+
from typing import Any, Optional
33
import anyio
44
from bson import ObjectId
55
import fastapi
66
from fastapi.staticfiles import StaticFiles
77

88
from .config import ROOT_PATH, DEBUG
9+
from .web import query_per_second_statistics
910

1011

1112
class StreamNotice:
@@ -51,6 +52,12 @@ def _():
5152
@app.get("/api/receive")
5253
async def _(request: fastapi.Request):
5354
return notice.add_client(request)
55+
56+
@app.get("/api/qps")
57+
async def _(request: fastapi.Request, interval: Optional[int] = 5):
58+
if interval is None:
59+
return query_per_second_statistics.get_all()
60+
return query_per_second_statistics.merge_data(interval)
5461

5562
@app.get("/")
5663
@app.get("/{page}")

core/storage/alist.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ async def _check(self):
114114

115115
async def check_measure(self, size: int):
116116
path = str(self._path / "measure" / size)
117-
print(path)
118117
async with aiohttp.ClientSession(
119118
base_url=self._endpoint,
120119
headers={

core/web.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from collections import defaultdict
2+
import datetime
23
import ssl
34
import anyio
45
import anyio.abc
@@ -8,6 +9,7 @@
89
import uvicorn
910
import tianxiu2b2t.anyio.streams as streams
1011
from tianxiu2b2t.anyio import concurrency
12+
from tianxiu2b2t.utils import runtime
1113

1214
from . import utils, abc
1315
from .logger import logger
@@ -35,6 +37,48 @@ def __exit__(self, *args):
3537
del forwards[self.sockname]
3638
del forwards_count[self.sockname]
3739

40+
class QueryPerSecondStatistics:
41+
def __init__(
42+
self,
43+
expires: int = 600
44+
):
45+
self._timer = lambda: runtime.monotonic()
46+
self._data: defaultdict[int, int] = defaultdict(int)
47+
self._expires = expires
48+
49+
50+
def add(self):
51+
self._data[int(self._timer())] += 1
52+
self.expire()
53+
54+
def expire(self):
55+
t = self._timer()
56+
for k, v in list(self._data.items()):
57+
if k + self._expires < t:
58+
del self._data[k]
59+
60+
def get_all(self) -> dict[datetime.datetime, int]:
61+
now = datetime.datetime.now().replace(microsecond=0)
62+
t = self._timer()
63+
data = {}
64+
for k, v in self._data.items():
65+
if k >= t:
66+
continue
67+
data[(now - datetime.timedelta(seconds=t - k)).replace(microsecond=0)] += v
68+
return data
69+
70+
def merge_data(self, interval: int = 5) -> dict[datetime.datetime, int]:
71+
timestamp = datetime.datetime.fromtimestamp(datetime.datetime.now().timestamp() // interval * interval)
72+
res: defaultdict[datetime.datetime, int] = defaultdict(int)
73+
cur = int(self._timer() // interval)
74+
for k, v in self._data.items():
75+
c = int(k // interval)
76+
if c > cur:
77+
continue
78+
res[timestamp + datetime.timedelta(seconds=c * interval)] += v
79+
return res
80+
81+
3882
app = fastapi.FastAPI(
3983
redoc_url=None,
4084
docs_url=None,
@@ -45,6 +89,7 @@ def __exit__(self, *args):
4589
tls_listener: streams.AutoTLSListener | None = None
4690
forwards: dict[tuple[str, int], tuple[str, int]] = {}
4791
forwards_count: defaultdict[tuple[str, int], int] = defaultdict(int)
92+
query_per_second_statistics = QueryPerSecondStatistics()
4893

4994
async def get_free_port():
5095
listener = await anyio.create_tcp_listener()

0 commit comments

Comments
 (0)
0