Files
Neo-ZQYY/docs/deployment/EXPORT-PATHS.md
Neo 2a7a5d68aa feat: 2026-04-15~04-20 累积变更基线 — 多主线合流
主线 1: rns1-customer-coach-api + 04-miniapp-core-business 后端实施
  - 新增 GET /xcx/coaches/{id}/banner 轻量接口
  - performance/records 加 coach_id 参数 + view_board_coach 权限分流
  - coach/customer/performance/board/task 服务层重构
  - fdw_queries 结算单粒度聚合 + consumption_summary 视图统一
  - task_generator 回访宽限 72h + UPSERT 替代策略 + Step 5 保底清理
  - recall_detector settle_type=3 双重限制 + 门店级 resolved

主线 2: 小程序权限分流 + 新增 coach-service-records 管理者视角业绩明细页
  - perf-progress 共享模块去重 task-list/coach-detail 动画逻辑
  - isScattered 散客标记端到端
  - foodDetail/phoneFull/creator* 字段透传

主线 3: P19 指数回测框架 Phase 1+2
  - 3 个指数表 stat_date 日快照模式
  - 新增 DWS_INDEX_BACKFILL / DWS_TASK_SIMULATION 工具任务
  - task_engine 升级 HTTP 实时 + 推演回测双模式

主线 4: Core 维度层启用
  - 新增 CORE_DIM_SYNC 任务(DWD → core 4 维度表)
  - 修复 app 视图空查询问题

主线 5: member_project_tag 改为 LAST_30_VISITS 消费次数窗口

主线 6: 2 个迁移 SQL 已执行(stat_date + member_project_tag 新窗口)
  - schema 基线与 DDL 快照同步

主线 7: 开发机路径迁移 C:\NeoZQYY → C:\Project\NeoZQYY(约 95% 改动量)

附带: 新建运维脚本(churned_customer_report / simulate_historical_tasks /
      backfill_index_snapshots)+ tools/task-analysis/ 任务分析工具

合计 157 文件。未包含中间产物(tmp/ .playwright-mcp/ inspect-* excel/sheet 分析 txt)。
审计记录见下一个 commit。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 06:32:07 +08:00

