# Observability(可观测性与打点载荷)|Tasks > 对应计划:`spec_kit/Personalized Reco/modules/observability/plan.md` > > 本清单执行原则: > > - Observability 只负责**统一 meta 结构与构建**,不负责埋点 SDK/落库/上报实现。 > - `RecoMeta` 必须可被 `reco-engine` 与 `integration-api-worker` 共同使用(同一结构、同一口径)。 --- ## 0. 任务标记规则 - 用勾选框标记执行状态: - `[ ]` 未开始 - `[x]` 已完成 - 每个任务都要求可独立验收(有明确产出/可运行的检查方式)。 --- ## 1. 文档对齐(先把口径写死,避免实现漂移) - [x] 1.1 校对 `modules/observability/spec.md` 与 `modules/observability/plan.md` 一致性 - **检查点**: - `RecoMeta` 必须字段集合一致(scene、candidate_pool_size_*、fallback_level_final、served_k、empty_reason、conf_U、missing_fields) - `empty_reason` 枚举与判定逻辑一致 - **验收**:两份文档无冲突;V1 的默认值/缺失策略写清楚。 --- ## 2. 目录与骨架(与推荐子模块同级) - [x] 2.1 新建目录 `server/app/features/personalized_reco/observability/` - **包含**: - `__init__.py` - `types.py`(`RecoMeta`、`MissingFields` 等 Pydantic 模型) - `utils.py`(`compute_empty_reason` 等纯函数) - `builder.py`(`RecoMetaBuilder`:逐阶段填充并 build) - **验收**:可通过 `app.features.personalized_reco.observability.*` 正常 import。 --- ## 3. 类型定义(稳定契约) - [x] 3.1 定义 `MissingFields`(布尔结构) - **字段**:`need/context/emotion` - **验收**:字段名与 `spec.md` 一致;序列化输出稳定。 - [x] 3.2 定义 `RecoMeta`(统一 meta 载荷) - **必须字段**: - `scene` - `candidate_pool_size_raw` - `candidate_pool_size_after_hard_filter` - `candidate_pool_size_after_dedup` - `candidate_pool_size_after_freqcap` - `fallback_level_final` - `served_k` - `empty_reason`(served_k=0 必填;served_k>0 可为 None) - `conf_U` - `missing_fields`(`MissingFields`) - **可选字段**: - `risk_filtered_count_by_flag` - `freqcap_filtered_counts` - `config_snapshot`(V1 可先不实现,仅预留字段) - **验收**:字段集合固定;可被 API/Celery 直接返回。 --- ## 4. 纯函数与判定逻辑(V1 写死) - [x] 4.1 实现 `compute_missing_fields(user_profile) -> MissingFields` - **规则**: - need:`user_profile.need` 为空对象 `{}` 或不存在 - context:`user_profile.context` 为空对象 `{}` 或不存在 - emotion:`user_profile.emotion_score` 为 `null`/不存在 - **验收**:单测覆盖三种缺失情况与全不缺失情况。 - [x] 4.2 实现 `compute_empty_reason(...) -> str | None` - **规则**(对齐 plan): - served_k>0 → None - raw==0 → `pool_empty` - raw>0 且 after_hard_filter==0 → `hard_filter_all` - after_freqcap==0 → `freqcap_all` - 其他 → `unknown` - **验收**:单测覆盖所有分支。 --- ## 5. Builder(在 pipeline 中逐阶段填充) - [x] 5.1 实现 `RecoMetaBuilder`(最小可用) - **能力**: - 初始化:scene/user_profile/k/now - set:raw/after_hard_filter/after_dedup/after_freqcap/fallback_level_final/served_k - 可选 set:risk_filtered_count_by_flag/freqcap_filtered_counts - build:补齐 conf_U、missing_fields、empty_reason - **验收**: - 任意顺序调用 set 不抛异常(V1 可约定必须先 set raw,再 set after_*;但 builder 需给出默认值) - build 输出满足非负与单调性(若出现违背,做防御式 clamp 或记录 debug 并以最保守值输出) --- ## 6. 单元测试(pytest) - [x] 6.1 新建测试文件 `server/tests/test_observability.py` - **用例覆盖**: - empty_reason 判定所有分支 - missing_fields 判定 - builder build 输出字段集合稳定 - 单调性约束:输入异常时 builder 的防御策略生效(不输出负数) - **验收**:`pytest -q tests/test_observability.py` 通过。 --- ## 7. 最终自检清单(合入前) - [x] 7.1 文档一致性检查 - **验收**:`spec.md` / `plan.md` / `RecoMeta` 类型字段一致。 - [x] 7.2 全量测试通过 - **命令**(在 `server/`): - `pytest -q` - **验收**:所有用例通过。 - [x] 7.3 全部完成后更新大规范 `overview.md` - **变更点**: - 将 `modules/observability/` 标记为“已实施” - 增加一条变更记录(日期 + 交付物:plan/tasks/代码/测试) - **验收**:`spec_kit/Personalized Reco/overview.md` 中模块状态与交付记录准确。