87 lines
3.0 KiB
PHP
87 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Widgets;
|
|
|
|
use Filament\Widgets\StatsOverviewWidget;
|
|
use Filament\Widgets\StatsOverviewWidget\Stat;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
class UploadPipelineHealthWidget extends StatsOverviewWidget
|
|
{
|
|
protected static ?int $sort = 2;
|
|
|
|
protected ?string $pollingInterval = '60s';
|
|
|
|
protected function getStats(): array
|
|
{
|
|
$snapshot = Cache::get('storage:monitor:last');
|
|
|
|
if (! is_array($snapshot)) {
|
|
return [
|
|
Stat::make(__('admin.ops_health.pipeline.label'), __('admin.ops_health.pipeline.no_snapshot'))
|
|
->description(__('admin.ops_health.pipeline.no_snapshot_desc'))
|
|
->color('warning'),
|
|
];
|
|
}
|
|
|
|
$totals = $this->summarizeAssets($snapshot['targets'] ?? []);
|
|
$alerts = $snapshot['alerts'] ?? [];
|
|
$snapshotAge = $this->formatSnapshotAge($snapshot['generated_at'] ?? null);
|
|
$snapshotLabel = $snapshotAge
|
|
? __('admin.ops_health.snapshot_age', ['age' => $snapshotAge])
|
|
: __('admin.ops_health.snapshot_missing');
|
|
|
|
return [
|
|
Stat::make(__('admin.ops_health.pipeline.pending'), number_format($totals['pending']))
|
|
->description($snapshotLabel)
|
|
->descriptionIcon('heroicon-m-clock')
|
|
->color($totals['pending'] > 0 ? 'warning' : 'success'),
|
|
Stat::make(__('admin.ops_health.pipeline.failed'), number_format($totals['failed']))
|
|
->description(__('admin.ops_health.pipeline.archived_hint', ['count' => number_format($totals['archived'])]))
|
|
->color($totals['failed'] > 0 ? 'danger' : 'success'),
|
|
Stat::make(__('admin.ops_health.pipeline.total'), number_format($totals['total']))
|
|
->description(__('admin.ops_health.pipeline.hot_hint', ['count' => number_format($totals['hot'])]))
|
|
->color('primary'),
|
|
Stat::make(__('admin.ops_health.pipeline.alerts'), number_format(count($alerts)))
|
|
->color(count($alerts) > 0 ? 'danger' : 'success'),
|
|
];
|
|
}
|
|
|
|
private function summarizeAssets(array $targets): array
|
|
{
|
|
$totals = [
|
|
'total' => 0,
|
|
'pending' => 0,
|
|
'failed' => 0,
|
|
'hot' => 0,
|
|
'archived' => 0,
|
|
];
|
|
|
|
foreach ($targets as $target) {
|
|
$assets = $target['assets'] ?? [];
|
|
$totals['total'] += (int) ($assets['total'] ?? 0);
|
|
|
|
$byStatus = $assets['by_status'] ?? [];
|
|
foreach (['pending', 'failed', 'hot', 'archived'] as $status) {
|
|
$totals[$status] += (int) ($byStatus[$status]['count'] ?? 0);
|
|
}
|
|
}
|
|
|
|
return $totals;
|
|
}
|
|
|
|
private function formatSnapshotAge(?string $timestamp): ?string
|
|
{
|
|
if (! $timestamp) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
return Carbon::parse($timestamp)->diffForHumans();
|
|
} catch (\Throwable) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|