feat(stack): XHProf 采集切换文件落盘并独立 xhgui 供应

This commit is contained in:
augushong
2026-08-14 21:58:29 +08:00
parent e0e2580646
commit da388a8c4f
6 changed files with 138 additions and 47 deletions

View File

@@ -49,38 +49,58 @@ cd source/stack/docker-dev-myproject && docker compose up -d
## XHProf 性能分析(可选)
docker-dev / docker-dev-sync / docker-serve / full 模式内置了 XHProf 性能分析能力,默认不启用,完全不影响现有行为。采集数据存储在 MySQL 中PDO 方式docker-dev / docker-dev-sync 开箱即用docker-serve / full 需配置 XHGUI_PDO_DSN 环境变量指向可用的 MySQL。
docker-dev / docker-dev-sync / docker-serve / full 模式内置了 XHProf 性能分析能力,默认不启用,完全不影响现有行为。
### 启用方式
### 推荐路径:本地文件落盘 + 后台查看(默认)
采集数据以 jsonl 文件按天落盘到容器内目录,由后台导入定时任务增量读取写入数据库,最终在后台管理界面查看性能报告。无需启动任何额外服务。
```
请求
└─ auto_prepend_file(xhprof-bootstrap.php)
└─ php-profiler 采集XHPROF_ENABLE 总闸 + cookie _profiler=1 强制 + 1% 采样)
└─ 落盘 {XHPROF_FILE_DIR}/runs-{Ymd}.jsonl默认 /var/www/html/runtime/xhprof按天分文件
└─ 后台导入定时任务增量读取入库(读同一 XHPROF_FILE_DIR导完的整天文件自动删除
└─ 后台管理界面查看性能报告
```
启用方式(默认即为 file 落盘,无需额外 profile
```bash
# 在模式目录中,加 --profile xhprof 启动
cd source/stack/docker-dev
XHPROF_ENABLE=true docker compose --profile xhprof up -d
XHPROF_ENABLE=true docker compose up -d
```
或者在 `.env` 中设置 `XHPROF_ENABLE=true`,然后
相关环境变量
| 变量 | 默认 | 说明 |
|------|------|------|
| XHPROF_ENABLE | false | 采集总开关true 开启 |
| XHPROF_SAVER | file | 落盘方式file文件落盘/ upload推送 XHGui/ stack双写 |
| XHPROF_FILE_DIR | 空 | jsonl 落盘目录,空时容器内 `/var/www/html/runtime/xhprof`;采集与导入共用此变量 |
| XHGUI_UPLOAD_URL | 空 | XHGui 上传地址,仅 upload / stack 模式使用 |
| XHGUI_UPLOAD_TOKEN | ulthon-admin-xhprof | 上传令牌,仅 upload / stack 模式使用 |
### 手动触发采集
默认 1% 采样率。需要强制采集某个请求时,浏览器请求带 cookie `_profiler=1`
### 可选XHGui 独立可视化服务
XHGui 已降级为可选服务(独立 profile只负责实时可视化不参与默认采集链路。需要时以 `--profile xhgui` 启动,并推荐配合 stack 双写:
```bash
docker compose --profile xhprof up -d
cd source/stack/docker-dev
XHPROF_ENABLE=true XHPROF_SAVER=stack XHGUI_UPLOAD_URL=<XHGui上传地址> docker compose --profile xhgui up -d
```
### 查看性能报告
- `XHPROF_SAVER=stack`:文件落盘与 XHGui 推送同时写SaverFactory 递归双写落盘数据不丢XHGui 实时可看
- `XHGUI_UPLOAD_URL` 为空时不会推送;`XHPROF_SAVER=stack` 且该地址为空时bootstrap 记录警告并自动降级为 file 单写(防静默丢数据)
- `XHPROF_SAVER=upload`(只推送 XHGui 不落盘)为旧行为,兼容保留,不推荐
浏览器打开 `http://localhost:8142`输入 Basic Auth 用户名密码(默认 `admin` / `xhgui123`
浏览器打开 `http://localhost:8142` 查看Basic Auth 默认 `admin` / `xhgui123`,通过 `XHGUI_AUTH_USER` / `XHGUI_AUTH_PASS` 覆盖
### 认证配置
通过环境变量覆盖默认密码(在 `.env` 或 docker-compose 命令行设置):
```env
XHGUI_AUTH_USER=myuser
XHGUI_AUTH_PASS=mypassword
```
### 存储配置
默认使用 PDO MySQL 存储(复用 docker-dev 的 MySQL。通过环境变量自定义
XHGui 存储使用 PDO MySQL。docker-dev / docker-dev-sync 复用栈内 MySQLdocker-serve / full 没有内置 MySQL需配置 `XHGUI_PDO_DSN` 指向可用的 MySQL 实例:
```env
XHGUI_PDO_DSN=mysql:host=mysql;dbname=ulthon;charset=utf8mb4
@@ -88,21 +108,27 @@ XHGUI_PDO_USER=root
XHGUI_PDO_PASS=root
```
docker-serve / full 模式没有内置 MySQL需要设置 `XHGUI_PDO_DSN` 指向可用的 MySQL 实例。
### 手动触发采集
默认 1% 采样率。需要强制采集某个请求时,浏览器请求带 cookie `_profiler=1`
### 端口说明
| 端口 | 服务 | 说明 |
|------|------|------|
| 8142 | XHGui | 性能分析报告界面 |
| 8142 | XHGui | 可选的性能分析报告界面(需 `--profile xhgui` |
### 迁移说明profiles 更名,破坏性变更)
XHGui 服务的 compose profile 已由 `xhprof` 更名为 `xhgui`,采集开关与 XHGui 界面彻底解耦:
- 旧命令 `docker compose --profile xhprof up -d` 不再启动 XHGui请改用 `--profile xhgui`
- 现在只需 `XHPROF_ENABLE=true` 即可采集(默认文件落盘),无需任何 profile
- 旧栈若依赖 upload 直推 XHGui需显式设置 `XHPROF_SAVER=upload` 或改用推荐的 file / stack 模式
### 部署注记
bootstrap 的落盘方式切换与后台导入定时任务是配套变更,须同批上线:若采集端已切换为默认 file 落盘而后台导入任务未部署,落盘文件将无人消费、持续增长。
### 默认行为
不加 `--profile xhprof`XHGui 服务不启动,行为与未集成 XHProf 完全一致
`XHPROF_ENABLE=false`(默认)时不采集,行为与未集成 XHProf 完全一致;不加 `--profile xhgui` XHGui 服务不启动。
## default 目录规则(强约束)

View File

@@ -18,7 +18,9 @@ services:
# Sync polling interval in seconds (default: 3)
- SYNC_INTERVAL=${SYNC_INTERVAL:-3}
- XHPROF_ENABLE=${XHPROF_ENABLE:-false}
- XHGUI_UPLOAD_URL=http://xhgui:80/run/import
- XHPROF_SAVER=${XHPROF_SAVER:-file}
- XHPROF_FILE_DIR=${XHPROF_FILE_DIR:-}
- XHGUI_UPLOAD_URL=${XHGUI_UPLOAD_URL:-}
- XHGUI_UPLOAD_TOKEN=${XHGUI_UPLOAD_TOKEN:-ulthon-admin-xhprof}
extra_hosts:
- "host.docker.internal:host-gateway"
@@ -64,7 +66,7 @@ services:
xhgui:
image: xhgui/xhgui:0.24.x
restart: unless-stopped
profiles: ["xhprof"]
profiles: ["xhgui"]
ports:
- "8142:80"
volumes:

View File

@@ -16,7 +16,9 @@ services:
- "host.docker.internal:host-gateway"
environment:
- XHPROF_ENABLE=${XHPROF_ENABLE:-false}
- XHGUI_UPLOAD_URL=http://xhgui:80/run/import
- XHPROF_SAVER=${XHPROF_SAVER:-file}
- XHPROF_FILE_DIR=${XHPROF_FILE_DIR:-}
- XHGUI_UPLOAD_URL=${XHGUI_UPLOAD_URL:-}
- XHGUI_UPLOAD_TOKEN=${XHGUI_UPLOAD_TOKEN:-ulthon-admin-xhprof}
depends_on:
mysql:
@@ -60,7 +62,7 @@ services:
xhgui:
image: xhgui/xhgui:0.24.x
restart: unless-stopped
profiles: ["xhprof"]
profiles: ["xhgui"]
ports:
- "8142:80"
volumes:

View File

@@ -20,7 +20,9 @@ services:
# - ./storage:/var/www/html/storage
environment:
- XHPROF_ENABLE=${XHPROF_ENABLE:-false}
- XHGUI_UPLOAD_URL=http://xhgui:80/run/import
- XHPROF_SAVER=${XHPROF_SAVER:-file}
- XHPROF_FILE_DIR=${XHPROF_FILE_DIR:-}
- XHGUI_UPLOAD_URL=${XHGUI_UPLOAD_URL:-}
- XHGUI_UPLOAD_TOKEN=${XHGUI_UPLOAD_TOKEN:-ulthon-admin-xhprof}
extra_hosts:
- "host.docker.internal:host-gateway"
@@ -28,7 +30,7 @@ services:
xhgui:
image: xhgui/xhgui:0.24.x
restart: always
profiles: ["xhprof"]
profiles: ["xhgui"]
ports:
- "8142:80"
volumes:

View File

@@ -20,7 +20,9 @@ services:
# - ./storage:/var/www/html/storage
environment:
- XHPROF_ENABLE=${XHPROF_ENABLE:-false}
- XHGUI_UPLOAD_URL=http://xhgui:80/run/import
- XHPROF_SAVER=${XHPROF_SAVER:-file}
- XHPROF_FILE_DIR=${XHPROF_FILE_DIR:-}
- XHGUI_UPLOAD_URL=${XHGUI_UPLOAD_URL:-}
- XHGUI_UPLOAD_TOKEN=${XHGUI_UPLOAD_TOKEN:-ulthon-admin-xhprof}
extra_hosts:
- "host.docker.internal:host-gateway"
@@ -28,7 +30,7 @@ services:
xhgui:
image: xhgui/xhgui:0.24.x
restart: always
profiles: ["xhprof"]
profiles: ["xhgui"]
ports:
- "8142:80"
volumes: