diff --git a/source/docs/xhprof-backend-verification-report.html b/source/docs/xhprof-backend-verification-report.html new file mode 100644 index 0000000..7e45a54 --- /dev/null +++ b/source/docs/xhprof-backend-verification-report.html @@ -0,0 +1,116 @@ + + + + +XHProf 后台化验证报告(Task 9 全链路验证与存证) + + + + +

XHProf 后台化验证报告

+

计划:.omo/plans/xhprof-log-backend.md Task 9(Wave 5 终验)
+环境:docker-dev 栈(Windows 宿主 + docker compose,ulthon_admin:8000 / mysql:13306)
+执行时间:2026-08-14 23:30 ~ 2026-08-15 10:45(Asia/Shanghai)
+执行身份:Sisyphus-Junior(验证 + 一处 T7 缺陷修复)

+ +

一、主链断言(6 组,全部通过)

+ + + + + + + + +
#断言实测结果判定
1XHPROF_ENABLE=true 重启栈(无 profile)无 xhgui 容器compose ps 仅 4 服务(mysql/redis/phpmyadmin/ulthon_admin);docker ps -a 无 xhgui/xhprof 容器;容器内 env XHPROF_ENABLE=true。注:旧 xhgui 残留容器需带 --profile xhgui down 才会移除(compose down 不动非激活 profile 的容器,符合预期语义)PASS
25 次 _profiler=1 请求(curl -b)当天 jsonl 行数=55 请求全 200;runs-20260815.jsonl wc -l=5,5 行均含 "profile"+"meta" 键,末字节 \n(注:请求后立即 wc 曾见 4,系 fastcgi 响应先于 shutdown 落盘的毫秒级窗口,1 秒后补齐)PASS
3导入后 run/detail 各 +5,导完 jsonl 删除timer 自动轮(ul_system_timer_log id=755)抢先导入:{"files":1,"runs":5,"watches":10,"fails":0,"deleted":1};run 12→17(+5,node_id=d804e1bd9e6d-ac4562f2),detail 12→17(+5),xhprof 目录空(文件已删)PASS
4watch 命中数 >0 且 SQL 执行层规则 wt_sum > 0启用规则命中 26 条;watch_id=2(SQL 执行层,regex 实测 hex=7E7468696E6B5C5C64625C5C50444F436F6E6E656374696F6E3A3A2E2A7E 即 ~think\\db\\PDOConnection::.*~)12 命中 wt_sum=5554063us;watch_id=3 业务层控制器 2 命中;watch_id=4 数据保存 12 命中PASS
5四页面 200:列表无添加钮 / 详情含 main() / watch 3 条 / 命中记录xhprof.run/index 200 code=0(视图 toolbar:[],data-auth 仅 index/detail);detail?id=20 200 响应含 "fn": "main()";xhprof.watch/index 200 count=3;xhprof.run_watch/index 200 count=33PASS
6清理:dry-run 统计 → 真跑 → 过期=0 未过期不动;xhgui_results 不变(Must-NOT)造 31 天前种子(id 900001/900002 含 detail+run_watch);dry-run {"run_watch_deleted":2,"detail_deleted":2,"run_deleted":2,"dry_run":true};真跑同计数 dry_run:false;过期行全 0;未过期 17 条原样;xhgui_results 全程恒 27PASS
+ +

二、失败路径(4 条,全部通过)

+ + + + + + +
#场景实测结果判定
F1坏 JSON 行导入追加非 JSON 文本行 → 导入 {"runs":1,"watches":2,"fails":1}:好行入库、坏行 fails+1 不中断PASS
F2无换行半行追加无换行半行 → 导入 runs=0(不入库);补齐剩余片段+换行 → 导入 runs=1,run 900005 wall_time=4321 与合成值精确一致;文件导完删除PASS
F3非法正则被拒POST add 提交无定界符 think\db → {"code":500,"msg":"正则非法(必须带定界符...)"};DB 无 T9-invalid 行PASS
F4禁用规则不物化建 status=0 合法规则 T9-disabled-probe → 采集+导入(runs=2 watches=4 均来自启用规则)→ 该规则 run_watch 0 行;对照组启用规则各 +2 命中。验证后已删探针规则PASS
+ +

三、回归(3 条 + 终态恢复,全部通过)

+ + + + + + +
#场景实测结果判定
R1XHPROF_ENABLE=false 静默shell env 传 false 重建容器(env 确认)→ 5 次普通请求 + 3 次 _profiler=1 cookie 强制请求全 200,jsonl 目录无文件(总闸拦截 cookie 强制)PASS
R2无 xhprof 报错ul_debug_log 近期 error 级 0 条(含 xhprof 关键字 0 条);tools:log:show 尾部仅常规 SQL 日志PASS
R34 stack compose configdocker-dev / docker-dev-sync / docker-serve / full 四个 docker-compose.yaml config -q 全部 OKPASS
R4终态恢复XHPROF_ENABLE=true 重建容器 → _profiler=1 请求 → jsonl 1 行 → 手动导入 runs=1 watches=2 文件删除,采集闭环恢复;.env 无临时改动(全程 shell 环境变量传值)PASS
+ +

