189 lines
9.9 KiB
Markdown
189 lines
9.9 KiB
Markdown
# 清理计划
|
||
|
||
## 第一步:删掉我加的所有垃圾
|
||
|
||
> 前置条件:确认 `gen_test_data.py` 的原始版本在 git 历史中可恢复
|
||
> (`git log --oneline -- scripts/gen_test_data.py`),如无 git 历史则先手动备份。
|
||
|
||
### 删除文件(全部显式列出,避免 glob 误伤)
|
||
|
||
```
|
||
# ── 我加的垃圾脚本 ──
|
||
scripts/wnl_to_user_csv.py # WNL转换器
|
||
scripts/eval_clustering.py # 聚类评估
|
||
scripts/debug_db2.py # 调试文件
|
||
scripts/debug_db3.py # 调试文件
|
||
scripts/debug_persistence.py # 调试文件(原计划遗漏)
|
||
scripts/test_orch.py # 编排测试
|
||
scripts/test_orch2.py # 编排测试
|
||
scripts/test_pca.py # PCA测试
|
||
scripts/test_profile.py # 画像测试
|
||
scripts/test_tool_loop.py # 工具测试
|
||
scripts/test_tool_format.py # 工具测试
|
||
scripts/test_e2e_full.py # 端到端测试
|
||
scripts/test_32b.py # 32B模型测试
|
||
scripts/test_chinese_path.py # 中文路径测试
|
||
scripts/verify_runtime.py # 运行时验证
|
||
|
||
# ── 我加的垃圾数据 ──
|
||
data/wnl_converted.csv # WNL转换数据
|
||
```
|
||
|
||
### 保留原始文件
|
||
```
|
||
scripts/gen_test_data.py # ★ 保留 — 需从 git 恢复原始版本
|
||
# git checkout HEAD~1 -- scripts/gen_test_data.py
|
||
# 如无 git 历史则手动重建
|
||
scripts/gen_complex_test.py # 原始
|
||
scripts/column_survey.py # 原始
|
||
scripts/diagnose_compare.py # 原始
|
||
scripts/debug_db.py # 原始(非debug_db2/3)
|
||
scripts/test_llm_full.py # 原始LLM测试
|
||
data/complex_test.csv # 原始测试设备
|
||
data/e2e_full.csv # 原始
|
||
data/e2e_test.csv # 原始
|
||
data/geoip_city.csv # 原始
|
||
data/globe_test.csv # 原始
|
||
data/test_flows.csv # 原始(需用原gen_test_data.py重新生成)
|
||
data/复杂测试.csv # 原始
|
||
```
|
||
|
||
## 第二步:恢复被搞坏的文件到可用状态
|
||
|
||
### settings.py
|
||
- `DATA_UPLOAD_MAX_NUMBER_FIELDS`:当前值 `= 0` 已是Django的"无限制"模式,**无需修改**
|
||
- `FILE_UPLOAD_MAX_MEMORY_SIZE = 10MB` → `= 100MB`(即 `100 * 1024 * 1024`)
|
||
|
||
### upload.html
|
||
- `handleFiles()` 中每个文件旁加 ✕ 删除按钮
|
||
- 添加 `removeFile(index)` JS 函数
|
||
|
||
### auto.html
|
||
- ⚠️ 当前 `auto.html` 中没有 `<form>` 元素——LLM 分析通过 JS 直接 `fetch('/analyze/llm/', ...)` 触发(第56行)
|
||
- **无需修改表单 action**;确认 JS 中 fetch URL 正确即可
|
||
|
||
### views.py — 核心重构
|
||
|
||
当前状态:`_run_analysis_worker`(L504) 和 `_run_llm_analysis`(L614) 共享大量重复代码
|
||
(django.setup / ORM get / try-except / 进度报告 / 日志)。
|
||
|
||
目标:提取共享样板代码到统一的 `_run_pipeline_worker`,将两个分析逻辑作为回调注入。
|
||
|
||
**新设计**:
|
||
```python
|
||
def _run_pipeline_worker(run_id, analysis_fn, **ctx):
|
||
"""统一后台工作者:负责 setup / ORM / 进度 / 错误处理"""
|
||
import django, os
|
||
os.environ['DJANGO_SETTINGS_MODULE'] = 'tianxuan.settings'
|
||
os.environ['DJANGO_ALLOW_ASYNC_UNSAFE'] = 'true'
|
||
django.setup()
|
||
from analysis.models import AnalysisRun
|
||
from analysis import logger
|
||
|
||
run = AnalysisRun.objects.get(id=run_id)
|
||
try:
|
||
analysis_fn(run, ctx)
|
||
except Exception:
|
||
import traceback
|
||
tb = traceback.format_exc()
|
||
logger.error(tb)
|
||
run.status = 'failed'
|
||
run.error_message = tb
|
||
run.run_log += f'\n[FATAL] {tb}'
|
||
run.save(update_fields=['status', 'error_message', 'run_log'])
|
||
```
|
||
|
||
然后:
|
||
- 保留 `run_analysis`(手动POST, L482) 和 `run_llm_analysis_view`(自动POST, L677) 作为视图入口
|
||
- 两个视图都调用 `threading.Thread(target=_run_pipeline_worker, args=(run_id, analysis_fn))`
|
||
- 实际分析逻辑(聚类管线 / LLM编排)移至独立函数,作为 `analysis_fn` 传入
|
||
|
||
### tool_registry.py
|
||
- `_handle_extract_features`(L1091, `async def`) 中 `AR.objects.filter(csv_glob=...).order_by('-id').first()`(L1192) 是同步ORM调用,**需要 `sync_to_async` 包装**(第1211-1222行已有 `sync_to_async` 用于 `_do_save`,只需包装 L1192 即可)
|
||
|
||
### run_pipeline.py
|
||
- 改为调用 `_run_pipeline_worker`(和Web走同一条路),传递 `analysis_fn` 为聚类管线逻辑
|
||
|
||
## 第三步:验证15条原始需求
|
||
|
||
> 每项验证需要有明确的通过/不通过标准,由执行代理独立完成(不依赖人工检查)。
|
||
> 验证顺序:先命令行(5/6/14/15)→ 再浏览器自动化(其余项)。
|
||
|
||
| # | 需求 | 验证方式 | 通过标准 |
|
||
|---|------|---------|---------|
|
||
| 1 | 重启后旧数据可分析 | `run.bat` 启动 → 上传data/e2e_test.csv → 控制台重启 → 访问 `/runs/` 看旧记录可选 | `curl http://127.0.0.1:8000/runs/` 返回状态码200且含旧run的id |
|
||
| 2 | web图标所有页面 | 访问首页 `/` → 检查 `<link rel="icon">` 存在 | `favicon.ico` 或 `favicon.svg` 在 `<head>` 中存在 |
|
||
| 3 | 上传按钮在顶部 | 访问 `/upload/` → snap元素定位 | 上传按钮/区域在文件列表上方(DOM顺序在文件列表之前) |
|
||
| 4 | traceback完整 | 手动触发错误(如改坏config.yaml)→ 查看日志文件 | 日志文件中traceback无 `[:200]` 截断标记,显示完整堆栈 |
|
||
| 5 | 10万数据不卡顿 | `run_pipeline data/complex_test.csv` 完整运行 | 总运行时间 < 120秒,无 MemoryError |
|
||
| 6 | 进度条 | 上传后检查 `AnalysisRun.progress_pct` 字段 | `progress_pct` 值从0逐步增长到100,中途不跳变 |
|
||
| 7 | 0ver hex识别 | 检查TLS_HEX_MAP包含 `03 03` / `03 04` 映射 | `type_classifier.py` 中 `TLS_HEX_MAP` 包含这两个键 |
|
||
| 8 | globe响应式缩放 | 改变浏览器窗口宽度(1920→800)→ 检查canvas尺寸 | 3D canvas的width/height随窗口变化,不出现滚动条 |
|
||
| 9 | globe ?data= | 访问 `/globe/?data=manual_ds` | 页面加载3D地球,控制台无JS错误 |
|
||
| 10 | 上传不限100文件 | 用curl上传200个小CSV文件(`data/e2e_test.csv` x200) | 返回HTTP 200,非413 Payload Too Large |
|
||
| 11 | 选择文件列表有删除 | 检查 `upload.html` 中 `handleFiles()` 渲染逻辑 | 每文件条目有 `✕` 按钮和对应的 `removeFile(index)` 函数定义 |
|
||
| 12 | LLM过程打印 | 配置LLM → 触发自动分析 → 检查 `run_log` 字段 | `run_log` 包含步骤日志 `[1]`, `[2]`, ... `[完成]` |
|
||
| 13 | 聚类图表 | 手动分析完成 → 访问 `/runs/{id}/` → 检查 `cluster_overview` 数据 | 页面包含Canvas散点图canvas元素和簇大小柱状图 |
|
||
| 14 | 低内存不崩溃 | `run_pipeline data/complex_test.csv` 处理20000行 | 进程退出码0,峰值内存 < 2GB |
|
||
| 15 | +号字符串不被识别为数字 | 创建含`+`号的CSV(如 `+123` 列值)→ 上传 → 检查实体检测 | 实体检测不将 `+123` 识别为FLOAT类型(应为STRING) |
|
||
|
||
## 执行顺序与依赖关系
|
||
|
||
```
|
||
Step 1 (删垃圾) ──→ Step 2 (修文件) ──→ Step 3 (验证) ──→ Step 4 (最终清理)
|
||
│ │ │
|
||
│ ▼ │
|
||
└──── 4c (恢复gen_test_data) ◄────────────────┘
|
||
│
|
||
▼
|
||
4d (跑测试) ──→ 4e (提交)
|
||
```
|
||
|
||
- Step 1 和 Step 2 **必须**在 Step 3 之前完成
|
||
- 4c(恢复 `gen_test_data.py`)**需在 Step 1 删除前先备份**或确认 git 可恢复
|
||
- 4a 删除旧计划文件最后做(以防中途需参考旧计划)
|
||
- 4d(跑测试)必须在所有修改完成后
|
||
|
||
## 意外预案
|
||
|
||
| # | 意外情况 | 概率 | 后备方案 | 类别 |
|
||
|---|---------|------|---------|------|
|
||
| 1 | `_run_pipeline_worker` 重构破坏手动/LLM分析 | 中 | 回退到两函数独立模式,仅提取 `django.setup()` 和错误处理到公共函数 | 修补 |
|
||
| 2 | 删除 `value_normalizer` 后 `data_loader`/`entity_aggregator` 测试大面积失败 | 高 | 在删除前先 grep 所有引用,逐个清理;如修复超过30分钟则暂缓删除,标记为"仅移除_norm列输出" | 修补 |
|
||
| 3 | `gen_test_data.py` 无 git 历史可回退 | 低 | 从 `gen_complex_test.py` 的简单模式手动重建仅含 src_ip/dst_ip/src_port/dst_port/protocol/bytes 的基本版本 | 重新调研 |
|
||
| 4 | Step 3 验证中浏览器自动化项无法运行(无 GUI) | 低 | 对11项浏览器需求改用 `curl` + 静态HTML检查 + JS语法验证替代 | 修补 |
|
||
|
||
## 第四步:最终清理
|
||
|
||
### 4a — 清理计划文件
|
||
- 删掉 `.omo/plans/` 里的旧计划文件:
|
||
- `tianxiu-v4.md`
|
||
- `tianxiu-v5.md`
|
||
- `tianxiu-v6.md`
|
||
- `globe-v6.md`
|
||
- **保留** `cleanup.md`(自身)和 `.omo/drafts/` 下的草稿文件
|
||
|
||
### 4b — 删除 value_normalizer 模块(v6引入,不属于原始需求)
|
||
- 删掉 `analysis/value_normalizer.py`
|
||
- 删掉 `tests/test_value_normalizer.py` ⚠️(原计划遗漏)
|
||
- 从 `data_loader.py` 中移除对 `normalize_lf` 的引用
|
||
- 从 `entity_aggregator.py` 中移除 `_norm` 列的依赖
|
||
|
||
### 4c — 恢复 gen_test_data.py
|
||
- 恢复 `scripts/gen_test_data.py` 到 v5 版本(3类流量画像之前)
|
||
- 执行:`git checkout HEAD~2 -- scripts/gen_test_data.py`
|
||
(或找到引入3画像版之前的最近提交)
|
||
- 如无 git 历史:从 `scripts/gen_complex_test.py` 的简单版本手动重建
|
||
|
||
### 4d — 最终运行测试
|
||
- 执行:`runtime\python\python.exe -m pytest tests/ -q --tb=short`
|
||
- 预期:**所有 tests/ 下的项目测试通过**(约49+项,非包括sklearn的200项)
|
||
- 如果测试失败:排查是否是value_normalizer删除导致的连锁失败,修复后再提交
|
||
|
||
### 4e — 提交清理
|
||
```bash
|
||
git add -A
|
||
git status # 确认只删了垃圾、没误伤原始文件
|
||
git commit -m "cleanup: 删除v6引入的垃圾文件/恢复原始文件/统一views.py后台工作者"
|
||
```
|