chore: 重写初始提交(清空历史,整理后全量提交)
This commit is contained in:
@@ -0,0 +1,280 @@
|
||||
<?php
|
||||
/*
|
||||
* @Author: YwxApp <ywx@ywxapp.cn>
|
||||
* @Date: 2026-07-17 17:02:05
|
||||
* @LastEditors: YwxApp <ywx@ywxapp.cn>
|
||||
* @LastEditTime: 2026-08-03 13:33:07
|
||||
* @Description:
|
||||
* @FilePath: \ywxapp_dev\app\backend\controller\AddonMonitor.php
|
||||
* @CustomString: Copyright (c) 2026 YwxApp
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace app\backend\controller;
|
||||
|
||||
use think\facade\View;
|
||||
use ywxapp\controller\BackendBase;
|
||||
use ywxapp\service\AddonPerformanceMonitor;
|
||||
use ywxapp\service\AddonHotReload;
|
||||
/**
|
||||
* AddonMonitor 类
|
||||
*
|
||||
* @author ywxapp <admin@ywxapp.cn>
|
||||
*/
|
||||
class AddonMonitor extends BackendBase
|
||||
{
|
||||
protected $noNeedLogin = [];
|
||||
protected $noNeedVerify = [];
|
||||
|
||||
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isAjax()) {
|
||||
$action = $this->request->param('action', 'overview');
|
||||
|
||||
switch ($action) {
|
||||
case 'overview':
|
||||
return $this->getOverview();
|
||||
case 'performance':
|
||||
return $this->getPerformance();
|
||||
case 'health':
|
||||
return $this->getHealth();
|
||||
case 'reload':
|
||||
return $this->getReloadStats();
|
||||
case 'reload_addon':
|
||||
return $this->reloadAddon();
|
||||
case 'clear_performance':
|
||||
return $this->clearPerformanceData();
|
||||
default:
|
||||
return $this->result->error('未知操作');
|
||||
}
|
||||
}
|
||||
|
||||
return View::fetch('addon_monitor/index');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取概览数据
|
||||
*/
|
||||
private function getOverview()
|
||||
{
|
||||
$overview = AddonPerformanceMonitor::getAllPerformanceOverview();
|
||||
$problematic = AddonPerformanceMonitor::getProblematicaddon();
|
||||
$reloadStats = AddonHotReload::getReloadStatistics();
|
||||
|
||||
// 统计数据
|
||||
$totaladdon = count($overview);
|
||||
$healthyaddon = 0;
|
||||
$problematicaddon = count($problematic);
|
||||
$totalCalls = 0;
|
||||
$avgExecutionTime = 0;
|
||||
$avgSuccessRate = 0;
|
||||
|
||||
foreach ($overview as $stats) {
|
||||
if ($stats['success_rate'] > 95 && $stats['avg_execution_time'] < 1.0) {
|
||||
$healthyaddon++;
|
||||
}
|
||||
$totalCalls += $stats['total_calls'];
|
||||
$avgExecutionTime += $stats['avg_execution_time'];
|
||||
$avgSuccessRate += $stats['success_rate'];
|
||||
}
|
||||
|
||||
if ($totaladdon > 0) {
|
||||
$avgExecutionTime = $avgExecutionTime / $totaladdon;
|
||||
$avgSuccessRate = $avgSuccessRate / $totaladdon;
|
||||
}
|
||||
|
||||
return $this->result->success([
|
||||
'total_addon' => $totaladdon,
|
||||
'healthy_addon' => $healthyaddon,
|
||||
'problematic_addon' => $problematicaddon,
|
||||
'total_calls' => $totalCalls,
|
||||
'avg_execution_time' => round($avgExecutionTime * 1000, 2),
|
||||
'avg_success_rate' => round($avgSuccessRate, 2),
|
||||
'reload_stats' => $reloadStats
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取性能详情
|
||||
*/
|
||||
private function getPerformance()
|
||||
{
|
||||
$addon = $this->request->param('addon', '');
|
||||
|
||||
if (empty($addon)) {
|
||||
// 返回所有插件性能数据
|
||||
$overview = AddonPerformanceMonitor::getAllPerformanceOverview();
|
||||
return $this->result->success($overview);
|
||||
} else {
|
||||
// 返回指定插件性能数据
|
||||
$stats = AddonPerformanceMonitor::getPerformanceStats($addon);
|
||||
return $this->result->success($stats);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取健康状态
|
||||
*/
|
||||
private function getHealth()
|
||||
{
|
||||
$problematic = AddonPerformanceMonitor::getProblematicaddon();
|
||||
$overview = AddonPerformanceMonitor::getAllPerformanceOverview();
|
||||
|
||||
// 生成健康报告
|
||||
$healthReport = [];
|
||||
foreach ($overview as $addon => $stats) {
|
||||
$isHealthy = true;
|
||||
$issues = [];
|
||||
|
||||
if ($stats['avg_execution_time'] > AddonPerformanceMonitor::PERFORMANCE_THRESHOLD) {
|
||||
$isHealthy = false;
|
||||
$issues[] = '执行时间过长';
|
||||
}
|
||||
|
||||
if ($stats['avg_memory_usage'] > AddonPerformanceMonitor::MEMORY_THRESHOLD) {
|
||||
$isHealthy = false;
|
||||
$issues[] = '内存使用过多';
|
||||
}
|
||||
|
||||
if ($stats['success_rate'] < 90) {
|
||||
$isHealthy = false;
|
||||
$issues[] = '成功率过低';
|
||||
}
|
||||
|
||||
$healthReport[$addon] = [
|
||||
'healthy' => $isHealthy,
|
||||
'issues' => $issues,
|
||||
'stats' => $stats
|
||||
];
|
||||
}
|
||||
|
||||
return $this->result->success([
|
||||
'health_report' => $healthReport,
|
||||
'problematic_addon' => $problematic
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取热重载统计
|
||||
*/
|
||||
private function getReloadStats()
|
||||
{
|
||||
$stats = AddonHotReload::getReloadStatistics();
|
||||
return $this->result->success($stats);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重载插件
|
||||
*/
|
||||
private function reloadAddon()
|
||||
{
|
||||
$addon = $this->request->param('addon', '');
|
||||
$force = $this->request->param('force', false);
|
||||
|
||||
if (empty($addon)) {
|
||||
return $this->result->error('请指定插件名称');
|
||||
}
|
||||
|
||||
if (!config('app.app_debug')) {
|
||||
return $this->result->error('热重载功能仅在开发环境可用');
|
||||
}
|
||||
|
||||
try {
|
||||
$reloaded = AddonHotReload::reloadAddon($addon, $force);
|
||||
|
||||
if ($reloaded) {
|
||||
$status = AddonHotReload::getReloadStatus($addon);
|
||||
return $this->result->success([
|
||||
'reloaded' => true,
|
||||
'status' => $status
|
||||
], '插件重载成功');
|
||||
} else {
|
||||
return $this->result->success([
|
||||
'reloaded' => false
|
||||
], '插件无文件变更,无需重载');
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return $this->result->error('插件重载失败:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除性能数据
|
||||
*/
|
||||
private function clearPerformanceData()
|
||||
{
|
||||
$addon = $this->request->param('addon', '');
|
||||
|
||||
try {
|
||||
if (empty($addon)) {
|
||||
AddonPerformanceMonitor::clearPerformanceData();
|
||||
return $this->result->success([], '已清除所有插件性能数据');
|
||||
} else {
|
||||
AddonPerformanceMonitor::clearPerformanceData($addon);
|
||||
return $this->result->success([], "已清除插件 {$addon} 的性能数据");
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return $this->result->error('清除性能数据失败:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 性能图表数据
|
||||
*/
|
||||
public function chart()
|
||||
{
|
||||
$type = $this->request->param('type', 'execution_time');
|
||||
$period = $this->request->param('period', 'day'); // day, week, month
|
||||
|
||||
$overview = AddonPerformanceMonitor::getAllPerformanceOverview();
|
||||
$chartData = [];
|
||||
|
||||
foreach ($overview as $addon => $stats) {
|
||||
if ($stats['total_calls'] === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
case 'execution_time':
|
||||
$chartData[] = [
|
||||
'name' => $addon,
|
||||
'value' => round($stats['avg_execution_time'] * 1000, 2)
|
||||
];
|
||||
break;
|
||||
case 'memory_usage':
|
||||
$chartData[] = [
|
||||
'name' => $addon,
|
||||
'value' => round($stats['avg_memory_usage'] / 1024, 2)
|
||||
];
|
||||
break;
|
||||
case 'success_rate':
|
||||
$chartData[] = [
|
||||
'name' => $addon,
|
||||
'value' => round($stats['success_rate'], 2)
|
||||
];
|
||||
break;
|
||||
case 'call_count':
|
||||
$chartData[] = [
|
||||
'name' => $addon,
|
||||
'value' => $stats['total_calls']
|
||||
];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 按值排序
|
||||
usort($chartData, function($a, $b) {
|
||||
return $b['value'] - $a['value'];
|
||||
});
|
||||
|
||||
// 只返回前10个
|
||||
$chartData = array_slice($chartData, 0, 10);
|
||||
|
||||
return $this->result->success([
|
||||
'chart_data' => $chartData,
|
||||
'type' => $type,
|
||||
'period' => $period
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user