@extends('layouts.app') @section('title', 'Состояние системы') {{-- Technical metrics for this instance (SystemHealthController). Every section arrives as ['ok' => bool, 'error' => ?string, ...]: a probe that failed renders as a red card here rather than taking the page down with it, which is the whole point — see App\Support\SystemHealth's docblock. Formatting helpers are defined once below instead of per section; they're display-only (bytes -> КБ/МБ/ГБ, seconds -> "3 д 4 ч") and deliberately live in the view rather than in SystemHealth, which returns raw numbers so the ?format=json output stays machine-readable. --}} @php $bytes = static function ($value): string { $value = (float) $value; foreach (['Б', 'КБ', 'МБ', 'ГБ', 'ТБ'] as $unit) { if ($value < 1024 || $unit === 'ТБ') { return number_format($value, $unit === 'Б' ? 0 : 1, ',', ' ').' '.$unit; } $value /= 1024; } return (string) $value; }; $duration = static function (int $seconds): string { $days = intdiv($seconds, 86400); $hours = intdiv($seconds % 86400, 3600); $minutes = intdiv($seconds % 3600, 60); return $days > 0 ? "{$days} д {$hours} ч" : ($hours > 0 ? "{$hours} ч {$minutes} мин" : "{$minutes} мин"); }; $number = static fn ($value): string => $value === null ? '—' : number_format((float) $value, 0, ',', ' '); @endphp @section('content')
Показатели считаются в момент открытия страницы и нигде не кэшируются. Данные технические — они не о работе центра, а о самом сервере.
{{-- Верхняя сводка: четыре ответа на «всё ли работает» --}} @php $statuses = [ ['label' => 'База данных', 'ok' => ($database['ok'] ?? false), 'detail' => ($database['ok'] ?? false) ? $database['latency_ms'].' мс' : 'недоступна'], ['label' => 'Кэш / Redis', 'ok' => ($cache['ok'] ?? false) && ($cache['round_trip'] ?? false), 'detail' => ($cache['ok'] ?? false) ? ($cache['store'].', '.$cache['latency_ms'].' мс') : 'недоступен'], ['label' => 'Планировщик', 'ok' => ($scheduler['ok'] ?? false) && ($scheduler['alive'] ?? false), 'detail' => ($scheduler['last_run'] ?? null) ? $scheduler['minutes_ago'].' мин назад' : 'нет сигнала'], ['label' => 'Ошибки за 24 ч', 'ok' => ($logs['ok'] ?? false) && (($logs['errors_24h'] ?? 0) === 0), 'detail' => $number($logs['errors_24h'] ?? null)], ]; @endphp| Бренд | {{ $application['brand'] }} |
|---|---|
| Окружение | {{ $application['env'] }} @if ($application['debug']) APP_DEBUG включён @endif |
| Версия PHP / Laravel | {{ $application['php'] }} / {{ $application['laravel'] }} |
| Часовой пояс | {{ $application['timezone'] }} — сейчас {{ $application['server_time'] }} |
| Развёрнутая версия |
@if ($application['commit'])
{{ $application['commit'] }}
@if ($application['branch'])
({{ $application['branch'] }})
@endif
@if ($application['deployed_at'])
— обновлено {{ $application['deployed_at'] }}
@endif
@else
неизвестно (нет доступа к .git)
@endif
|
Ежеминутный сигнал пишется самим планировщиком. Если сигнала нет дольше
{{ $scheduler['stale_after_minutes'] ?? 5 }} минут, значит cron на сервере не запускает
schedule:run — тогда не выполняются ни начисления, ни напоминания об оплате.
Последний сигнал: {{ $scheduler['last_run'] }} ({{ $scheduler['minutes_ago'] }} мин назад)
@endif| Задача | Расписание | Следующий запуск |
|---|---|---|
{{ $job['command'] }} |
{{ $job['expression'] }} ({{ $job['timezone'] }}) | {{ $job['next_run'] ?? '—' }} |
| Задач нет. | ||
| Название | {{ $database['name'] }} |
|---|---|
| MySQL | {{ $database['version'] }}, аптайм {{ $duration($database['uptime_seconds']) }}, соединений: {{ $database['connections'] }} |
| Размер | {{ $bytes($database['total_bytes']) }} в {{ $database['table_count'] }} таблицах |
| Отклик | {{ $database['latency_ms'] }} мс |
|
{{ $table }}
{{ $number($count) }}
|
@endforeach
| Таблица | Строк (≈) | Размер |
|---|---|---|
{{ $table->name }} |
{{ $number($table->approx_rows) }} | {{ $bytes($table->size_bytes) }} |
| Хранилище кэша | {{ $cache['store'] }} |
|---|---|
| Сессии | {{ $cache['session_driver'] }} |
| Запись и чтение | @if ($cache['round_trip']) ОК {{ $cache['latency_ms'] }} мс @else не совпало @endif |
Занято {{ $usedPct }}% — свободно {{ $bytes($storage['free_bytes']) }} из {{ $bytes($storage['total_bytes']) }}
| Каталог storage | @if ($storage['writable']) доступен для записи @else только чтение @endif |
|---|---|
| Размер laravel.log | {{ $bytes($storage['log_bytes']) }} |
| Загруженный логотип | {{ $storage['logo_uploaded'] ? 'есть' : 'стандартный' }} |
Считаются по последним {{ 256 }} КБ файла laravel.log — уровни ERROR и выше.
Файл лога ещё не создан — ошибок не было.
@else