9354588ba2
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
41 lines
1.4 KiB
Python
41 lines
1.4 KiB
Python
"""接口指标埋点:有界事件队列 + 纯 ASGI 中间件。
|
|
|
|
每个 HTTP 请求测总耗时、抓路由模板 + 状态码,非阻塞塞进有界队列;由 observe_worker
|
|
后台批量上报到 OpenObserve。请求路径上无任何 I/O。未配置观测时中间件直接透传。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
|
|
from app.core.config import settings
|
|
|
|
# 有界事件队列(懒创建,见 get_queue):首次取用时在运行中的 loop 里建,避免 import 期
|
|
# 无 loop 的边角问题;put_nowait/get_nowait 不需运行中的 loop → 可在无 loop 下测试。
|
|
_queue: asyncio.Queue[dict] | None = None
|
|
# 队列满时的丢弃计数,worker 定期取出打日志。
|
|
_dropped = 0
|
|
|
|
|
|
def get_queue() -> asyncio.Queue[dict]:
|
|
"""返回全局有界事件队列(懒创建)。测试可 monkeypatch 模块级 _queue 换成小队列。"""
|
|
global _queue
|
|
if _queue is None:
|
|
_queue = asyncio.Queue(maxsize=settings.OBSERVE_QUEUE_MAX)
|
|
return _queue
|
|
|
|
|
|
def take_dropped() -> int:
|
|
"""取出并清零累计丢弃数(供 worker 打点)。"""
|
|
global _dropped
|
|
n, _dropped = _dropped, 0
|
|
return n
|
|
|
|
|
|
def record_event(event: dict) -> None:
|
|
"""非阻塞入队;队列满则丢弃当前事件并计数。永不抛异常、永不阻塞请求。"""
|
|
global _dropped
|
|
try:
|
|
get_queue().put_nowait(event)
|
|
except asyncio.QueueFull:
|
|
_dropped += 1
|