11from collections import defaultdict
2+ import datetime
23import ssl
34import anyio
45import anyio .abc
89import uvicorn
910import tianxiu2b2t .anyio .streams as streams
1011from tianxiu2b2t .anyio import concurrency
12+ from tianxiu2b2t .utils import runtime
1113
1214from . import utils , abc
1315from .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+
3882app = fastapi .FastAPI (
3983 redoc_url = None ,
4084 docs_url = None ,
@@ -45,6 +89,7 @@ def __exit__(self, *args):
4589tls_listener : streams .AutoTLSListener | None = None
4690forwards : dict [tuple [str , int ], tuple [str , int ]] = {}
4791forwards_count : defaultdict [tuple [str , int ], int ] = defaultdict (int )
92+ query_per_second_statistics = QueryPerSecondStatistics ()
4893
4994async def get_free_port ():
5095 listener = await anyio .create_tcp_listener ()
0 commit comments