homeos/app/Services/SystemHealth.php

98 lines
3.2 KiB
PHP

<?php
namespace App\Services;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
/**
* Host/infrastructure health probes. Used by the Host page (full detail) and by the
* Dashboard (only to raise a warning when a service is down — the home view itself
* never shows server internals).
*/
class SystemHealth
{
/** @return array<int, array{key:string,label:string,icon:string,state:string,detail:string}> */
public function services(): array
{
return [
$this->database(),
$this->redis(),
$this->reverb(),
$this->horizon(),
];
}
/** True when every probed service is online. */
public function allOnline(): bool
{
return ! collect($this->services())->contains(fn ($s) => $s['state'] !== 'online');
}
protected function database(): array
{
$base = ['key' => 'database', 'label' => __('host.svc_database'), 'icon' => 'network'];
try {
$start = microtime(true);
DB::connection()->select('select 1');
return $base + ['state' => 'online', 'detail' => (int) round((microtime(true) - $start) * 1000).' ms'];
} catch (\Throwable) {
return $base + ['state' => 'offline', 'detail' => __('host.svc_unreachable')];
}
}
protected function redis(): array
{
$base = ['key' => 'cache', 'label' => __('host.svc_cache'), 'icon' => 'devices'];
try {
$start = microtime(true);
Redis::connection()->ping();
return $base + ['state' => 'online', 'detail' => (int) round((microtime(true) - $start) * 1000).' ms'];
} catch (\Throwable) {
return $base + ['state' => 'offline', 'detail' => __('host.svc_unreachable')];
}
}
protected function reverb(): array
{
$base = ['key' => 'realtime', 'label' => __('host.svc_realtime'), 'icon' => 'activity'];
$host = config('broadcasting.connections.reverb.options.host', 'reverb');
$port = (int) config('broadcasting.connections.reverb.options.port', 8080);
$conn = @fsockopen($host, $port, $errno, $errstr, 1.0);
if ($conn) {
fclose($conn);
return $base + ['state' => 'online', 'detail' => $host.':'.$port];
}
return $base + ['state' => 'offline', 'detail' => __('host.svc_unreachable')];
}
protected function horizon(): array
{
$base = ['key' => 'queue', 'label' => __('host.svc_queue'), 'icon' => 'automation'];
try {
$masters = app(\Laravel\Horizon\Contracts\MasterSupervisorRepository::class)->all();
if (empty($masters)) {
return $base + ['state' => 'offline', 'detail' => __('host.svc_stopped')];
}
$running = collect($masters)->contains(fn ($m) => ($m->status ?? null) === 'running');
return $base + ($running
? ['state' => 'online', 'detail' => __('host.svc_running')]
: ['state' => 'warning', 'detail' => __('host.svc_stopped')]);
} catch (\Throwable) {
return $base + ['state' => 'offline', 'detail' => __('host.svc_unreachable')];
}
}
}