建立项目级标杆文档 docs/_overview/ 作为产品全景索引, 解决"PRD 零碎、文档膨胀、跨子系统调研无入口"的问题。 主要内容: - 00-index 总索引 + 维护协议 + 与 CLAUDE.md 关系 - 01-product-overview 产品全景脑图(6 角色 / 6 子系统 / 数据流 / 7 业务概念 / 8+1 AI 矩阵 / 22 术语) - 02a-miniprogram-page-matrix 小程序 21 页业务指纹 - 02b-adminweb-page-matrix admin-web 19 路由业务指纹 - 03-test-spec 测试规范 (L1-L5 分层 + 走查模板 + 75-95 case 估算) - 04-doc-conflicts 39 条冲突索引(P0×8 / P1×13 / P2×13 + 5 子项) - 04a/b/c-conflicts-*-detail 业务故事卡(7 字段:关联/逻辑/影响/选项/判定) - 05-orphan-pages-cleanup admin-web 6 孤儿页面处置(1 归档 + 4 保留) - WAVES-MASTER-PLAN.md 全 Wave 主计划(0-5,共 22-32 工作日) - WAVE-1-KICKOFF.md Wave 1 实施 kickoff - GLOBAL-DECISION-DASHBOARD.md 全局决策仪表板 反馈调研产物: - 04a-feedback/ P0 两轮反馈(8+8 项决策 + D-1/2/3 + F-1/2 子代理产出) - 04b-feedback/ P1 两轮反馈(13+1+5 项 + E-1/2/3/4 + G-1/2 子代理产出) - 04c-feedback/ P2 反馈(13 项 + 5 子项 + H-1/2/3 子代理产出) - NEO-DECISIONS-LOG 累积决策记录 关键追加发现 8 处 D Bug(原蓝本 0): - P0-3 看板沙箱接入(Wave 1 W1-T1) - P0-5 致命 1 (4 处 fdw_etl 残留, 已修 commit17f045a) - P0-5 致命 2 (JWT aud 缺失, 已修 commit17f045a) - P0-6 clearAllTasks 守卫 (Wave 3) - P0-8 DBViewer 黑名单漏 (已修 commit17f045a) - P1-3 task-detail 跳转传 task_id 而非 customer_id - P2-7 board-finance 隐式 null - 2 个独立 Bug (page_context.created_at + ClueCategory 字典) 参考: docs/_overview/00-index.md
292 lines
10 KiB
Markdown
292 lines
10 KiB
Markdown
# dev-trace 性能消耗调研
|
|
|
|
> 调研时间:2026-05-04
|
|
> Neo 反馈:"web-admin 的 dev-trace 功能并没有用上,一次也没有使用过,而且还有占用性能的嫌疑"
|
|
> 入口:http://localhost:5173/logs/dev-trace
|
|
|
|
## 一、模块功能定位
|
|
|
|
### 1.1 前端(admin-web)
|
|
|
|
文件:`apps/admin-web/src/pages/DevTrace.tsx`(761 行,React + Antd)
|
|
|
|
功能:
|
|
- **覆盖率状态栏**:扫描后端代码所有路由 / Service / Job / SSE / WS,统计哪些"已在生产中产生过 trace"
|
|
- **筛选栏**:按日期、时间段、trace 类型、HTTP 方法、路径、状态码、最小耗时、是否错误、span 类型筛选
|
|
- **请求列表**(左):分页表格,展示 时间 / 类型 / 方法 / 路径 / 状态 / 耗时 / DB 次数 / 错误标记
|
|
- **Span 链路树**(右):点击列表行后展示该请求的全 span 树,带 SQL / params / 耗时 / 错误
|
|
- **设置抽屉**:运行时切换 `enabled` / `log_sql` / `log_params` / `retention_days`,手动按日期范围清理日志
|
|
|
|
定位:**纯开发调试工具**(不涉及业务数据)。
|
|
|
|
### 1.2 后端
|
|
|
|
文件:`apps/backend/app/routers/admin_dev_trace.py`(375 行)
|
|
|
|
8 个端点,前缀 `/api/admin/dev-trace/`,JWT 鉴权(只要 admin-web 已登录用户即可,不限角色)。
|
|
|
|
数据来源:全部读 `export/dev-trace-logs/<YYYY-MM-DD>/*.jsonl` 文件(JSON Lines 格式,非数据库)。
|
|
|
|
## 二、数据采集机制
|
|
|
|
### 2.1 采集组件清单(全部位于 `apps/backend/app/trace/`)
|
|
|
|
| 文件 | 作用 |
|
|
|------|------|
|
|
| `middleware.py` | ASGI 中间件,**仅拦截 `/api/xcx/` 前缀**的请求,创建 TraceContext |
|
|
| `db_wrapper.py` | psycopg2 connection / cursor 包装,拦截每条 `execute()` 记录 DB_QUERY span |
|
|
| `decorators.py` | `@trace_service` / `@trace_route` 装饰器(可选标注) |
|
|
| `sse_wrapper.py` | SSE 流式响应包装 |
|
|
| `ws_wrapper.py` | WebSocket 包装 |
|
|
| `job_wrapper.py` | 后台 Job 包装 |
|
|
| `error_handler.py` | 异常捕获记 ERROR span |
|
|
| `writer.py` | JSON Lines 异步落盘(asyncio.to_thread) |
|
|
| `context.py` | TraceContext / TraceSpan 数据模型(基于 contextvars) |
|
|
| `cleanup.py` | 按 retention_days 清理过期目录 |
|
|
| `coverage.py` | 静态扫描代码统计覆盖率 |
|
|
| `config.py` | 单例配置(env + 运行时 patch) |
|
|
|
|
### 2.2 装配点(`apps/backend/app/main.py`)
|
|
|
|
```python
|
|
# line 196
|
|
app.add_middleware(TraceMiddleware)
|
|
# line 240
|
|
app.include_router(admin_dev_trace.router)
|
|
```
|
|
|
|
`apps/backend/app/database.py:75-104`:每次 `get_connection()` 在 trace 启用时记 DB_CONN span 并返回 `TracedConnection`。
|
|
|
|
### 2.3 触发条件(关键!)
|
|
|
|
`middleware.py:43-46`:
|
|
```python
|
|
XCX_PATH_PREFIX = "/api/xcx/"
|
|
def _should_trace(path: str) -> bool:
|
|
return path.startswith(XCX_PATH_PREFIX)
|
|
```
|
|
|
|
```python
|
|
# line 75-78
|
|
if not config.enabled or not _should_trace(path):
|
|
await self.app(scope, receive, send)
|
|
return
|
|
```
|
|
|
|
**只有 `/api/xcx/`(微信小程序)路径才走 trace 全链路。** admin-web、tenant-admin、internal、其他路径**完全不采集**。
|
|
|
|
`db_wrapper.py:96-100`(关键性能点):
|
|
```python
|
|
ctx = get_current_trace()
|
|
if ctx is None:
|
|
self._cursor.execute(sql, params)
|
|
return
|
|
```
|
|
|
|
**无 TraceContext 时零开销直接委托**(只多一个 contextvars 读)。
|
|
|
|
### 2.4 写入位置
|
|
|
|
```env
|
|
DEV_TRACE_LOG_DIR=export/dev-trace-logs
|
|
DEV_TRACE_LOG_RETENTION_DAYS=7
|
|
```
|
|
|
|
实际落盘:`C:/Project/NeoZQYY/export/dev-trace-logs/<YYYY-MM-DD>/trace_<YYYY-MM-DD>_<HH>.jsonl`
|
|
|
|
写入是 `asyncio.to_thread` 异步线程池,不阻塞请求主流程。
|
|
|
|
## 三、性能消耗评估
|
|
|
|
### 3.1 CPU / 内存(单请求)
|
|
|
|
**xcx 路径(被采集)**:
|
|
- 中间件主链:HTTP_IN span 创建 + query string 解析 + send 响应包装 — **+0.2~0.5ms / 请求**
|
|
- DB 包装:每条 SQL 多一次 `inspect.currentframe()` 取调用方 + dict 序列化 + span 追加 — **+0.05~0.3ms / SQL**
|
|
- HTTP_OUT span + 序列化 + 异步写盘 — **+0.5~1ms / 请求**
|
|
- 内存:单请求 spans 列表平均 5-15 条,每条 dataclass 约 200-500 字节,**<10KB / 请求**
|
|
|
|
**非 xcx 路径(直接透传)**:
|
|
- 中间件分支判断 + path startswith 检查 — **<0.01ms / 请求**
|
|
- DB 包装:`get_current_trace()` 返回 None 时直接 `cursor.execute`,**仅 1 次 contextvars.get()**(纳秒级)
|
|
- 实际开销:**接近零**
|
|
|
|
**结论**:开销集中在 xcx 路径,admin-web / tenant-admin / mcp 完全无负担。
|
|
|
|
### 3.2 存储消耗(实测)
|
|
|
|
```bash
|
|
$ du -sh export/dev-trace-logs/
|
|
111M export/dev-trace-logs/
|
|
|
|
$ du -sh 2026-04-* 2026-05-*
|
|
6.5M 2026-04-23
|
|
5.5M 2026-04-25
|
|
5.8M 2026-04-26
|
|
4.4M 2026-04-27
|
|
3.2M 2026-04-29
|
|
3.6M 2026-04-30
|
|
15M 2026-05-01
|
|
2.7M 2026-05-02
|
|
209K 2026-05-03
|
|
513K 2026-05-04
|
|
```
|
|
|
|
- **日均**:约 3-15 MB(高峰为 5-1 的 15M,可能压测/批量)
|
|
- **总量**:111 MB(2026-04-11 至 2026-05-04 共 24 天,实际有 retention 但目前未触发)
|
|
- `DEV_TRACE_LOG_RETENTION_DAYS=7` 但 4-11 仍存在,清理任务**可能未运行**或者未达条件
|
|
- 单 jsonl 文件 200KB ~ 700KB,records 100-200/小时
|
|
|
|
### 3.3 查询消耗(打开 dev-trace 页面)
|
|
|
|
`admin_dev_trace.py:217-242` `list_requests` 端点:
|
|
```python
|
|
for f in sorted(date_dir.glob("*.jsonl")):
|
|
all_records.extend(_read_jsonl_file(f))
|
|
# 然后 Python 内存中做过滤、排序、分页
|
|
```
|
|
|
|
**问题**:每次刷新都全量读取当日所有 jsonl 文件到内存再过滤。
|
|
|
|
- 单日 200-700 条记录,15M 数据 → 单次列表查询 **~500ms-2s**(磁盘 IO + JSON 解析)
|
|
- `get_request_detail` 更糟:遍历**所有日期目录所有文件**,直到找到匹配 request_id(O(n) 全表扫)
|
|
- 但**只在用户主动打开页面时触发**,日常无负担
|
|
|
|
### 3.4 总评
|
|
|
|
| 场景 | 开销 |
|
|
|------|------|
|
|
| admin-web 日常请求(非 xcx) | **零** |
|
|
| 小程序请求(xcx) | 每请求 +0.5~2ms,内存 <10KB |
|
|
| 后台 Job(若标注) | 每 Job 写一次 jsonl |
|
|
| 用户打开 dev-trace 页 | 单次 0.5-2s |
|
|
| 存储增长 | 3-15 MB/天,7 天 retention 应控制在 100MB 内,但实际 retention 未生效到 111MB |
|
|
|
|
**性能消耗等级:中低**。不是"高占用"。
|
|
|
|
## 四、使用率证据
|
|
|
|
### 4.1 grep 引用扫描
|
|
|
|
```bash
|
|
$ grep -r "dev_trace\|DevTrace\|DEV_TRACE\|trace_writer\|trace_middleware" apps/backend
|
|
apps/backend/app/main.py
|
|
apps/backend/docs/API-REFERENCE.md
|
|
apps/backend/app/trace/writer.py
|
|
apps/backend/app/trace/middleware.py
|
|
apps/backend/app/trace/decorators.py
|
|
apps/backend/app/trace/db_wrapper.py
|
|
apps/backend/app/trace/config.py
|
|
apps/backend/app/trace/__init__.py
|
|
apps/backend/app/database.py
|
|
apps/backend/README.md
|
|
```
|
|
|
|
只有 trace 自身模块和装配点引用,**没有任何业务模块依赖 dev-trace**。
|
|
|
|
### 4.2 用户视角
|
|
|
|
Neo 反馈:**"一次也没有使用过"**。
|
|
|
|
### 4.3 日志数据是否被消费
|
|
|
|
- 没有任何脚本 / 任务 / 报表读取 `export/dev-trace-logs/` 数据
|
|
- 仅 dev-trace 页面 GUI 查看,但用户从未打开过
|
|
- AI 应用、审计、数据库工具均不依赖
|
|
|
|
**结论:dev-trace 当前对业务零价值,纯粹是开发期排错工具,且开发者未实际使用。**
|
|
|
|
## 五、drop 移除影响评估
|
|
|
|
### 5.1 删除文件清单
|
|
|
|
**前端**(admin-web):
|
|
- `apps/admin-web/src/pages/DevTrace.tsx` (761 行)
|
|
- `apps/admin-web/src/api/devTrace.ts`(估计存在,未单独读)
|
|
- `apps/admin-web/src/types/devTrace.ts`(估计存在)
|
|
- `apps/admin-web/src/App.tsx` 路由 `/logs/dev-trace` 删除
|
|
- 侧边栏菜单项删除
|
|
|
|
**后端**(backend):
|
|
- `apps/backend/app/routers/admin_dev_trace.py` (375 行)
|
|
- `apps/backend/app/trace/` 整个目录(11 个文件,约 1500-2000 行)
|
|
- `apps/backend/app/main.py` 删除 import 和 `add_middleware` / `include_router`
|
|
- `apps/backend/app/database.py` 删除 trace 相关分支(line 75-104)
|
|
|
|
**配置**(根 .env):
|
|
- `DEV_TRACE_ENABLED` / `DEV_TRACE_LOG_DIR` / `DEV_TRACE_LOG_RETENTION_DAYS` / `DEV_TRACE_LOG_SQL` / `DEV_TRACE_LOG_PARAMS` 5 个变量
|
|
|
|
**测试**:
|
|
- `apps/backend/tests/` 中所有 trace 相关测试(估计 5-10 个文件,需 grep 确认)
|
|
|
|
**数据**:
|
|
- `export/dev-trace-logs/` 目录(111MB)— 直接删除
|
|
|
|
### 5.2 数据库表
|
|
|
|
**没有**任何数据库表。dev-trace 全部基于文件落盘,与 PostgreSQL 无关。
|
|
|
|
### 5.3 是否有其他模块依赖
|
|
|
|
grep 已确认:**没有**业务代码依赖 dev-trace 模块。
|
|
- AI 调用不依赖(自己有 metadata 表)
|
|
- 调度器不依赖
|
|
- WebSocket / SSE 业务流不依赖(trace 是被动包装,业务流正常)
|
|
- 审计、监控不依赖
|
|
|
|
### 5.4 删除前的安全前提
|
|
|
|
1. **确认无生产环境正在用**:Neo 是单机开发者,目前仅本机环境,无生产部署
|
|
2. **关掉 Open API 文档引用**:`apps/backend/docs/API-REFERENCE.md` 可能有 dev-trace 章节,需同步删
|
|
3. **删除 main.py 时小心顺序**:先 `include_router` 再 `add_middleware`,反向删除
|
|
|
|
## 六、推荐
|
|
|
|
### 主推荐:**Drop 移除**
|
|
|
|
理由:
|
|
1. **使用率为零**:Neo 明确未使用过,业务代码无依赖
|
|
2. **维护成本**:1500-2000 行后端 + 760 行前端 = 2500 行无用代码
|
|
3. **存储积累**:111MB 且 retention 实际未生效,会持续增长
|
|
4. **认知负担**:9 种 span 类型 + 4 种 trace 类型 + 24 种 SpanType 常量,新人理解成本高
|
|
5. **替代方案充足**:
|
|
- SQL 审计:PostgreSQL 自带 `pg_stat_statements`
|
|
- HTTP 慢请求:nginx access log + 简易筛选
|
|
- 异常追踪:`logging` 模块 + `loguru` / `sentry`
|
|
- 排查具体 bug:`logger.debug` + 单测复现
|
|
6. **如未来真需要**:有成熟 OSS 方案(OpenTelemetry + Jaeger / Tempo),不用自己造轮子
|
|
|
|
### 次选:**保留但默认关闭**
|
|
|
|
如果 Neo 觉得"也许某天能用上",最小代价方案:
|
|
- 设 `DEV_TRACE_ENABLED=false`(目前是 `true`!)
|
|
- 删除 `export/dev-trace-logs/` 数据(111MB)
|
|
- 保留代码
|
|
|
|
代价:
|
|
- 仍占代码库 2500 行
|
|
- 后端启动时 TraceMiddleware 仍 `add_middleware`,每个请求多一次 path 判断(纳秒级,可忽略)
|
|
- DB 连接获取多一次 `get_current_trace()` 检查(返回 None,纳秒级)
|
|
|
|
实际运行开销几乎为零,但**代码维护负担仍在**。
|
|
|
|
### 不推荐:**改进**
|
|
|
|
dev-trace 设计本身合理(只拦 xcx 路径、文件落盘、异步写、span 模型规范),改进空间不大。问题不在"做得不好",在"用不上"。
|
|
|
|
## 七、最终建议
|
|
|
|
**Neo 直接 drop 移除**。
|
|
|
|
执行步骤(单 PR,1-2 小时):
|
|
1. 删 `apps/backend/app/trace/` 整目录
|
|
2. 删 `apps/backend/app/routers/admin_dev_trace.py`
|
|
3. 改 `apps/backend/app/main.py`(删 import + add_middleware + include_router)
|
|
4. 改 `apps/backend/app/database.py`(删 trace 分支)
|
|
5. 删 `apps/backend/tests/` 中 trace 相关测试
|
|
6. 删 admin-web `DevTrace.tsx` + 路由 + 菜单 + types/api
|
|
7. 删 `.env` 5 个 DEV_TRACE_* 变量
|
|
8. 删 `apps/backend/docs/API-REFERENCE.md` 中 dev-trace 章节
|
|
9. 物理删 `export/dev-trace-logs/`(回收 111MB)
|
|
10. 提交 PR + 审计记录(`docs/audit/changes/2026-05-04__drop-dev-trace.md`)
|