mivita/resources/views/sys/status/index.blade.php
Kevin fec88ee265 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

109 lines
4.4 KiB
PHP

@extends('layouts.layout-2')
@php
$badges = ['ok' => 'badge-success', 'warn' => 'badge-warning', 'critical' => 'badge-danger'];
$labels = ['ok' => 'OK', 'warn' => 'Warnung', 'critical' => 'Kritisch'];
@endphp
@section('content')
<h4 class="font-weight-bold py-3 mb-2">
Systemstatus
<span class="badge {{ $badges[$overall] }} align-middle ml-2">{{ $labels[$overall] }}</span>
<small class="text-muted ml-2">Stand {{ now()->format('d.m.Y H:i:s') }}</small>
</h4>
<div class="card mb-4">
<h6 class="card-header">Prüfungen</h6>
<div class="table-responsive">
<table class="table table-striped mb-0">
<thead>
<tr>
<th style="width: 220px;">Prüfung</th>
<th style="width: 120px;">Status</th>
<th>Detail</th>
</tr>
</thead>
<tbody>
@foreach ($checks as $check)
<tr>
<td>{{ $check['label'] }}</td>
<td><span class="badge {{ $badges[$check['status']] }}">{{ $labels[$check['status']] }}</span></td>
<td>{{ $check['detail'] }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card mb-4">
<h6 class="card-header">Umgebung</h6>
<table class="table mb-0">
<tbody>
@foreach ($environment as $label => $value)
<tr>
<td style="width: 160px;">{{ $label }}</td>
<td><code>{{ $value }}</code></td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<div class="col-md-6">
<div class="card mb-4">
<h6 class="card-header">Externe Überwachung</h6>
<div class="card-body">
<p class="mb-2">
Endpunkt für den externen Monitor:
<code>{{ url('/health') }}</code>
</p>
@if ($healthTokenConfigured)
<p class="mb-2"><span class="badge badge-success">Token gesetzt</span>
Abruf mit Header <code>Authorization: Bearer &lt;MONITORING_HEALTH_TOKEN&gt;</code>.
Antwort 200 = in Ordnung, 503 = kritisch.</p>
@else
<p class="mb-2"><span class="badge badge-warning">Kein Token</span>
<code>MONITORING_HEALTH_TOKEN</code> ist in der <code>.env</code> nicht gesetzt — der Endpunkt
antwortet mit 404.</p>
@endif
@if ($horizonAvailable)
<a href="{{ url(config('horizon.path', 'horizon')) }}" class="btn btn-sm btn-outline-primary" target="_blank">Horizon öffnen</a>
@endif
</div>
</div>
</div>
</div>
<div class="card mb-4">
<h6 class="card-header">Zuletzt fehlgeschlagene Jobs</h6>
@if ($failedJobs->isEmpty())
<div class="card-body text-muted">Keine fehlgeschlagenen Jobs gespeichert.</div>
@else
<div class="table-responsive">
<table class="table table-striped mb-0">
<thead>
<tr>
<th style="width: 160px;">Zeitpunkt</th>
<th>Job</th>
<th>Queue</th>
<th>Fehler</th>
</tr>
</thead>
<tbody>
@foreach ($failedJobs as $job)
<tr>
<td>{{ $job['failed_at'] }}</td>
<td>{{ $job['job'] }}</td>
<td>{{ $job['queue'] }}</td>
<td><small>{{ $job['error'] }}</small></td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
</div>
@endsection