667cda566f
新手引导埋点的服务端: - 表 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>
53 lines
1.9 KiB
Python
53 lines
1.9 KiB
Python
"""admin 埋点日志:列表 + 按事件 / 设备 / 用户 / 会话 / 时间筛选(只读,同库直接查 analytics_event)。"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from typing import Annotated
|
|
|
|
from fastapi import APIRouter, Depends, Query
|
|
|
|
from app.admin.deps import AdminDb, get_current_admin
|
|
from app.admin.repositories import queries
|
|
from app.admin.schemas.analytics import AnalyticsEventOut
|
|
from app.admin.schemas.common import CursorPage
|
|
|
|
router = APIRouter(
|
|
prefix="/admin/api/event-logs",
|
|
tags=["admin-event-logs"],
|
|
dependencies=[Depends(get_current_admin)],
|
|
)
|
|
|
|
|
|
@router.get("", response_model=CursorPage[AnalyticsEventOut], summary="埋点日志列表")
|
|
def list_event_logs(
|
|
db: AdminDb,
|
|
event: Annotated[str | None, Query(max_length=64)] = None,
|
|
device_id: Annotated[str | None, Query(max_length=64)] = None,
|
|
user_id: Annotated[int | None, Query()] = None,
|
|
session_id: Annotated[str | None, Query(max_length=64)] = None,
|
|
created_from: Annotated[datetime | None, Query()] = None,
|
|
created_to: Annotated[datetime | None, Query()] = None,
|
|
sort_by: Annotated[str, Query(pattern="^(id|created_at)$")] = "id",
|
|
sort_order: Annotated[str, Query(pattern="^(asc|desc)$")] = "desc",
|
|
limit: Annotated[int, Query(ge=1, le=100)] = 20,
|
|
cursor: Annotated[int | None, Query()] = None,
|
|
) -> CursorPage[AnalyticsEventOut]:
|
|
items, next_cursor, total = queries.list_analytics_events(
|
|
db,
|
|
event=event,
|
|
device_id=device_id,
|
|
user_id=user_id,
|
|
session_id=session_id,
|
|
created_from=created_from,
|
|
created_to=created_to,
|
|
sort_by=sort_by,
|
|
sort_order=sort_order,
|
|
limit=limit,
|
|
cursor=cursor,
|
|
)
|
|
return CursorPage(
|
|
items=[AnalyticsEventOut.model_validate(e) for e in items],
|
|
next_cursor=next_cursor,
|
|
total=total,
|
|
)
|