53 lines
1.8 KiB
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;
|
|
}
|
|
}
|