Files
Genarrative/docs/technical/ANALYTICS_DATE_DIMENSION_IMPLEMENTATION_2026-05-04.md
历冰郁-hermes版 1d9d8c2e41
Some checks failed
CI / verify (push) Has been cancelled
feat: add analytics metric granularity query
2026-05-04 16:29:48 +08:00

11 KiB
Raw Blame History

Analytics Date Dimension 与个人任务埋点范围收口记录2026-05-04

背景

本记录用于收口 .hermes/plans/2026-05-04_022223-analytics-time-dimension-mapping.md 中当前阶段已经落地的内容,并明确尚未执行的后续范围。

本阶段目标不是完整上线运营统计查询,而是先完成两件基础工作:

  1. 收紧个人任务系统的埋点范围,避免运营或接口把个人任务错误配置为 sitemodulework 等非用户维度。
  2. 新增统一日期维表 analytics_date_dimension,为后续按周、月、季、年聚合埋点数据提供稳定的日期 bucket 映射。

当前已完成范围

1. 个人任务埋点范围锁定为 User

当前个人任务系统首版只支持用户维度埋点。

已完成:

  • Admin 任务配置页不再展示“埋点范围”选择。
  • Admin 保存任务配置时固定传 scopeKind: 'user'
  • API 层拒绝非 user 的个人任务配置。
  • 领域输入构造层拒绝非 User 的个人任务配置。
  • Work => user_id 的错误映射已移除。
  • 任务进度刷新、任务中心快照、领奖链路遇到非 User 的异常个人任务配置时显式报错,不再静默按 0 进度处理。

相关文件:

apps/admin-web/src/pages/AdminTaskConfigPage.tsx
apps/admin-web/src/api/adminApiTypes.ts
server-rs/crates/api-server/src/runtime_profile.rs
server-rs/crates/module-runtime/src/commands.rs
server-rs/crates/module-runtime/src/errors.rs
server-rs/crates/spacetime-module/src/runtime/profile.rs

2. 日期维表领域模型与纯函数

已在 module-runtime 中补充日期维表快照和纯函数。

日期维表使用现有北京时间业务日 day_key 语义:

date_key = floor((occurred_at_micros + 8h) / 1d)

已完成能力:

  • YYYY-MM-DD 解析业务日 date_key
  • date_key 构造日期维表快照。
  • 生成 ISO weekday周一=1周日=7。
  • 生成 ISO week keyYYYYWW,跨年周按 ISO week-year。
  • 生成 week/month/quarter/year 的 key 和起止 date_key
  • 限制日期维表支持范围为:
    • 2000-01-01
    • 2100-12-31

相关文件:

server-rs/crates/module-runtime/src/domain.rs
server-rs/crates/module-runtime/src/application.rs
server-rs/crates/module-runtime/src/lib.rs

3. SpacetimeDB 日期维表与 reducer

已新增 SpacetimeDB 表:

analytics_date_dimension

表字段包括:

date_key
calendar_date
weekday
iso_week_key
week_start_date_key
week_end_date_key
month_key
month_start_date_key
month_end_date_key
quarter_key
quarter_start_date_key
quarter_end_date_key
year_key
year_start_date_key
year_end_date_key
created_at
updated_at

已新增索引:

iso_week_key
month_key
quarter_key
year_key

已新增 reducer

ensure_analytics_date_dimension_for_date
seed_analytics_date_dimensions

当前 reducer 行为:

  • ensure 单日幂等补齐。
  • seed 按日期范围幂等补齐。
  • seed 拒绝 start_date > end_date
  • seed 单次最多允许 ANALYTICS_DATE_DIMENSION_MAX_SEED_DAYS = 3660 天。
  • date_key 进入 ensure 前先做支持范围校验,避免极端整数进入日历算法。

相关文件:

server-rs/crates/spacetime-module/src/runtime/analytics_date_dimension.rs
server-rs/crates/spacetime-module/src/runtime/mod.rs
server-rs/crates/spacetime-module/src/migration.rs
docs/technical/SPACETIMEDB_TABLE_CATALOG.md

4. SpacetimeDB Rust client bindings

