Files
Neo-ZQYY/scripts/ops/gen_integration_report.py
Neo b25308c3f4 feat: P1-P3 全栈集成 — 数据库基础 + DWS 扩展 + 小程序鉴权 + 工程化体系
## P1 数据库基础
- zqyy_app: 创建 auth/biz schema、FDW 连接 etl_feiqiu
- etl_feiqiu: 创建 app schema RLS 视图、商品库存预警表
- 清理 assistant_abolish 残留数据

## P2 ETL/DWS 扩展
- 新增 DWS 助教订单贡献度表 (dws.assistant_order_contribution)
- 新增 assistant_order_contribution_task 任务及 RLS 视图
- member_consumption 增加充值字段、assistant_daily 增加处罚字段
- 更新 ODS/DWD/DWS 任务文档及业务规则文档
- 更新 consistency_checker、flow_runner、task_registry 等核心模块

## P3 小程序鉴权系统
- 新增 xcx_auth 路由/schema(微信登录 + JWT)
- 新增 wechat/role/matching/application 服务层
- zqyy_app 鉴权表迁移 + 角色权限种子数据
- auth/dependencies.py 支持小程序 JWT 鉴权

## 文档与审计
- 新增 DOCUMENTATION-MAP 文档导航
- 新增 7 份 BD_Manual 数据库变更文档
- 更新 DDL 基线快照(etl_feiqiu 6 schema + zqyy_app auth)
- 新增全栈集成审计记录、部署检查清单更新
- 新增 BACKLOG 路线图、FDW→Core 迁移计划

## Kiro 工程化
- 新增 5 个 Spec(P1/P2/P3/全栈集成/核心业务)
- 新增审计自动化脚本(agent_on_stop/build_audit_context/compliance_prescan)
- 新增 6 个 Hook(合规检查/会话日志/提交审计等)
- 新增 doc-map steering 文件

## 运维与测试
- 新增 ops 脚本:迁移验证/API 健康检查/ETL 监控/集成报告
- 新增属性测试:test_dws_contribution / test_auth_system
- 清理过期 export 报告文件
- 更新 .gitignore 排除规则
2026-02-26 08:03:53 +08:00

