Skip to content

Commit 6793dda

Browse files
committed
feat(analytics): 埋点迁到 Java 后端 /analytics/events
Vercel Fluid CPU 用到 85%,原因是前端 /api/analytics 每次埋点都跑 Next function 做 resolveUserId + Prisma 直写。现改为走 next.config 已有的 /analytics/:path* rewrite 直转 Java,Vercel 只做 edge 代理不跑 function。 前端改动: - lib/analytics.ts: URL /api/analytics → /analytics/events,header x-satoken → satoken - 删除 app/api/analytics/route.ts(Prisma 直写逻辑搬到 Java) 配套后端改动(另开 PR): - AnalyticsController 加 POST /events - 新增 AnalyticsEventIngestService 用 JdbcTemplate INSERT - SaTokenConfigure 白名单放行 /analytics/events(匿名也收) AnalyticsEvent 表保留:GA4 走 top-docs,这张表暂无读取方但 未来自建 dashboard / 登录用户精细追踪可直接复用。
1 parent d9c86e8 commit 6793dda

2 files changed

Lines changed: 10 additions & 41 deletions

File tree

app/api/analytics/route.ts

Lines changed: 0 additions & 32 deletions
This file was deleted.

lib/analytics.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,30 @@ function getStoredToken(): string | null {
1313
}
1414

1515
/**
16-
* 向 Next.js 内置 /api/analytics 发送埋点事件。
17-
* 失败静默,不抛异常,不影响用户主流程。
16+
* 向后端 /analytics/events 上报埋点事件。
17+
*
18+
* 历史:之前走 Next.js 路由 /api/analytics 做 Prisma 直写,占用 Vercel Fluid CPU;
19+
* 现改为走 next.config 的 /analytics/:path* rewrite 直接转发到 Java 后端,
20+
* Next 这一层只做 edge 代理不跑 function,CPU 用量显著降低。
1821
*
19-
* Header 命名注意:/api/analytics 的 resolveUserId 从 `x-satoken` 读取 token(见 lib/server-auth.ts),
20-
* 然后在内部再以 `satoken` header 转发给后端 /auth/me 验证。所以客户端 → Next 这一跳必须用 `x-satoken`,
21-
* 否则 userId 永远解析不到,埋点记录的 uniqueUsers 会恒为 0。
22+
* Header 约定:Java 后端 SaToken 读取 `satoken` header 识别登录用户,匿名也会放行。
23+
* 失败静默,不抛异常,不影响用户主流程。
2224
*/
2325
export async function trackEvent(
2426
eventType: string,
2527
eventData?: Record<string, unknown>,
2628
): Promise<void> {
2729
try {
2830
const token = getStoredToken();
29-
// 用 Record<string, string> 而不是 HeadersInit(联合类型),保证可变 + 类型安全
3031
const headers: Record<string, string> = {
3132
"Content-Type": "application/json",
3233
};
33-
// 客户端 → Next 路由必须用 x-satoken(见上方注释)
34+
// 登录用户附带 satoken,后端用它解析 userId;匿名时不加 header,后端按 userId=null 记录
3435
if (token) {
35-
headers["x-satoken"] = token;
36+
headers["satoken"] = token;
3637
}
3738

38-
await fetch("/api/analytics", {
39+
await fetch("/analytics/events", {
3940
method: "POST",
4041
headers,
4142
body: JSON.stringify({ eventType, eventData: eventData ?? {} }),

0 commit comments

Comments
 (0)