diff --git a/resources/css/app.css b/resources/css/app.css index 8bfb74a3cb..3948fa7d6f 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -3695,7 +3695,8 @@ input[type="search"]::-webkit-search-results-decoration { } .fleet-containers-table-grid { - grid-template-columns: 2.25rem minmax(9rem, 1.7fr) minmax(6rem, 0.9fr) minmax(8.5rem, 1fr); + grid-template-columns: 2.25rem minmax(9rem, 1.7fr) minmax(6rem, 0.9fr) repeat(4, minmax(7rem, 1fr)); + min-width: 54rem; } .scheduled-executions-table-grid { diff --git a/resources/views/livewire/fleet/metrics.blade.php b/resources/views/livewire/fleet/metrics.blade.php index cd1723fff7..11bd7abe14 100644 --- a/resources/views/livewire/fleet/metrics.blade.php +++ b/resources/views/livewire/fleet/metrics.blade.php @@ -276,22 +276,7 @@ $serverListboxOptions = array_merge( {{-- Hottest containers --}} - -
- -
- @foreach (['cpu' => 'CPU', 'memory' => 'Memory', 'disk' => 'Disk', 'network' => 'Network'] as $m => $mlabel) - - @endforeach -
-
-
+ helper="{{ $scoped ? 'Busiest containers on this server, sortable by resource usage.' : 'Busiest containers across the fleet, sortable by resource usage.' }}"> @if (empty($topContainers))
@else @php - $metricOf = fn ($c) => match ($containerMetric) { - 'memory' => $c['memUsed'] ?? 0, - 'disk' => $c['diskBytes'] ?? 0, - 'network' => $c['net'] ?? 0, - default => $c['cpu'] ?? 0, - }; - // Bars are scaled to the leader so the row length reads as "share of the hottest". - $maxMetric = max(1, collect($topContainers)->map($metricOf)->max()); + $containerMetrics = ['cpu' => 'CPU', 'memUsed' => 'Memory', 'diskBytes' => 'Disk', 'net' => 'Network']; + $maxMetrics = []; + foreach ($containerMetrics as $key => $label) { + $maxMetrics[$key] = max(1, collect($topContainers)->max($key) ?? 0); + } @endphp -
+
# @include('livewire.traffic._sort-header', ['column' => 'name', 'label' => 'Container', 'text' => true, 'class' => 'justify-self-start']) @include('livewire.traffic._sort-header', ['column' => 'server', 'label' => 'Server', 'text' => true, 'class' => 'justify-self-start']) - @include('livewire.traffic._sort-header', ['column' => 'value', 'label' => ['cpu' => 'CPU', 'memory' => 'Memory', 'disk' => 'Disk', 'network' => 'Network'][$containerMetric], 'class' => 'justify-self-end']) + @foreach ($containerMetrics as $key => $label) + @include('livewire.traffic._sort-header', ['column' => $key, 'label' => $label, 'class' => 'justify-self-end']) + @endforeach
@foreach ($topContainers as $c) @php $meta = $this->containerMeta($c['id']); - $pct = min(100, round($metricOf($c) / $maxMetric * 100, 1)); - $display = match ($containerMetric) { - 'memory' => formatBytes($c['memUsed'] ?? 0), - 'disk' => formatBytes($c['diskBytes'] ?? 0), - 'network' => formatBytes($c['net'] ?? 0).'/s', - default => round($c['cpu'] ?? 0).'%', - }; @endphp
{{ $loop->iteration }}
@@ -344,13 +320,23 @@ $serverListboxOptions = array_merge( @endif
{{ $c['server'] }}
-
- + @endforeach
@endforeach
diff --git a/tests/v4/Browser/FleetMetricsTableSortTest.php b/tests/v4/Browser/FleetMetricsTableSortTest.php index 3d3c30bf3c..b658ffb333 100644 --- a/tests/v4/Browser/FleetMetricsTableSortTest.php +++ b/tests/v4/Browser/FleetMetricsTableSortTest.php @@ -34,8 +34,8 @@ class FakeBrowserFleetMetricsClient extends SentinelMetricsClient public function containersCurrent(): array { return match ($this->server->name) { - 'alpha' => [['id' => 'zeta', 'cpu' => 70.0, 'memUsed' => 10, 'memPercent' => 1.0, 'diskBytes' => 1, 'net' => 0.0]], - 'bravo' => [['id' => 'beta', 'cpu' => 5.0, 'memUsed' => 20, 'memPercent' => 2.0, 'diskBytes' => 2, 'net' => 0.0]], + 'alpha' => [['id' => 'zeta', 'cpu' => 70.0, 'memUsed' => 10, 'memPercent' => 1.0, 'diskBytes' => 1, 'net' => 30.0]], + 'bravo' => [['id' => 'beta', 'cpu' => 5.0, 'memUsed' => 20, 'memPercent' => 2.0, 'diskBytes' => 2, 'net' => 10.0]], default => [], }; } @@ -111,7 +111,8 @@ it('sorts the servers and containers tables when a column header is selected', f expect(visibleFleetMetricsRowNames($page, 'metrics-servers-section'))->toBe(['bravo', 'alpha', 'charlie']); // A data refresh keeps the sort. - $page->click('button:visible:has-text("7 days")') + $page->click('button:visible:has-text("Last 24 hours")') + ->click('[role="option"]:has-text("Last 7 days")') ->assertQueryStringHas('range', '7d'); expect(visibleFleetMetricsRowNames($page, 'metrics-servers-section'))->toBe(['bravo', 'alpha', 'charlie']); @@ -120,6 +121,14 @@ it('sorts the servers and containers tables when a column header is selected', f $page->script('document.querySelector(\'#metrics-containers-section button[title="Sort by container"]\').click()'); expect(visibleFleetMetricsRowNames($page, 'metrics-containers-section'))->toBe(['beta', 'zeta']); + foreach (['memory' => ['beta', 'zeta'], 'disk' => ['beta', 'zeta'], 'network' => ['zeta', 'beta'], 'cpu' => ['zeta', 'beta']] as $metric => $expected) { + $page->script("document.querySelector('#metrics-containers-section button[title=\"Sort by {$metric}\"]').click()"); + expect(visibleFleetMetricsRowNames($page, 'metrics-containers-section'))->toBe($expected); + + $page->script("document.querySelector('#metrics-containers-section button[title=\"Sort by {$metric}\"]').click()"); + expect(visibleFleetMetricsRowNames($page, 'metrics-containers-section'))->toBe(array_reverse($expected)); + } + $page->assertNoJavaScriptErrors() ->screenshot(filename: 'fleet-metrics-tables-sorted'); });