From 7e73902325e59426790889e244c212971a636f41 Mon Sep 17 00:00:00 2001 From: augushong Date: Fri, 14 Aug 2026 22:04:52 +0800 Subject: [PATCH] =?UTF-8?q?feat(admin):=20XHProf=20=E6=80=A7=E8=83=BD?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E4=BA=94=E5=BC=A0=E8=A1=A8=20Scheme=20?= =?UTF-8?q?=E8=BF=81=E7=A7=BB=E4=B8=8E=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/model/XhprofLogPosition.php | 27 +++++++++ app/admin/model/XhprofRun.php | 26 +++++++++ app/admin/model/XhprofRunDetail.php | 18 ++++++ app/admin/model/XhprofRunWatch.php | 23 ++++++++ app/admin/model/XhprofWatch.php | 24 ++++++++ app/admin/scheme/XhprofLogPosition.php | 56 +++++++++++++++++++ app/admin/scheme/XhprofRun.php | 55 ++++++++++++++++++ app/admin/scheme/XhprofRunDetail.php | 24 ++++++++ app/admin/scheme/XhprofRunWatch.php | 42 ++++++++++++++ app/admin/scheme/XhprofWatch.php | 45 +++++++++++++++ .../migrations/20260814100001_xhprof_run.php | 31 ++++++++++ .../20260814100002_xhprof_run_detail.php | 22 ++++++++ .../20260814100003_xhprof_watch.php | 27 +++++++++ .../20260814100004_xhprof_run_watch.php | 27 +++++++++ .../20260814100005_xhprof_log_position.php | 31 ++++++++++ 15 files changed, 478 insertions(+) create mode 100644 app/admin/model/XhprofLogPosition.php create mode 100644 app/admin/model/XhprofRun.php create mode 100644 app/admin/model/XhprofRunDetail.php create mode 100644 app/admin/model/XhprofRunWatch.php create mode 100644 app/admin/model/XhprofWatch.php create mode 100644 app/admin/scheme/XhprofLogPosition.php create mode 100644 app/admin/scheme/XhprofRun.php create mode 100644 app/admin/scheme/XhprofRunDetail.php create mode 100644 app/admin/scheme/XhprofRunWatch.php create mode 100644 app/admin/scheme/XhprofWatch.php create mode 100644 database/migrations/20260814100001_xhprof_run.php create mode 100644 database/migrations/20260814100002_xhprof_run_detail.php create mode 100644 database/migrations/20260814100003_xhprof_watch.php create mode 100644 database/migrations/20260814100004_xhprof_run_watch.php create mode 100644 database/migrations/20260814100005_xhprof_log_position.php diff --git a/app/admin/model/XhprofLogPosition.php b/app/admin/model/XhprofLogPosition.php new file mode 100644 index 0000000..1d0ad7b --- /dev/null +++ b/app/admin/model/XhprofLogPosition.php @@ -0,0 +1,27 @@ + '禁用', '1' => '启用'])] + public $status; + + #[Field(type: 'int', length: 11, unsigned: true, comment: '创建时间戳')] + #[Component(type: 'date', options: [])] + public $create_time; + + #[Field(type: 'int', length: 11, unsigned: true, comment: '更新时间戳')] + #[Component(type: 'date', options: [])] + public $update_time; +} diff --git a/database/migrations/20260814100001_xhprof_run.php b/database/migrations/20260814100001_xhprof_run.php new file mode 100644 index 0000000..b4db348 --- /dev/null +++ b/database/migrations/20260814100001_xhprof_run.php @@ -0,0 +1,31 @@ +table('xhprof_run', ['id' => false, 'primary_key' => ['id']]) + ->setComment('XHProf 性能采样记录(每次请求一条)') + ->addColumn('id', 'integer', ['limit' => 11, 'null' => false, 'signed' => false, 'identity' => true, 'comment' => '主键ID']) + ->addColumn('node_id', 'string', ['limit' => 64, 'null' => false, 'default' => 'default', 'comment' => '节点ID(区分不同采集节点)']) + ->addColumn('url', 'string', ['limit' => 500, 'null' => false, 'comment' => '请求完整 URL(超长截断)']) + ->addColumn('simple_url', 'string', ['limit' => 255, 'null' => false, 'default' => '', 'comment' => '规范化 URL(去 query、数字段替换,聚合用)']) + ->addColumn('method', 'string', ['limit' => 10, 'null' => false, 'default' => '', 'comment' => 'HTTP 方法']) + ->addColumn('wall_time', 'biginteger', ['default' => 0, 'comment' => '总耗时(微秒,main() 的 wt)']) + ->addColumn('cpu_time', 'biginteger', ['default' => 0, 'comment' => 'CPU 耗时(微秒,main() 的 cpu)']) + ->addColumn('memory_peak', 'biginteger', ['default' => 0, 'comment' => '内存峰值(字节,main() 的 pmu)']) + ->addColumn('request_time', 'decimal', ['precision' => 12, 'scale' => 3, 'default' => 0, 'comment' => '请求开始时间(REQUEST_TIME_FLOAT 浮点秒)']) + ->addColumn('create_time', 'integer', ['limit' => 11, 'comment' => '入库时间戳', 'signed' => false]) + ->addIndex(['simple_url', 'request_time'], ['name' => 'idx_simple_url_time']) + ->addIndex(['request_time'], ['name' => 'idx_request_time']) + ->addIndex(['wall_time'], ['name' => 'idx_wall_time']) + ->create(); + } +} diff --git a/database/migrations/20260814100002_xhprof_run_detail.php b/database/migrations/20260814100002_xhprof_run_detail.php new file mode 100644 index 0000000..9b36138 --- /dev/null +++ b/database/migrations/20260814100002_xhprof_run_detail.php @@ -0,0 +1,22 @@ +table('xhprof_run_detail', ['id' => false, 'primary_key' => ['id']]) + ->setComment('XHProf 采样原始 profile 数据(按 run 1:1,不进后台)') + ->addColumn('id', 'integer', ['limit' => 11, 'null' => false, 'signed' => false, 'comment' => '主键,值=ul_xhprof_run.id(不自增)']) + ->addColumn('profile_data', 'text', ['length' => MysqlAdapter::TEXT_LONG, 'null' => true, 'comment' => '原始 profile JSON']) + ->create(); + } +} diff --git a/database/migrations/20260814100003_xhprof_watch.php b/database/migrations/20260814100003_xhprof_watch.php new file mode 100644 index 0000000..8426e86 --- /dev/null +++ b/database/migrations/20260814100003_xhprof_watch.php @@ -0,0 +1,27 @@ +table('xhprof_watch', ['id' => false, 'primary_key' => ['id']]) + ->setComment('XHProf 函数监控规则') + ->addColumn('id', 'integer', ['limit' => 11, 'null' => false, 'signed' => false, 'identity' => true, 'comment' => '主键ID']) + ->addColumn('name', 'string', ['limit' => 100, 'null' => false, 'comment' => '规则名称(人读)']) + ->addColumn('regex', 'string', ['limit' => 255, 'null' => false, 'comment' => 'PCRE 正则(对被调用函数名匹配)']) + ->addColumn('note', 'string', ['limit' => 255, 'null' => false, 'default' => '', 'comment' => '备注']) + ->addColumn('threshold_ms', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '比对阈值(毫秒),0=不比对']) + ->addColumn('status', 'tinyinteger', ['limit' => 4, 'default' => 1, 'comment' => '状态:1=启用,0=禁用']) + ->addColumn('create_time', 'integer', ['limit' => 11, 'comment' => '创建时间戳', 'signed' => false]) + ->addColumn('update_time', 'integer', ['limit' => 11, 'comment' => '更新时间戳', 'signed' => false]) + ->addIndex(['regex'], ['unique' => true, 'name' => 'uniq_regex']) + ->create(); + } +} diff --git a/database/migrations/20260814100004_xhprof_run_watch.php b/database/migrations/20260814100004_xhprof_run_watch.php new file mode 100644 index 0000000..1bf32c5 --- /dev/null +++ b/database/migrations/20260814100004_xhprof_run_watch.php @@ -0,0 +1,27 @@ +table('xhprof_run_watch', ['id' => false, 'primary_key' => ['id']]) + ->setComment('XHProf 采样与监控规则命中聚合(导入时物化)') + ->addColumn('id', 'integer', ['limit' => 11, 'null' => false, 'signed' => false, 'identity' => true, 'comment' => '主键ID']) + ->addColumn('run_id', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '采样记录ID(ul_xhprof_run.id)', 'signed' => false]) + ->addColumn('watch_id', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '监控规则ID(ul_xhprof_watch.id)', 'signed' => false]) + ->addColumn('ct', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '命中边次数和']) + ->addColumn('wt_sum', 'biginteger', ['default' => 0, 'comment' => '命中耗时合计(微秒)']) + ->addColumn('wt_max', 'biginteger', ['default' => 0, 'comment' => '命中单次最大耗时(微秒)']) + ->addColumn('create_time', 'integer', ['limit' => 11, 'comment' => '入库时间戳', 'signed' => false]) + ->addIndex(['watch_id', 'create_time'], ['name' => 'idx_watch_time']) + ->addIndex(['run_id'], ['name' => 'idx_run_id']) + ->create(); + } +} diff --git a/database/migrations/20260814100005_xhprof_log_position.php b/database/migrations/20260814100005_xhprof_log_position.php new file mode 100644 index 0000000..2293887 --- /dev/null +++ b/database/migrations/20260814100005_xhprof_log_position.php @@ -0,0 +1,31 @@ +table('xhprof_log_position', ['id' => false, 'primary_key' => ['id']]) + ->setComment('XHProf 日志文件读取位置(增量读取状态)') + ->addColumn('id', 'integer', ['limit' => 11, 'null' => false, 'signed' => false, 'identity' => true, 'comment' => '主键ID']) + ->addColumn('node_id', 'string', ['limit' => 64, 'null' => false, 'default' => '', 'comment' => '节点ID(区分不同采集节点)']) + ->addColumn('file_path', 'string', ['limit' => 500, 'null' => false, 'comment' => '日志文件绝对路径']) + ->addColumn('inode', 'biginteger', ['default' => 0, 'comment' => '文件 inode,用于检测日志轮转', 'signed' => false]) + ->addColumn('offset', 'biginteger', ['default' => 0, 'comment' => '上次读取到的字节偏移', 'signed' => false]) + ->addColumn('last_read_time', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '上次读取时间戳', 'signed' => false]) + ->addColumn('last_line_hash', 'string', ['limit' => 32, 'default' => '', 'comment' => '上次最后一行的 md5 哈希(容错校验)']) + ->addColumn('parse_fail_count', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '解析失败累计次数', 'signed' => false]) + ->addColumn('parse_fail_samples', 'text', ['null' => true, 'comment' => '解析失败样本行(最多保留若干条)']) + ->addColumn('create_time', 'integer', ['limit' => 11, 'comment' => '创建时间戳', 'signed' => false]) + ->addColumn('update_time', 'integer', ['limit' => 11, 'comment' => '更新时间戳', 'signed' => false]) + ->addIndex(['node_id', 'file_path'], ['unique' => true, 'name' => 'uniq_node_file']) + ->create(); + } +}