已按项目脚本生成 Rust bindings并在生成参数中显式包含 private tables/functions

PATH="/tmp/spacetime-bin:$PATH" npm run spacetime:generate -- --rust-only

本次已修改生成脚本:

scripts/generate-spacetime-bindings.mjs

spacetime generate 参数中加入:

--include-private

说明SpacetimeDB CLI 2.1.0 的参数名是 --include-private,不是 --non-private。该参数含义是将 private tables/functions 也包含进生成代码,满足 api-server 通过 Rust bindings 访问 module private table/reducer 的需求。

spacetimedb tool version 2.1.0; spacetimedb-lib version 2.1.0

生成脚本:

scripts/generate-spacetime-bindings.mjs

已新增 analytics date dimension 相关 bindings

server-rs/crates/spacetime-client/src/module_bindings/analytics_date_dimension_ensure_input_type.rs
server-rs/crates/spacetime-client/src/module_bindings/analytics_date_dimension_seed_input_type.rs
server-rs/crates/spacetime-client/src/module_bindings/analytics_date_dimension_type.rs
server-rs/crates/spacetime-client/src/module_bindings/analytics_date_dimension_table.rs
server-rs/crates/spacetime-client/src/module_bindings/ensure_analytics_date_dimension_for_date_reducer.rs
server-rs/crates/spacetime-client/src/module_bindings/seed_analytics_date_dimensions_reducer.rs

并更新了:

server-rs/crates/spacetime-client/src/module_bindings/mod.rs

注意:

  • analytics_date_dimension 表当前是 private table由于生成脚本已加 --include-private,本次 codegen 已生成 analytics_date_dimension_table.rs,可通过 ctx.db.analytics_date_dimension() 访问 client cache / query builder。
  • bindings 目录是自动生成产物,本次以项目脚本整体刷新,除新增 analytics 文件外,也带来了大量已存在 table/reducer/procedure 文件的格式化/生成器输出差异。

5. 测试覆盖

已新增测试:

server-rs/crates/module-runtime/tests/analytics_date_dimension.rs
server-rs/crates/module-runtime/tests/profile_task_scope.rs
server-rs/crates/shared-contracts/tests/profile_task_contract.rs

覆盖重点:

  • 2024-02-29 闰年。
  • 2025-12-29 ISO week 跨年。
  • 2026-01-01 跨年周。
  • 2026-03-31 Q1 结束。
  • 2026-04-01 Q2 开始。
  • 2026-12-31 年末。
  • 非法日期解析失败。
  • 超出日期维表支持范围失败。
  • 个人任务 scopeKind=user 成功。
  • 个人任务 scopeKind=site/module/work 失败。
  • work scope 不会静默映射到 user_id
  • Admin 个人任务配置 contract 保持 scopeKind: user

已验证命令

server-rs/ 执行:

cargo fmt -p module-runtime -p spacetime-module -p spacetime-client
cargo test -p spacetime-client --no-run
cargo test -p spacetime-module --no-run
cargo test -p module-runtime --test analytics_date_dimension
cargo test -p module-runtime --test profile_task_scope
cargo test -p shared-contracts --test profile_task_contract

从项目根目录执行:

npm run admin-web:typecheck

当前结果:

  • spacetime-client --no-run 编译通过。
  • spacetime-module --no-run 编译通过。
  • analytics_date_dimension 测试通过8 passed。
  • profile_task_scope 测试通过3 passed。
  • profile_task_contract 测试通过2 passed。
  • admin-web:typecheck 通过。

已知非本阶段阻塞:

  • 完整运行 cargo test -p spacetime-module 时,曾出现既有 puzzle 测试失败:
puzzle::tests::puzzle_preview_is_publishable_with_complete_draft FAILED
assertion failed: preview.publish_ready

该失败与当前埋点范围和日期维表改动无直接关系,本阶段以 cargo test -p spacetime-module --no-run 作为编译门禁。

当前未完成 / 暂缓项

1. 暂未新增 spacetime-client facade

当前没有新增:

SpacetimeClient::ensure_analytics_date_dimension_for_date
SpacetimeClient::seed_analytics_date_dimensions

