"""客户端埋点上报接口。 POST /api/v1/analytics/events — 批量接收新手引导(及后续)埋点,append 落 analytics_event 表。 **不强制登录**(未登录态也要采集行为):user_id 由客户端在 body 里可选带上,不靠 Bearer。 服务端补 client_ip(X-Forwarded-For)与 created_at(接收时间 = server_at)。 """ from __future__ import annotations from fastapi import APIRouter, Request from app.api.deps import DbSession from app.repositories import analytics as analytics_repo from app.schemas.analytics import AnalyticsBatchIn, AnalyticsIngestOut router = APIRouter(prefix="/api/v1/analytics", tags=["analytics"]) def _client_ip(request: Request) -> str: """取客户端 IP:生产经 nginx 反代优先 X-Forwarded-For 第一段,否则直连 IP(同 admin get_client_ip)。""" xff = request.headers.get("x-forwarded-for") if xff: return xff.split(",")[0].strip() return request.client.host if request.client else "" @router.post("/events", response_model=AnalyticsIngestOut, summary="批量上报埋点事件") def ingest_events( batch: AnalyticsBatchIn, request: Request, db: DbSession ) -> AnalyticsIngestOut: n = analytics_repo.record_batch(db, batch, client_ip=_client_ip(request)) return AnalyticsIngestOut(received=n)