feat(analytics): 埋点事件接收接口 + admin 查询接口 + 埋点表 (#81)
新手引导埋点的服务端: - 表 analytics_event(五维硬性列 + props JSON 扩展字段;event/device_id/user_id/session_id/created_at 带索引) - POST /api/v1/analytics/events:客户端批量上报(不鉴权、body 读可选 user_id、补 client_ip + server_at) - admin GET /admin/api/event-logs:列表 + 按 事件/设备/用户/会话/时间 筛选(offset 分页,照 list_feedbacks) - alembic migration 建表(autogenerate 顺带检出的 ad/cps 历史索引漂移已手动剔除) app 主后端 :8770 与 admin :8771 共用同一 SQLite,admin 同库直接查、无需跨库。 配套客户端五维上报 + admin 日志页(另两仓库 PR)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: zzhyyyyy <2685922758@qq.com> Reviewed-on: #81 Co-authored-by: zhuzihao <zhuzihao@wonderable.ai> Co-committed-by: zhuzihao <zhuzihao@wonderable.ai>
This commit was merged in pull request #81.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
"""客户端埋点上报接口。
|
||||
|
||||
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)
|
||||
Reference in New Issue
Block a user