四、页面 QA(ulthon-page-qa checklist,两分辨率)

+ + + + + + + + +
检查项采样列表运行详情
页面可开(HTML)OK(iframe 200)OK(iframe 200)
数据正确表头 8 列齐全(请求时间/方法/URL/节点/总耗时/CPU耗时/内存峰值/操作),共 23 条头部统计渲染(总耗时/CPU/SQL占比/内存峰值/请求信息)
按钮显隐(data-auth)toolbar 0 按钮(无添加,符合只读设计);操作列仅"详情"(data-auth-index/detail,index.html 无 add 标记)无多余按钮
搜索搜索区由 cols 生成(request_time range / method 等)-(详情页无搜索)
1920x1080 布局正常,操作列 fixed right正常(弹层全屏)
390x844 布局不崩:表格横向滚动形态,数据行/分页/fixed 操作列完整(框架在此视口走横向滚动而非卡片)不崩:头部统计纵向堆叠可读
+

命中记录页(修复后):32 行可见,时间列 2026-08-15 08:23:49 格式正确,超阈值红色徽章(685.844 ms 超阈值 500ms)正常,console 0 errors。监控规则页:3 条预置规则 + regex 原文完整展示。

+ +

五、验证中发现并处理的缺陷

+ + + + +
#缺陷处置
B1(已修复)app/admin/view/xhprof/run_watch/index.js:26 调用 window.UA_CORE.util.toDateString —— UA_CORE 全项目零定义(T7 笔误 API),浏览器抛 "Cannot read properties of undefined (reading 'util')",命中记录页数据行渲染崩溃照抄 T5 formatRequestTime 纯 JS 实现替换(保留 isNaN 兜底);实测 32 行正常渲染、console 0 error;fix 提交入库
B2(已上报,不在 T9 修复范围)app/admin/view/xhprof/run/detail.js:37 $.ajax 用裸相对 URL 'xhprof.run/detail',在 /admin/xhprof.run/detail iframe 内解析为 /admin/xhprof.run/xhprof.run/detail → 404,详情页函数表与 SQL 摘要在浏览器端加载失败(服务端渲染的头部统计正常;API 层功能本身正常)上报编排器;建议修法 url: ua.url('xhprof.run/detail')(属 T6 文件,T9 红线禁止改动)
+ +

六、关键命令与输出摘录

+
# 断言1:重启(PowerShell env 传值)
+$env:XHPROF_ENABLE='true'; docker compose -f source/stack/docker-dev/docker-compose.yaml up -d
+docker compose ps --format "{{.Name}} {{.Service}}"   # 4 服务,无 xhgui
+
+# 断言2:5 次强制采集(容器内)
+for i in 1 2 3 4 5; do curl -s -b "_profiler=1" -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8000/; done
+wc -l /var/www/html/runtime/xhprof/runs-20260815.jsonl   # 5
+
+# 断言3:timer 自动导入抢先(手动 /do 返回 files:0 因已被消费)
+SELECT result FROM ul_system_timer_log WHERE id=755;
+# {"files":1,"runs":5,"watches":10,"fails":0,"deleted":1,"errors":[]}
+
+# 断言6:清理(防刷 query nonce;& 必须整体引号内,否则 PS/CRT 吃引号后 sh 将其后台化)
+curl -s -X POST "http://127.0.0.1:8000/tools/timer.XhprofRunClean/do?nonce=t9dryA&dryRun=1"
+# {"run_watch_deleted":2,"detail_deleted":2,"run_deleted":2,"dry_run":true}
+curl -s -X POST "http://127.0.0.1:8000/tools/timer.XhprofRunClean/do?nonce=t9realC"
+# {"run_watch_deleted":2,"detail_deleted":2,"run_deleted":2,"dry_run":false}
+
+# 回归 R1:false 总闸(连 cookie 强制也拦)
+$env:XHPROF_ENABLE='false'; docker compose ... up -d  # 8 请求全 200,jsonl 不生成
+ +

七、截图存证(6 张,1920x1080 + 390x844)

+
+
采样列表 1920
01 采样列表(1920x1080,共 23 条,无添加按钮)
+
运行详情 1920
02 运行详情(1920x1080,头部统计正常;函数表受 B2 影响未加载,已上报)
+
监控规则 1920
03 监控规则(1920x1080,3 条预置规则)
+
命中记录 1920
04 命中记录(1920x1080,B1 修复后 32 行正常渲染 + 超阈值徽章)
+
采样列表 390
05 采样列表(390x844,横向滚动不崩)
+
运行详情 390
06 运行详情(390x844,统计卡片纵向堆叠不崩)
+
+ +

八、结论

+

6 组主链断言 + 4 条失败路径 + 3 条回归(+终态恢复)全部通过;页面 QA 两分辨率不崩。XHProf 后台化全链路(采集 → jsonl 落盘 → 定时导入入库 → watch 物化 → 后台三页面 → 过期清理)在真实容器环境验证可用。遗留 B2(详情页浏览器端 ajax 相对路径 404)已上报编排器,不影响列表/命中/监控页面与服务端 API。

+ + +