clusev/app/Console/Commands/SampleMetrics.php

53 lines
1.8 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Models\MetricSample;
use App\Models\Server;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
/**
* Persist a once-a-minute resource sample per server from the live (cache-backed) reading the
* 15s poller keeps fresh — the long history the Server-Details graph plots. No extra SSH: a server
* with no fresh cached reading (not polled / offline) simply gets no sample (an honest gap). Prunes
* beyond the retention window. Scheduled everyMinute in routes/console.php.
*/
class SampleMetrics extends Command
{
protected $signature = 'clusev:sample-metrics {--retention=30 : Days of history to keep}';
protected $description = 'Persist a one-per-minute metric history sample per server (and prune old samples)';
public function handle(): int
{
$now = now();
$rows = [];
foreach (Server::query()->get(['id']) as $server) {
$m = Cache::get("metrics:latest:{$server->id}");
if (! is_array($m)) {
continue;
}
$rows[] = [
'server_id' => $server->id,
// Percentages — clamp to 0..100 so a stray reading can never plot outside the chart.
'cpu' => min(100, max(0, (int) ($m['cpu'] ?? 0))),
'mem' => min(100, max(0, (int) ($m['mem'] ?? 0))),
'disk' => min(100, max(0, (int) ($m['disk'] ?? 0))),
'load' => round((float) ($m['load'] ?? 0), 2),
'sampled_at' => $now,
];
}
if ($rows !== []) {
MetricSample::insert($rows);
}
$retention = max(1, (int) $this->option('retention'));
MetricSample::where('sampled_at', '<', now()->subDays($retention))->delete();
return self::SUCCESS;
}
}