mivita/app/Http/Controllers/SyS/SystemStatusController.php
Kevin 8ad779ea3e Systemstatus im Sysadmin-Bereich und /health fuer externe Ueberwachung
- HealthProbe: Datenbank, Cache, Queue (sync / database / Horizon),
  fehlgeschlagene Jobs (24 h), Scheduler-Herzschlag, Plattenplatz
- /health auf jeder Domain, ohne web-Gruppe, nur mit MONITORING_HEALTH_TOKEN
- monitoring:heartbeat minuetlich im Scheduler
- Sysadmin -> Systemstatus (my.mivita.care/sysadmin/status) mit Version,
  Umgebung und zuletzt fehlgeschlagenen Jobs
- Anleitung Abschnitt G

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 11:49:14 +00:00

59 lines
2 KiB
PHP

<?php
namespace App\Http\Controllers\SyS;
use App\Http\Controllers\Controller;
use App\Services\Monitoring\HealthProbe;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Throwable;
/**
* Systemstatus im Sysadmin-Bereich: dieselben Prüfungen wie `/health`,
* dazu Umgebung und die zuletzt fehlgeschlagenen Jobs.
*/
class SystemStatusController extends Controller
{
public function index(HealthProbe $probe): View
{
$checks = $probe->checks();
return view('sys.status.index', [
'checks' => $checks,
'overall' => HealthProbe::worstStatus($checks),
'environment' => [
'Version' => config('app.version') ?? 'unbekannt',
'Umgebung' => app()->environment(),
'PHP' => PHP_VERSION,
'Laravel' => app()->version(),
'Queue-Treiber' => config('queue.default'),
'Cache-Treiber' => config('cache.default'),
],
'healthTokenConfigured' => filled(config('monitoring.health.token')),
'horizonAvailable' => config('queue.default') === 'redis',
'failedJobs' => $this->recentFailedJobs(),
]);
}
/**
* @return Collection<int, array{uuid: ?string, job: string, queue: string, failed_at: string, error: string}>
*/
private function recentFailedJobs(): Collection
{
try {
$rows = DB::table('failed_jobs')->latest('failed_at')->limit(10)->get();
} catch (Throwable) {
return collect();
}
return $rows->map(fn (object $row): array => [
'uuid' => $row->uuid ?? null,
'job' => json_decode($row->payload, true)['displayName'] ?? 'unbekannt',
'queue' => $row->connection.' / '.$row->queue,
'failed_at' => (string) $row->failed_at,
'error' => Str::limit(Str::before((string) $row->exception, "\n"), 200),
]);
}
}