$this->checkDatabase(), 'redis' => $this->checkRedis(), 'storage' => $this->checkStorage(), 'queue' => $this->checkQueue(), ]; $hasFailure = collect($checks)->contains(fn ($c) => $c['status'] === 'fail'); $allOk = collect($checks)->every(fn ($c) => $c['status'] === 'ok'); return response()->json([ 'status' => $allOk ? 'healthy' : ($hasFailure ? 'degraded' : 'warn'), 'timestamp' => now()->toIso8601String(), 'checks' => $checks, ], $hasFailure ? 503 : 200); } private function checkDatabase(): array { try { DB::connection()->getPdo(); return ['status' => 'ok', 'latency_ms' => $this->measure(fn () => DB::select('SELECT 1'))]; } catch (\Throwable $e) { return ['status' => 'fail', 'error' => $e->getMessage()]; } } private function checkRedis(): array { try { $latency = $this->measure(fn () => Cache::store('redis')->put('health_check', true, 5)); return ['status' => 'ok', 'latency_ms' => $latency]; } catch (\Throwable $e) { return ['status' => 'fail', 'error' => $e->getMessage()]; } } private function checkStorage(): array { try { $free = disk_free_space(storage_path()); $total = disk_total_space(storage_path()); if ($free === false || $total === false || $total === 0.0) { return ['status' => 'fail', 'error' => 'Unable to read disk space.']; } $usedPct = round((($total - $free) / $total) * 100, 1); return [ 'status' => $usedPct < 90 ? 'ok' : 'warn', 'used_pct' => $usedPct, 'free_gb' => round($free / 1073741824, 2), ]; } catch (\Throwable $e) { return ['status' => 'fail', 'error' => $e->getMessage()]; } } private function checkQueue(): array { try { $size = Queue::size('default'); return ['status' => 'ok', 'pending_jobs' => $size]; } catch (\Throwable $e) { return ['status' => 'unknown', 'error' => $e->getMessage()]; } } private function measure(callable $fn): int { $start = hrtime(true); $fn(); return (int) round((hrtime(true) - $start) / 1_000_000); } }