mailwolt/app/Console/Commands/CollectHealth.php

100 lines
3.0 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Events\HealthUpdated;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
class CollectHealth extends Command
{
protected $signature = 'health:collect';
protected $description = 'Sammelt Systemmetriken und broadcastet sie';
public function handle(): int
{
$system = [
// CPU-Last (1/5/15) aus PHP
'cpu_load_1' => $this->loadavg(0),
'cpu_load_5' => $this->loadavg(1),
'cpu_load_15' => $this->loadavg(2),
// Kerne
'cores' => $this->cpuCores(),
// RAM % + Details aus /proc/meminfo (used = MemTotal - MemAvailable)
'ram' => $this->ramInfo(),
// Uptime in Sekunden aus /proc/uptime
'uptime_seconds' => $this->uptimeSeconds(),
// IPs aus ENV (falls gesetzt)
'ipv4' => env('SERVER_PUBLIC_IPV4'),
'ipv6' => env('SERVER_PUBLIC_IPV6'),
];
// Optional: eine “CPU-%”-Schätzung aus Load(1m)/Cores (damit dein UI einen %-Wert hat)
if (is_numeric($system['cpu_load_1']) && $system['cores'] > 0) {
$system['cpu_percent'] = (int) round(
100 * max(0, min(1, $system['cpu_load_1'] / $system['cores']))
);
}
$meta = [
'system' => $system,
'updated_at' => now()->toIso8601String(),
];
Cache::put('health:meta', $meta, 60);
event(new HealthUpdated($meta));
$this->info('Health aktualisiert & gesendet.');
return self::SUCCESS;
}
private function loadavg(int $index): ?float
{
$la = @sys_getloadavg();
return (is_array($la) && isset($la[$index])) ? (float) $la[$index] : null;
}
private function cpuCores(): int
{
$n = (int) @shell_exec('nproc 2>/dev/null');
return $n > 0 ? $n : 1;
// Alternativ: count(preg_grep('/^processor\s*:/', @file('/proc/cpuinfo') ?: [])) ?: 1;
}
private function ramInfo(): array
{
$mem = @file('/proc/meminfo', FILE_IGNORE_NEW_LINES) ?: [];
$kv = [];
foreach ($mem as $ln) {
if (preg_match('/^(\w+):\s+(\d+)/', $ln, $m)) {
$kv[$m[1]] = (int) $m[2]; // kB
}
}
$totalKB = $kv['MemTotal'] ?? 0;
$availKB = $kv['MemAvailable'] ?? 0; // besser als “free”
$usedKB = max(0, $totalKB - $availKB);
$totalGB = $totalKB / 1024 / 1024;
$usedGB = $usedKB / 1024 / 1024;
$percent = $totalKB > 0 ? (int) round(100 * $usedKB / $totalKB) : null;
return [
'percent' => $percent,
'used_gb' => (int) round($usedGB),
'total_gb' => (int) round($totalGB),
];
}
private function uptimeSeconds(): ?int
{
$s = @file_get_contents('/proc/uptime');
if (!$s) return null;
$parts = explode(' ', trim($s));
return isset($parts[0]) ? (int) floor((float) $parts[0]) : null;
}
}