feat(admin): XHProf 函数监控规则与命中记录

This commit is contained in:
augushong
2026-08-15 07:02:37 +08:00
parent e57b186126
commit c980ebdff0
23 changed files with 901 additions and 1 deletions

View File

@@ -0,0 +1,81 @@
<?php
use think\migration\Migrator;
/**
* XHProf 函数监控规则 - 预置三条规则
*
* regex 为 PCRE带 ~...~ 定界符导入任务物化时对被调用callee函数名匹配。
* 反斜杠形态说明DB 存储值形如 ~think\\db\\PDOConnection::.*~(双反斜杠字符),
* PCRE 解析 \\ 为一个字面 \,与采样键 think\db\PDOConnection::xxx命名空间单反斜杠对齐。
* 已对运行环境真实采样验证PDOConnection::(静态形态)、::save如 think\Cookie::save均有命中
* app\admin\controller\.* 在后台页面流量下命中(控制器中心主义)。
*
* MySQL 字符串字面量会把 \\ 解析为单个 \,故写入前用 addcslashes 将每个字面 \ 加倍,
* 保证落库值为双反斜杠字符。
*
* 幂等regex 有 UNIQUE 键ON DUPLICATE KEY UPDATE id=id 使重复执行不产生新行、不覆盖用户改动。
*/
class XhprofWatchSeed extends Migrator
{
public function up()
{
$now = time();
$rows = [
[
'name' => 'SQL 执行层',
// PHP 值:~think\\db\\PDOConnection::.*~(每个分隔位置两个反斜杠字符)
'regex' => '~think\\\\db\\\\PDOConnection::.*~',
'note' => 'PDO 连接层查询执行(真实形态实测)',
'threshold_ms' => 500,
],
[
'name' => '业务层控制器',
'regex' => '~app\\\\admin\\\\controller\\\\.*~',
'note' => '控制器中心主义,业务逻辑所在',
'threshold_ms' => 1000,
],
[
'name' => '数据保存操作',
'regex' => '~.*::save$~',
'note' => 'Model/log/session 的 save 调用',
'threshold_ms' => 0,
],
];
foreach ($rows as $row) {
$sql = sprintf(
"INSERT INTO `%sxhprof_watch` (`name`, `regex`, `note`, `threshold_ms`, `status`, `create_time`, `update_time`) VALUES (%s, %s, %s, %d, 1, %d, %d) ON DUPLICATE KEY UPDATE `id` = `id`",
$this->getAdapter()->getOption('table_prefix'),
$this->quoteLiteral($row['name']),
$this->quoteLiteral($row['regex']),
$this->quoteLiteral($row['note']),
$row['threshold_ms'],
$now,
$now
);
$this->execute($sql);
}
}
public function down()
{
$prefix = $this->getAdapter()->getOption('table_prefix');
$regexes = implode(', ', array_map(function ($regex) {
return $this->quoteLiteral($regex);
}, [
'~think\\\\db\\\\PDOConnection::.*~',
'~app\\\\admin\\\\controller\\\\.*~',
'~.*::save$~',
]));
$this->execute("DELETE FROM `{$prefix}xhprof_watch` WHERE `regex` IN ({$regexes})");
}
/**
* MySQL 字面量包装:单引号包裹 + 反斜杠转义(保证落库值与 PHP 值逐字符一致).
*/
private function quoteLiteral(string $value): string
{
return "'" . addcslashes($value, "\\") . "'";
}
}