feat(observe): main.py 挂中间件 + lifespan 启停上报 worker
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+10
@@ -50,6 +50,11 @@ from app.core.heartbeat_monitor_worker import (
|
|||||||
stop_heartbeat_monitor,
|
stop_heartbeat_monitor,
|
||||||
)
|
)
|
||||||
from app.core.logging import setup_logging
|
from app.core.logging import setup_logging
|
||||||
|
from app.core.observe import RequestMetricsMiddleware
|
||||||
|
from app.core.observe_worker import (
|
||||||
|
start_observe_worker,
|
||||||
|
stop_observe_worker,
|
||||||
|
)
|
||||||
from app.core.pricebot_client import aclose_pricebot_client, get_pricebot_client
|
from app.core.pricebot_client import aclose_pricebot_client, get_pricebot_client
|
||||||
from app.core.withdraw_reconcile_worker import (
|
from app.core.withdraw_reconcile_worker import (
|
||||||
start_withdraw_reconcile_worker,
|
start_withdraw_reconcile_worker,
|
||||||
@@ -74,12 +79,14 @@ async def lifespan(_: FastAPI) -> AsyncIterator[None]:
|
|||||||
reconcile_task = start_withdraw_reconcile_worker()
|
reconcile_task = start_withdraw_reconcile_worker()
|
||||||
heartbeat_task = start_heartbeat_monitor()
|
heartbeat_task = start_heartbeat_monitor()
|
||||||
daily_exchange_task = start_daily_exchange_worker()
|
daily_exchange_task = start_daily_exchange_worker()
|
||||||
|
observe_task = start_observe_worker()
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
await stop_heartbeat_monitor(heartbeat_task)
|
await stop_heartbeat_monitor(heartbeat_task)
|
||||||
await stop_withdraw_reconcile_worker(reconcile_task)
|
await stop_withdraw_reconcile_worker(reconcile_task)
|
||||||
await stop_daily_exchange_worker(daily_exchange_task)
|
await stop_daily_exchange_worker(daily_exchange_task)
|
||||||
|
await stop_observe_worker(observe_task)
|
||||||
await aclose_pricebot_client()
|
await aclose_pricebot_client()
|
||||||
logger.info("shutting down")
|
logger.info("shutting down")
|
||||||
|
|
||||||
@@ -101,6 +108,9 @@ if settings.cors_origins_list:
|
|||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 接口指标埋点(放在 CORS 之后 = 最外层:测到含 CORS 的完整耗时)。未配置观测时中间件自 no-op。
|
||||||
|
app.add_middleware(RequestMetricsMiddleware)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/health", tags=["meta"])
|
@app.get("/health", tags=["meta"])
|
||||||
def health() -> dict[str, str]:
|
def health() -> dict[str, str]:
|
||||||
|
|||||||
@@ -225,3 +225,10 @@ async def test_stop_flushes_remaining_and_closes_client(monkeypatch):
|
|||||||
|
|
||||||
assert b'"n"' in posted["body"] # 关停时把剩余事件发了出去
|
assert b'"n"' in posted["body"] # 关停时把剩余事件发了出去
|
||||||
assert observe_worker._client is None # client 已关闭并置空
|
assert observe_worker._client is None # client 已关闭并置空
|
||||||
|
|
||||||
|
|
||||||
|
def test_app_has_metrics_middleware():
|
||||||
|
from app.main import app
|
||||||
|
|
||||||
|
names = [m.cls.__name__ for m in app.user_middleware]
|
||||||
|
assert "RequestMetricsMiddleware" in names
|
||||||
|
|||||||
Reference in New Issue
Block a user