348 lines
14 KiB
Markdown
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.
# Export 输出路径规范
> 最后更新2026-03-23
> 本文档描述 `export/` 目录的统一结构、各子目录用途、对应的 `.env` 变量、以及代码中的读取方式。
---
## 目录总览
```
export/
├── ETL-Connectors/feiqiu/
│ ├── JSON/ — API 原始 JSON 导出ODS 抓取落盘)
│ ├── LOGS/ — ETL 运行日志(每次 run 一个 .log
│ └── REPORTS/ — ETL 质检/完整性报告JSON 格式)
├── SYSTEM/
│ ├── LOGS/ — 系统级运维日志(预留)
│ ├── REPORTS/
│ │ ├── dataflow_analysis/ — 数据流结构分析报告Markdown + 采集中间产物)
│ │ ├── field_audit/ — 字段排查报告Markdown
│ │ └── full_dataflow_doc/ — 全链路数据流文档Markdown
│ └── CACHE/
│ └── api_samples/ — API 样本缓存24h 有效gen_full_dataflow_doc 使用)
├── BACKEND/
│ ├── LOGS/ — 后端结构化日志(预留,待 5.3 后端日志改造后启用)
│ └── avatars/ — 用户头像文件({user_id}.jpg覆盖式保存
└── dev-trace-logs/ — 开发调试全链路日志DevTrace 模块)
└── YYYY-MM-DD/ — 按日期分子目录
└── trace_YYYY-MM-DD_HH.jsonl — 按小时分文件JSON Lines
```
> 服务器部署时不保留 `export/`(通过 `setup-server-git.py` 排除),仅开发机留存。
> 服务器的输出路径由各环境 `.env` 独立配置,指向 `repo/export/` 下对应子目录。
---
## 环境变量与目录映射
| 环境变量 | 默认值(开发机) | 对应目录 | 说明 |
|----------|------------------|----------|------|
| `EXPORT_ROOT` | `C:/Project/NeoZQYY/export/ETL-Connectors/feiqiu/JSON` | `ETL-Connectors/feiqiu/JSON/` | ODS 抓取 JSON 落盘根目录 |
| `LOG_ROOT` | `C:/Project/NeoZQYY/export/ETL-Connectors/feiqiu/LOGS` | `ETL-Connectors/feiqiu/LOGS/` | ETL 运行日志 |
| `FETCH_ROOT` | `C:/Project/NeoZQYY/export/ETL-Connectors/feiqiu/JSON` | `ETL-Connectors/feiqiu/JSON/` | FETCH_ONLY 模式 JSON 输出(通常与 EXPORT_ROOT 相同) |
| `ETL_REPORT_ROOT` | `C:/Project/NeoZQYY/export/ETL-Connectors/feiqiu/REPORTS` | `ETL-Connectors/feiqiu/REPORTS/` | ETL 质检/完整性报告 |
| `SYSTEM_ANALYZE_ROOT` | `C:/Project/NeoZQYY/export/SYSTEM/REPORTS/dataflow_analysis` | `SYSTEM/REPORTS/dataflow_analysis/` | 数据流结构分析报告 |
| `FIELD_AUDIT_ROOT` | `C:/Project/NeoZQYY/export/SYSTEM/REPORTS/field_audit` | `SYSTEM/REPORTS/field_audit/` | 字段排查报告 |
| `FULL_DATAFLOW_DOC_ROOT` | `C:/Project/NeoZQYY/export/SYSTEM/REPORTS/full_dataflow_doc` | `SYSTEM/REPORTS/full_dataflow_doc/` | 全链路数据流文档 |
| `API_SAMPLE_CACHE_ROOT` | `C:/Project/NeoZQYY/export/SYSTEM/CACHE/api_samples` | `SYSTEM/CACHE/api_samples/` | API 样本缓存 |
| `SYSTEM_LOG_ROOT` | `C:/Project/NeoZQYY/export/SYSTEM/LOGS` | `SYSTEM/LOGS/` | 系统级运维日志 |
| `BACKEND_LOG_ROOT` | `C:/Project/NeoZQYY/export/BACKEND/LOGS` | `BACKEND/LOGS/` | 后端结构化日志 |
| `DEV_TRACE_LOG_DIR` | `export/dev-trace-logs` | `dev-trace-logs/` | 开发调试全链路日志DevTrace 模块) |
| `AVATAR_EXPORT_PATH` | `C:/Project/NeoZQYY/export/BACKEND/avatars` | `BACKEND/avatars/` | 用户头像文件存储目录 |
---
## 各目录详细说明与代码配合
### 1. ETL-Connectors/feiqiu/JSON — API 原始 JSON 导出
环境变量:`EXPORT_ROOT``FETCH_ROOT`
配置加载链路:
```
.env EXPORT_ROOT=...
→ env_parser.py ENV_MAP["EXPORT_ROOT"] → ("io.export_root",)
→ defaults.py io.export_root 默认 ""(空字符串,强制要求 .env 配置)
→ AppConfig.get("io.export_root")
```
代码使用:
- `utils/json_store.py``dump_json()` 负责写入 JSON 文件
- `tasks/ods/ods_json_archive_task.py` 调用 `dump_json()` 将 API 原始响应落盘
- 目录结构:`{EXPORT_ROOT}/{TASK_CODE}/{TASK_CODE}-{run_id}-{timestamp}/`
- 每个子目录包含按 endpoint 命名的 `.json` 文件和 `manifest.json`
示例输出:
```
export/ETL-Connectors/feiqiu/JSON/
└── ODS_PAYMENT/
└── ODS_PAYMENT-abc123-20260219_1430/
├── payment_transactions.json
└── manifest.json
```
---
### 2. ETL-Connectors/feiqiu/LOGS — ETL 运行日志
环境变量:`LOG_ROOT`
配置加载链路:
```
.env LOG_ROOT=...
→ env_parser.py ENV_MAP["LOG_ROOT"] → ("io.log_root",)
→ defaults.py io.log_root 默认 ""(空字符串,强制要求 .env 配置)
→ AppConfig.get("io.log_root") 或 config["io"]["log_root"]
```
代码使用:
- `orchestration/task_executor.py``_attach_run_file_logger()` 方法
- 读取 `self.config["io"]["log_root"]`
- 创建 `{LOG_ROOT}/{run_uuid}.log`
- 每次 ETL 运行生成一个以 run_uuid 命名的日志文件
- `utils/logging_utils.py``configure_logging()` 上下文管理器
- 接收 `log_file: Path` 参数,支持同时输出到控制台和文件
示例输出:
```
export/ETL-Connectors/feiqiu/LOGS/
├── 37f16195960649b384a6bf1e3bdb092c.log
├── 7b6d77fe8a6a4503a0ce4374e3864be9.log
└── ecc3684e2c794d1ba30b6748b999593c.log
```
---
### 3. ETL-Connectors/feiqiu/REPORTS — ETL 质检/完整性报告
环境变量:`ETL_REPORT_ROOT`
当前代码行为(已适配):
- `quality/integrity_service.py``write_report()` 函数
- 读取 `ETL_REPORT_ROOT` 环境变量作为输出根目录
- 环境变量缺失时抛出 `KeyError`
- 支持 `report_path` 参数覆盖
- `quality/integrity_checker.py``_default_report_path()` 函数
- 读取 `ETL_REPORT_ROOT` 环境变量
- 环境变量缺失时抛出 `KeyError`
- `tasks/dwd/dwd_quality_task.py``DwdQualityTask`
- `REPORT_PATH``ETL_REPORT_ROOT` 环境变量读取
- 环境变量缺失时 `load()` 抛出 `RuntimeError`
- `scripts/debug/generate_report.py`
- `REPORTS_DIR``ETL_REPORT_ROOT` 环境变量读取
- 环境变量缺失时抛出 `KeyError`
- ETL 内部脚本(`check/``repair/``debug/``scripts/`
- 均通过 `os.environ.get("ETL_REPORT_ROOT")` 读取
- 环境变量缺失时抛出 `KeyError`
---
### 4. SYSTEM/REPORTS/dataflow_analysis — 数据流结构分析报告
环境变量:`SYSTEM_ANALYZE_ROOT`
代码使用:
- `scripts/ops/gen_dataflow_report.py``resolve_data_dir()` 函数
- 通过 `_env_paths.get_output_path("SYSTEM_ANALYZE_ROOT")` 读取
- 环境变量缺失时抛出 `KeyError`
- 支持 `--output-dir` CLI 参数覆盖
- `scripts/ops/analyze_dataflow.py``resolve_output_dir()` 函数
- 通过 `_env_paths.get_output_path("SYSTEM_ANALYZE_ROOT")` 读取
- 环境变量缺失时抛出 `KeyError`
目录内容:
```
export/SYSTEM/REPORTS/dataflow_analysis/
├── bd_descriptions/ — 业务描述 JSON每表一个
├── db_schemas/ — 数据库表结构 JSONODS + DWD
├── field_mappings/ — 字段映射 JSON
├── json_trees/ — API JSON 结构树
├── collection_manifest.json — 采集清单
└── dataflow_YYYY-MM-DD_HHMMSS.md — 最终报告
```
已适配:代码直接读取 `SYSTEM_ANALYZE_ROOT`,无需改动。
---
### 5. SYSTEM/REPORTS/field_audit — 字段排查报告
环境变量:`FIELD_AUDIT_ROOT`
当前代码行为(已适配):
- `scripts/ops/field_audit.py`
- 通过 `_env_paths.get_output_path("FIELD_AUDIT_ROOT")` 读取
- 环境变量缺失时抛出 `KeyError`
- 支持 `--output` 参数覆盖
- `scripts/ops/export_dwd_field_review.py`
- 通过 `_env_paths.get_output_path("FIELD_AUDIT_ROOT")` 读取
- 环境变量缺失时抛出 `KeyError`
---
### 6. SYSTEM/REPORTS/full_dataflow_doc — 全链路数据流文档
环境变量:`FULL_DATAFLOW_DOC_ROOT`
当前代码行为(已适配):
- `scripts/ops/gen_full_dataflow_doc.py`
- `OUT` 通过 `_env_paths.get_output_path("FULL_DATAFLOW_DOC_ROOT")` 读取
- `SAMPLE_DIR` 通过 `_env_paths.get_output_path("API_SAMPLE_CACHE_ROOT")` 读取
- 环境变量缺失时抛出 `KeyError`
- `scripts/ops/gen_dataflow_doc.py`
- `OUT` 通过 `_env_paths.get_output_path("FULL_DATAFLOW_DOC_ROOT")` 读取
- 环境变量缺失时抛出 `KeyError`
- `scripts/ops/gen_api_field_mapping.py`
- `INPUT_DOC` 通过 `_env_paths.get_output_path("FULL_DATAFLOW_DOC_ROOT")` 读取
- 环境变量缺失时抛出 `KeyError`
---
### 7. SYSTEM/CACHE/api_samples — API 样本缓存
环境变量:`API_SAMPLE_CACHE_ROOT`
当前代码行为(已适配):
- `scripts/ops/gen_full_dataflow_doc.py`
- `SAMPLE_DIR` 通过 `_env_paths.get_output_path("API_SAMPLE_CACHE_ROOT")` 读取
- 环境变量缺失时抛出 `KeyError`
- 缓存 24 小时有效,超时重新从 API 获取
---
### 8. BACKEND/LOGS — 后端结构化日志
环境变量:`BACKEND_LOG_ROOT`(预留)
当前状态:
- 后端仅使用 uvicorn 默认日志,无文件输出
- 对应 LAUNCH-CHECKLIST 第 5.3 项"后端结构化日志"
启用时机:
- 后端接入结构化日志后,配置 `BACKEND_LOG_ROOT` 指向此目录
---
### 9. SYSTEM/LOGS — 系统级运维日志
环境变量:`SYSTEM_LOG_ROOT`(预留)
当前状态:
- 预留给未来的系统级运维脚本日志输出
- 如监控系统LAUNCH-CHECKLIST 7.2)上线后的采集器日志
---
### 10. dev-trace-logs — 开发调试全链路日志
环境变量:`DEV_TRACE_LOG_DIR`
默认值:`export/dev-trace-logs`(相对于项目根目录)
用途:
- DevTrace 模块的全链路请求追踪日志输出目录
- 覆盖 HTTP 请求、SSE 流式响应、WebSocket 连接、后台 Job、异常/错误、数据库连接生命周期、中间件层
- 仅用于开发调试,不影响生产环境
目录结构:
```
export/dev-trace-logs/
├── _index.json — 索引文件(文件列表、记录数、文件大小)
├── 2026-03-23/ — 按日期分子目录
│ ├── trace_2026-03-23_08.jsonl — 按小时分文件JSON Lines 格式)
│ ├── trace_2026-03-23_09.jsonl
│ ├── trace_2026-03-23_09_001.jsonl — 单文件超 10MB 自动轮转
│ └── ...
└── 2026-03-22/
└── ...
```
自动清理:
-`DEV_TRACE_LOG_RETENTION_DAYS` 环境变量控制保留天数(默认 7 天)
- 每日凌晨自动检查并删除超期日期目录
- 也可通过 `POST /api/admin/dev-trace/cleanup` 手动按日期范围清理
相关环境变量:
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `DEV_TRACE_ENABLED` | `true` | 总开关,关闭后不采集任何 trace |
| `DEV_TRACE_LOG_DIR` | `export/dev-trace-logs` | 日志输出目录 |
| `DEV_TRACE_LOG_RETENTION_DAYS` | `7` | 自动清理保留天数 |
| `DEV_TRACE_LOG_SQL` | `true` | 是否记录完整 SQL 语句 |
| `DEV_TRACE_LOG_PARAMS` | `true` | 是否记录函数参数值 |
代码使用:
- `apps/backend/app/trace/config.py``TraceConfig` 类读取上述环境变量
- `apps/backend/app/trace/writer.py``TraceWriter` 负责写入 `.jsonl` 文件
- `apps/backend/app/trace/cleanup.py` 负责自动清理过期目录
---
## 配置优先级
所有路径变量遵循项目统一的配置优先级:
```
defaults.py 默认值(路径类均为空字符串)< 根 .env < 应用 .env如 feiqiu/.env< 环境变量 < CLI 参数
```
ETL 模块的路径变量通过 `env_parser.py``ENV_MAP` 映射到 `AppConfig``io.*` 配置节。
`defaults.py` 中所有 `io.*` 路径默认值已清空为 `""`,如果 `.env` 未配置,下游代码会因空路径而失败。
系统级脚本直接通过 `os.environ.get()``python-dotenv` 读取。
---
## 代码适配状态
| 目录 | 环境变量 | 代码已适配 | 备注 |
|------|----------|-----------|------|
| ETL JSON | `EXPORT_ROOT` | ✅ | `env_parser.py``io.export_root` |
| ETL LOGS | `LOG_ROOT` | ✅ | `env_parser.py``io.log_root` |
| ETL FETCH | `FETCH_ROOT` | ✅ | `env_parser.py``io.fetch_root` |
| ETL REPORTS | `ETL_REPORT_ROOT` | ✅ | `integrity_service.py` / `dwd_quality_task.py` 已适配 |
| dataflow_analysis | `SYSTEM_ANALYZE_ROOT` | ✅ | `gen_dataflow_report.py` 已读取 |
| field_audit | `FIELD_AUDIT_ROOT` | ✅ | `field_audit.py` 已适配 |
| full_dataflow_doc | `FULL_DATAFLOW_DOC_ROOT` | ✅ | `gen_full_dataflow_doc.py` 已适配 |
| api_samples | `API_SAMPLE_CACHE_ROOT` | ✅ | `gen_full_dataflow_doc.py` 已适配 |
| SYSTEM LOGS | `SYSTEM_LOG_ROOT` | — | 预留 |
| BACKEND LOGS | `BACKEND_LOG_ROOT` | — | 预留 |
| dev-trace-logs | `DEV_TRACE_LOG_DIR` | ✅ | `app/trace/config.py``TraceConfig``app/trace/writer.py` 写入 |
| BACKEND avatars | `AVATAR_EXPORT_PATH` | ✅ | `app/config.py``AVATAR_EXPORT_PATH``xcx_avatar.py` 读写 |
---
## 服务器环境配置示例
开发机(`C:\Project\NeoZQYY\.env`
```env
EXPORT_ROOT=C:/Project/NeoZQYY/export/ETL-Connectors/feiqiu/JSON
LOG_ROOT=C:/Project/NeoZQYY/export/ETL-Connectors/feiqiu/LOGS
FETCH_ROOT=C:/Project/NeoZQYY/export/ETL-Connectors/feiqiu/JSON
ETL_REPORT_ROOT=C:/Project/NeoZQYY/export/ETL-Connectors/feiqiu/REPORTS
SYSTEM_ANALYZE_ROOT=C:/Project/NeoZQYY/export/SYSTEM/REPORTS/dataflow_analysis
BACKEND_LOG_ROOT=C:/Project/NeoZQYY/export/BACKEND/LOGS
AVATAR_EXPORT_PATH=C:/Project/NeoZQYY/export/BACKEND/avatars
```
服务器测试环境(`D:\NeoZQYY\test\repo\.env`
```env
EXPORT_ROOT=D:/NeoZQYY/test/repo/export/ETL-Connectors/feiqiu/JSON
LOG_ROOT=D:/NeoZQYY/test/repo/export/ETL-Connectors/feiqiu/LOGS
FETCH_ROOT=D:/NeoZQYY/test/repo/export/ETL-Connectors/feiqiu/JSON
ETL_REPORT_ROOT=D:/NeoZQYY/test/repo/export/ETL-Connectors/feiqiu/REPORTS
SYSTEM_ANALYZE_ROOT=D:/NeoZQYY/test/repo/export/SYSTEM/REPORTS/dataflow_analysis
BACKEND_LOG_ROOT=D:/NeoZQYY/test/repo/export/BACKEND/LOGS
```
服务器正式环境(`D:\NeoZQYY\prod\repo\.env`
```env
EXPORT_ROOT=D:/NeoZQYY/prod/repo/export/ETL-Connectors/feiqiu/JSON
LOG_ROOT=D:/NeoZQYY/prod/repo/export/ETL-Connectors/feiqiu/LOGS
FETCH_ROOT=D:/NeoZQYY/prod/repo/export/ETL-Connectors/feiqiu/JSON
ETL_REPORT_ROOT=D:/NeoZQYY/prod/repo/export/ETL-Connectors/feiqiu/REPORTS
SYSTEM_ANALYZE_ROOT=D:/NeoZQYY/prod/repo/export/SYSTEM/REPORTS/dataflow_analysis
BACKEND_LOG_ROOT=D:/NeoZQYY/prod/repo/export/BACKEND/LOGS
```