"""验证遥测口径、有界内存和请求关联,防止监控干扰业务及泄漏原始地址。""" from datetime import datetime, timedelta from fastapi import FastAPI from fastapi.testclient import TestClient from app.core.monitoring import REQUEST_ID, MonitorMiddleware, Recorder, merge_metrics def test_合并直方图计算P95且四百不计系统错误(): recorder = Recorder() at = datetime(2026, 11, 2, 10) for status, elapsed in [(200, 10), (400, 100), (403, 200), (500, 750)]: recorder.record("GET", "/items/{id}", status, elapsed, "r", at=at) result = merge_metrics(recorder.metrics()[at].values()) assert (result["count"], result["errors_4xx"], result["errors_5xx"]) == (4, 2, 1) assert result["error_rate"] == 25 assert result["p95_ms"] == 750 assert merge_metrics([])["p95_ms"] is None def test_中间件生成编号使用模板排除自身且不读取正文(): app, recorder = FastAPI(), Recorder() app.add_middleware(MonitorMiddleware, recorder=recorder) @app.get("/items/{id}") def item(id: str): return {"request_id": REQUEST_ID.get()} @app.get("/api/v1/system/monitor/overview") def monitor(): return {} client = TestClient(app) response = client.get("/items/private-id?token=never-record") assert response.headers["x-request-id"] == response.json()["request_id"] client.get("/api/v1/system/monitor/overview") client.get("/private-route") values = next(iter(recorder.metrics().values())) assert set(values) == {("GET", "/items/{id}"), ("GET", "/__unmatched__")} assert "private" not in str(recorder.metrics()) assert REQUEST_ID.get() == "-" def test_内存分钟路由和事件队列均有界(): recorder = Recorder() at = datetime(2026, 11, 2, 10) for i in range(2100): recorder.record("GET", f"/route/{i}", 500, 1, str(i), at=at) assert len(recorder.events) == 2000 and recorder.dropped_events == 100 assert len(recorder.metrics()[at]) == 201 for i in range(11): recorder.record("GET", "/ok", 200, 1, "r", at=at + timedelta(minutes=i)) assert len(recorder.metrics()) == 10 def test_遥测内部失败不改变业务响应(monkeypatch): app, recorder = FastAPI(), Recorder() app.add_middleware(MonitorMiddleware, recorder=recorder) @app.get("/ok") def ok(): return {"ok": True} def broken(*args, **kwargs): raise RuntimeError("synthetic-recorder-failure") monkeypatch.setattr(recorder, "record", broken) response = TestClient(app).get("/ok") assert response.status_code == 200 and response.json() == {"ok": True}