Refactor Proxmox components: optimize data fetching in Server and Overview; enhance macro handling in Firewall; improve task data refresh logic in Statistics and views

This commit is contained in:
2026-03-14 11:44:46 -04:00
parent a8b6e5cfba
commit 91cdaf2a6b
7 changed files with 116 additions and 72 deletions

View File

@@ -71,10 +71,60 @@ class Overview extends Component
#[On('proxmox:stats')]
public function stats()
{
$this->fetchGraphData('cpu', $this->cpuTimeRange, $this->cpuAggregation);
$this->fetchGraphData('memory', $this->memoryTimeRange, $this->memoryAggregation);
$this->fetchGraphData('network', $this->networkTimeRange, $this->networkAggregation);
$this->fetchGraphData('disk', $this->diskTimeRange, $this->diskAggregation);
// Group graph types by their (timeRange, aggregation) to batch API calls.
// The Proxmox /rrddata endpoint returns ALL metrics in a single response,
// so we can serve multiple graph types from one API call when they share parameters.
$groups = [];
$graphConfigs = [
'cpu' => [$this->cpuTimeRange, $this->cpuAggregation],
'memory' => [$this->memoryTimeRange, $this->memoryAggregation],
'network' => [$this->networkTimeRange, $this->networkAggregation],
'disk' => [$this->diskTimeRange, $this->diskAggregation],
];
foreach ($graphConfigs as $graphType => [$timeRange, $aggregation]) {
$key = $timeRange . '|' . $aggregation;
$groups[$key]['timeRange'] = $timeRange;
$groups[$key]['aggregation'] = $aggregation;
$groups[$key]['types'][] = $graphType;
}
foreach ($groups as $group) {
$this->fetchGraphDataBatch($group['types'], $group['timeRange'], $group['aggregation']);
}
}
/**
* Fetch rrddata once and dispatch to multiple graph types that share the same parameters.
*/
protected function fetchGraphDataBatch(array $graphTypes, string $timeRange, string $aggregation): void
{
$allowedRanges = ['hour', 'day', 'week', 'month', 'year'];
$allowedAggs = ['average', 'maximum'];
if (!in_array($timeRange, $allowedRanges, true) || !in_array($aggregation, $allowedAggs, true)) {
return;
}
// Use a shared cache key for the raw API data (not per-graph-type)
$cacheKey = 'proxmox-stats-' . $this->server->id . '-rrd-' . $timeRange . '-' . $aggregation;
$data = Cache::remember($cacheKey, 60, function () use ($timeRange, $aggregation) {
$proxmox = new Proxmox;
$vmType = $this->server->node->vmType();
$stats = $proxmox->request('/nodes/' . $this->server->node->name . '/' . $vmType . '/' . $this->server->vm_id . '/rrddata', data: [
'timeframe' => $timeRange,
'cf' => $aggregation === 'maximum' ? 'MAX' : 'AVERAGE',
]);
return $stats->json()['data'] ?? [];
});
foreach ($graphTypes as $graphType) {
// Also store per-graph-type cache keys for individual update/invalidation
$perGraphKey = 'proxmox-stats-' . $this->server->id . '-' . $graphType . '-' . $timeRange . '-' . $aggregation;
Cache::put($perGraphKey, $data, 60);
$this->dispatch('proxmox:stats:' . $this->server->id . ':' . $graphType, $data);
}
}
protected function fetchGraphData(string $graphType, string $timeRange, string $aggregation)
@@ -214,56 +264,39 @@ class Overview extends Component
public function getPowerEventStatsProperty(): array
{
// Compute uptime percentage from DB statistics
$stats = ServerStatistics::where('server_id', $this->server->id)
->orderBy('DateTime')
->limit(500)
->get(['vmstatus', 'uptime']);
->get(['vmstatus']);
$counts = [
'starts' => 0,
'shutdowns' => 0,
'reboots' => 0,
'samples' => $stats->count(),
'running_samples' => 0,
'uptime_percent' => 0,
];
$previousStatus = null;
$previousUptime = null;
$samples = $stats->count();
$runningSamples = 0;
foreach ($stats as $stat) {
$status = strtolower($stat->vmstatus ?? '');
if ($status === 'running') {
$counts['running_samples']++;
if ($previousStatus !== 'running') {
$counts['starts']++;
} elseif (!is_null($stat->uptime) && !is_null($previousUptime) && $stat->uptime < $previousUptime) {
$counts['reboots']++;
}
} elseif (in_array($status, ['stopped', 'shutdown', 'offline', 'stopped - shutdown', 'suspended'])) {
if ($previousStatus === 'running') {
$counts['shutdowns']++;
}
if (strtolower($stat->vmstatus ?? '') === 'running') {
$runningSamples++;
}
$previousStatus = $status;
$previousUptime = $stat->uptime;
}
if ($counts['samples'] > 0) {
$counts['uptime_percent'] = round(($counts['running_samples'] / $counts['samples']) * 100, 1);
$uptimePercent = 0;
if ($samples > 0) {
$uptimePercent = round(($runningSamples / $samples) * 100, 1);
} elseif ($this->status) {
$counts['uptime_percent'] = strtolower($this->status->status ?? '') === 'running' ? 100 : 0;
$uptimePercent = strtolower($this->status->status ?? '') === 'running' ? 100 : 0;
}
// Get start/shutdown/reboot counts from Proxmox API (authoritative source)
$taskCounts = $this->getTaskEventCounts();
$counts['starts'] = $taskCounts['starts'];
$counts['shutdowns'] = $taskCounts['shutdowns'];
$counts['reboots'] = $taskCounts['reboots'];
return $counts;
return [
'starts' => $taskCounts['starts'],
'shutdowns' => $taskCounts['shutdowns'],
'reboots' => $taskCounts['reboots'],
'samples' => $samples,
'running_samples' => $runningSamples,
'uptime_percent' => $uptimePercent,
];
}
public function getNetworkRateStatsProperty(): array