原因:

  • 生成脚本已加入 --include-privateprivate reducer/type/table bindings 已可用于后续 facade 实现。
  • 但 Step 7/8/9 暂缓,尚未由 api-server 或统计查询链路调用该能力。
  • 如后续只是 SpacetimeDB module 内部写入统计时 ensure可以直接复用 module 内部 helper不一定需要远程 client facade。
  • 若后续需要由 API 或运维接口触发 seed/ensure可基于本次已生成的 reducer bindings 再补 facade。

2. Step 7/8/9 暂缓

本阶段未接入:

  • 事件写入链路自动 ensure 日期维表。
  • 聚合查询 API 的 granularity = day | week | month | quarter | year
  • shared contracts / 前端 analytics contracts。
  • 历史事件回填。

这些应作为后续阶段单独设计和落地。

后续建议顺序

  1. 如需提交本阶段改动,确认是否接受 module_bindings 整体刷新带来的大量生成文件 diff。
  2. 如希望 diff 更小,可评估仅提交 analytics date dimension 相关生成文件与 mod.rs;但需要非常谨慎,因为 module_bindings 是自动生成产物。
  3. 如需要由 api-server 触发 seed/ensure再补 spacetime-client facade。
  4. 进入 Step 7/8/9事件写入链路、聚合查询 API、前端 contracts。

Step 7/8/9 后续接入记录2026-05-04

本次继续推进此前暂缓的 Step 7/8/9 中“按日期维度聚合查询 API / contracts / client facade”部分。

已新增能力

  1. module-runtime 新增 analytics metric 聚合领域类型与纯函数:

    • AnalyticsGranularity = day | week | month | quarter | year
    • AnalyticsMetricQueryInput
    • AnalyticsBucketMetric
    • AnalyticsMetricQueryResponse
    • aggregate_runtime_tracking_daily_stats(...)
  2. spacetime-module 新增 query_analytics_metric procedure直接聚合 tracking daily stat输出按 bucket 排序的统计结果。

  3. spacetime-client 新增 facade

SpacetimeClient::query_analytics_metric(event_key, scope_kind, scope_id, granularity)
  1. api-server 新增登录态接口:
GET /api/profile/analytics/metric?eventKey=...&scopeKind=user&scopeId=...&granularity=day

请求参数:

参数 说明
eventKey 埋点事件 key必填
scopeKind `site
scopeId 对应范围 ID必填
granularity `day

响应 data

type AnalyticsMetricQueryResponse = {
  buckets: Array<{
    bucketKey: string;
    bucketStartDateKey: number;
    bucketEndDateKey: number;
    value: number;
  }>;
};
  1. shared contracts / 前端 shared contracts 已新增 analytics query 类型:
    • AnalyticsMetricQueryRequest
    • AnalyticsMetricQueryResponse
    • AnalyticsBucketMetricResponse / AnalyticsBucketMetric
    • AnalyticsGranularity

本次验证

server-rs/ 执行通过:

cargo test -p module-runtime --test analytics_granularity
cargo check -p spacetime-module
cargo check -p spacetime-client
cargo check -p api-server

验证结果:

  • analytics_granularity 测试通过3 passed。
  • spacetime-module 编译通过,仅存在既有 dead_code warnings。
  • spacetime-client 编译通过。
  • api-server 编译通过,仅存在既有 prompt dead_code warnings。

注意事项

当前环境未检测到 spacetime / spacetimedb CLI因此 analytics metric 相关 module_bindings 是按现有生成物结构手动补齐的临时生成物。后续有 CLI 的开发机应优先通过项目脚本重新生成 bindings并复核手写生成物是否可被正式生成输出覆盖。


阶段结论

当前阶段已经完成“个人任务埋点范围收紧”和“日期维表 module 侧能力”的核心落地,并已生成 SpacetimeDB Rust client bindings。

剩余工作不再是 bindings 环境阻塞,而是后续业务接入范围:是否增加 spacetime-client facade以及是否继续推进事件写入链路、聚合查询 API 和前端 analytics contracts。