256 lines
8.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 生成 ETL 全流程联调综合报告
# 输出路径:{SYSTEM_LOG_ROOT}/{date}__etl_integration_report.md
# 环境变量 SYSTEM_LOG_ROOT 缺失时报错终止。
# 用法cd C:\NeoZQYY && python scripts/ops/gen_integration_report.py
import os
import sys
from pathlib import Path
from dotenv import load_dotenv
# 加载根 .env
load_dotenv(Path(__file__).resolve().parents[2] / ".env")
SYSTEM_LOG_ROOT = os.environ.get("SYSTEM_LOG_ROOT")
if not SYSTEM_LOG_ROOT:
print("ERROR: 环境变量 SYSTEM_LOG_ROOT 未设置,无法输出报告。", file=sys.stderr)
sys.exit(1)
output_dir = Path(SYSTEM_LOG_ROOT)
output_dir.mkdir(parents=True, exist_ok=True)
REPORT_DATE = "2026-02-24"
output_path = output_dir / f"{REPORT_DATE}__etl_integration_report.md"
# ── 报告内容 ──────────────────────────────────────────────────────────────────
REPORT = r"""# ETL 全流程联调报告
> 生成时间2026-02-24
> execution_id: `41938155-db8c-4eec-9b81-9e5aef42fb8a`
> run_uuid: `f764a42487c34e0f9bd19e4fa9c57f03`
---
## 1. 执行概要
| 项目 | 值 |
|------|-----|
| Flow | `api_full`API → ODS → DWD → DWS → INDEX |
| 处理模式 | `full_window`(全窗口) |
| 时间窗口 | 2025-11-01 ~ 2026-02-20自定义 |
| 窗口切分 | 30 天/切片,共 4 个切片 |
| force_full | 是 |
| 任务数 | 41 个常用任务(`is_common=True` |
| 开始时间 | 2026-02-24 12:27:22 |
| 结束时间 | 2026-02-24 13:05:43 |
| 总耗时 | 38m22s |
| 退出码 | 0 |
| 最终状态 | **success** |
| 数据统计 | 225,760 fetched / 13,437 inserted / 225,648 updated |
### 窗口切片
| 切片 | 窗口范围 |
|------|---------|
| 1 | 2025-10-31 22:00 ~ 2025-11-30 22:00 |
| 2 | 2025-11-30 22:00 ~ 2025-12-30 22:00 |
| 3 | 2025-12-30 22:00 ~ 2026-01-29 22:00 |
| 4 | 2026-01-29 22:00 ~ 2026-02-20 02:00 |
---
## 2. 性能报告
### 2.1 阶段耗时汇总
| 阶段 | 墙钟耗时 | 占比 | 状态 |
|------|---------|------|------|
| ODS | 31m17s | 81.8% | ✅ 全部成功21 任务 + 1 跳过) |
| DWD | 2m30s | 6.5% | ✅ 全部成功1 任务) |
| DWS | 4m29s | 11.7% | ⚠️ 7 成功 / 8 失败 |
| INDEX | <1s | 0.0% | ❌ 3 任务全部失败(级联) |
| **合计** | **38m16s** | **100%** | 29 成功 / 11 失败 / 1 跳过 |
### 2.2 Top-5 耗时瓶颈
| 排名 | 任务 | 阶段 | 耗时 | 备注 |
|------|------|------|------|------|
| 1 | ODS_PLATFORM_COUPON | ODS | 10m41s | 数据量大4 切片均 >2m |
| 2 | ODS_TABLE_USE | ODS | 4m23s | 每切片 ~1m |
| 3 | ODS_GROUP_BUY_REDEMPTION | ODS | 4m22s | 每切片 ~1m |
| 4 | ODS_PAYMENT | ODS | 4m7s | 每切片 ~1m |
| 5 | DWS_ASSISTANT_DAILY | DWS | 2m43s | 聚合计算密集 |
> Top-5 合计 26m16s占总耗时 68.6%。ODS 阶段 API 拉取是主要瓶颈。
### 2.3 ODS 任务耗时明细
| 任务 | 切片数 | 总耗时 | 状态 |
|------|--------|--------|------|
| ODS_PLATFORM_COUPON | 4 | 10m41s | ✅ |
| ODS_TABLE_USE | 4 | 4m23s | ✅ |
| ODS_GROUP_BUY_REDEMPTION | 4 | 4m22s | ✅ |
| ODS_PAYMENT | 4 | 4m7s | ✅ |
| ODS_MEMBER_BALANCE | 4 | 2m8s | ✅ |
| ODS_SETTLEMENT_RECORDS | 4 | 1m45s | ✅ |
| ODS_TABLE_FEE_DISCOUNT | 4 | 54s | ✅ |
| ODS_INVENTORY_CHANGE | 4 | 48s | ✅ |
| ODS_MEMBER_CARD | 4 | 35s | ✅ |
| ODS_ASSISTANT_LEDGER | 4 | 24s | ✅ |
| ODS_MEMBER | 4 | 14s | ✅ |
| ODS_INVENTORY_STOCK | 4 | 9s | ✅ |
| ODS_ASSISTANT_ACCOUNT | 4 | 7s | ✅ |
| ODS_STORE_GOODS | 4 | 7s | ✅ |
| ODS_REFUND | 4 | 4s | ✅ |
| ODS_RECHARGE_SETTLE | 4 | 4s | ✅ |
| ODS_TENANT_GOODS | 4 | 4s | ✅ |
| ODS_TABLES | 4 | 2s | ✅ |
| ODS_GROUP_PACKAGE | 4 | 2s | ✅ |
| ODS_GOODS_CATEGORY | 4 | 1s | ✅ |
| ODS_STORE_GOODS_SALES | 4 | 1s | ✅ |
| ODS_ASSISTANT_ABOLISH | — | — | ⏭️ 跳过(未启用) |
### 2.4 DWD 任务耗时明细
| 任务 | 切片数 | 总耗时 | 状态 |
|------|--------|--------|------|
| DWD_LOAD_FROM_ODS | 4 | 2m30s | ✅ |
### 2.5 DWS 任务耗时明细
| 任务 | 切片数 | 总耗时 | 状态 |
|------|--------|--------|------|
| DWS_ASSISTANT_DAILY | 4 | 2m43s | ✅ |
| DWS_ASSISTANT_CUSTOMER | 4 | 1m32s | ✅ |
| DWS_GOODS_STOCK_MONTHLY | 4 | 1s | ✅ |
| DWS_BUILD_ORDER_SUMMARY | 0 | 1s | ✅ |
| DWS_GOODS_STOCK_DAILY | 4 | <1s | ✅ |
| DWS_GOODS_STOCK_WEEKLY | 4 | <1s | ✅ |
| DWS_ASSISTANT_SALARY | 4 | <1s | ✅ |
| DWS_MEMBER_CONSUMPTION | — | — | ❌ 失败(根因) |
| DWS_MEMBER_VISIT | — | — | ❌ 级联失败 |
| DWS_FINANCE_DAILY | — | — | ❌ 级联失败 |
| DWS_FINANCE_RECHARGE | — | — | ❌ 级联失败 |
| DWS_FINANCE_INCOME_STRUCTURE | — | — | ❌ 级联失败 |
| DWS_FINANCE_DISCOUNT_DETAIL | — | — | ❌ 级联失败 |
| DWS_ASSISTANT_MONTHLY | — | — | ❌ 级联失败 |
| DWS_ASSISTANT_FINANCE | — | — | ❌ 级联失败 |
### 2.6 INDEX 任务耗时明细
| 任务 | 状态 |
|------|------|
| DWS_WINBACK_INDEX | ❌ 级联失败 |
| DWS_NEWCONV_INDEX | ❌ 级联失败 |
| DWS_RELATION_INDEX | ❌ 级联失败 |
---
## 3. DEBUG 报告
### 3.1 错误摘要
共发现 **1 个根因错误**,导致 **10 个任务级联失败**。
### 3.2 WARNINGODS_ASSISTANT_ABOLISH 未启用
- **级别**:低优先级
- **现象**:日志输出 `ODS_ASSISTANT_ABOLISH 未启用或不存在`
- **原因**:任务注册表中该任务标记为 `is_common=False`(非活跃),但仍在全选列表中
- **影响**:无,任务被正常跳过
- **建议**:无需处理,属于预期行为
### 3.3 ROOT CAUSEDWS_MEMBER_CONSUMPTION 失败
**根因分析**:两个 BUG 叠加导致任务失败。
#### BUG-1FDW 外部表未部署
- **现象**:查询 `fdw_app.member_birthday_manual` 时报错(外部表不存在)
- **原因**`db/fdw/setup_fdw_reverse.sql` 中定义的反向 FDW 外部表未在测试库部署
- **影响**:主 SQL 执行失败,触发 rollback进入 `sql_fallback` 分支
#### BUG-2sql_fallback 列名错误
- **现象**fallback SQL 引用了不存在的列 `tenant_member_id`
- **原因**:实际列名应为 `member_id`fallback SQL 未与表结构同步
- **影响**fallback 也失败,事务进入 `InFailedSqlTransaction` 状态
### 3.4 CASCADE FAILURE10 个任务级联失败
- **触发点**DWS_MEMBER_CONSUMPTION 失败后,数据库连接的事务处于 `InFailedSqlTransaction` 状态
- **根因**`run_tasks` 的 `except` 块未调用 `self.db.rollback()`,导致后续所有任务在同一个已失败的事务中执行
- **级联任务**(共 10 个):
1. DWS_MEMBER_VISIT
2. DWS_FINANCE_DAILY
3. DWS_FINANCE_RECHARGE
4. DWS_FINANCE_INCOME_STRUCTURE
5. DWS_FINANCE_DISCOUNT_DETAIL
6. DWS_ASSISTANT_MONTHLY
7. DWS_ASSISTANT_FINANCE
8. DWS_WINBACK_INDEX
9. DWS_NEWCONV_INDEX
10. DWS_RELATION_INDEX
### 3.5 修复建议
| 优先级 | 修复项 | 说明 |
|--------|--------|------|
| **P0** | 修复 SQL 列名 | `tenant_member_id` → `member_id`DWS_MEMBER_CONSUMPTION 的 sql_fallback |
| **P0** | run_tasks except 块添加 rollback | `self.db.rollback()` 防止级联失败 |
| **P1** | 部署 FDW 外部表 | 执行 `db/fdw/setup_fdw_reverse.sql` 到测试库 |
---
## 4. 黑盒测试报告
> ⏳ 待补充 — 将在 Task 5.3 完成后追加。
>
> 预期内容:
> - API vs ODS通过数/总数
> - ODS vs DWD通过数/总数
> - DWD vs DWS表概览
> - 白名单差异统计
> - 失败表清单
> - 全链路检查报告路径引用
---
## 附录
### A. 完整 CLI 参数
```
--flow api_full
--processing-mode full_window
--window-start 2025-11-01
--window-end 2026-02-20
--window-split day
--window-split-days 30
--force-full
--tasks ODS_ASSISTANT_ACCOUNT ODS_ASSISTANT_LEDGER ODS_ASSISTANT_ABOLISH
ODS_SETTLEMENT_RECORDS ODS_TABLE_USE ODS_TABLE_FEE_DISCOUNT
ODS_TABLES ODS_PAYMENT ODS_REFUND ODS_PLATFORM_COUPON
ODS_MEMBER ODS_MEMBER_CARD ODS_MEMBER_BALANCE ODS_RECHARGE_SETTLE
ODS_GROUP_PACKAGE ODS_GROUP_BUY_REDEMPTION
ODS_INVENTORY_STOCK ODS_INVENTORY_CHANGE
ODS_GOODS_CATEGORY ODS_STORE_GOODS ODS_STORE_GOODS_SALES ODS_TENANT_GOODS
DWD_LOAD_FROM_ODS
DWS_BUILD_ORDER_SUMMARY DWS_ASSISTANT_DAILY DWS_ASSISTANT_MONTHLY
DWS_ASSISTANT_CUSTOMER DWS_ASSISTANT_SALARY DWS_ASSISTANT_FINANCE
DWS_MEMBER_CONSUMPTION DWS_MEMBER_VISIT
DWS_FINANCE_DAILY DWS_FINANCE_RECHARGE DWS_FINANCE_INCOME_STRUCTURE
DWS_FINANCE_DISCOUNT_DETAIL
DWS_GOODS_STOCK_DAILY DWS_GOODS_STOCK_WEEKLY DWS_GOODS_STOCK_MONTHLY
DWS_WINBACK_INDEX DWS_NEWCONV_INDEX DWS_RELATION_INDEX
```
### B. 精细计时报告
完整的窗口切片级计时数据见:`export/temp_timing_report.md`
"""
output_path.write_text(REPORT.strip(), encoding="utf-8")
print(f"✅ 报告已生成: {output_path}")