diff --git a/app/Services/FleetMetricsAggregator.php b/app/Services/FleetMetricsAggregator.php index 72f6ddb10b..29e0459d3b 100644 --- a/app/Services/FleetMetricsAggregator.php +++ b/app/Services/FleetMetricsAggregator.php @@ -61,6 +61,50 @@ class FleetMetricsAggregator ]; } + /** + * @param array> $seriesPerServer + * @return array + */ + public static function sumSeriesByBucket(array $seriesPerServer, string $mode): array + { + $totals = []; + $counts = []; + + foreach ($seriesPerServer as $series) { + foreach ($series as [$ts, $value]) { + $totals[$ts] = ($totals[$ts] ?? 0.0) + (float) $value; + $counts[$ts] = ($counts[$ts] ?? 0) + 1; + } + } + + ksort($totals); + + $out = []; + foreach ($totals as $ts => $sum) { + $out[] = [(int) $ts, $mode === 'avg' ? round($sum / $counts[$ts], 2) : round($sum, 2)]; + } + + return $out; + } + + /** + * @param array> $containers + * @return array> + */ + public static function rankContainers(array $containers, string $metric, int $limit = 20): array + { + $key = match ($metric) { + 'memory' => 'memUsed', + 'disk' => 'diskBytes', + 'network' => 'net', + default => 'cpu', + }; + + usort($containers, fn ($a, $b) => ($b[$key] ?? 0) <=> ($a[$key] ?? 0)); + + return array_slice($containers, 0, $limit); + } + /** * @param array> $rows * @return array diff --git a/tests/Unit/Services/FleetMetricsAggregatorRankingTest.php b/tests/Unit/Services/FleetMetricsAggregatorRankingTest.php new file mode 100644 index 0000000000..6b6fe2ee1e --- /dev/null +++ b/tests/Unit/Services/FleetMetricsAggregatorRankingTest.php @@ -0,0 +1,33 @@ +toBe([[1000, 3.0], [2000, 5.0], [3000, 9.0]]); +}); + +it('averages series across servers per bucket', function () { + $merged = FleetMetricsAggregator::sumSeriesByBucket([ + [[1000, 20.0]], + [[1000, 40.0]], + ], 'avg'); + + expect($merged)->toBe([[1000, 30.0]]); +}); + +it('ranks containers by the selected metric and caps the list', function () { + $containers = [ + ['id' => 'a', 'cpu' => 10.0, 'memUsed' => 500, 'diskBytes' => 5, 'net' => 1.0], + ['id' => 'b', 'cpu' => 90.0, 'memUsed' => 100, 'diskBytes' => 9, 'net' => 2.0], + ['id' => 'c', 'cpu' => 50.0, 'memUsed' => 900, 'diskBytes' => 1, 'net' => 3.0], + ]; + + expect(array_column(FleetMetricsAggregator::rankContainers($containers, 'cpu', 2), 'id'))->toBe(['b', 'c']); + expect(array_column(FleetMetricsAggregator::rankContainers($containers, 'memory'), 'id'))->toBe(['c', 'a', 'b']); + expect(array_column(FleetMetricsAggregator::rankContainers($containers, 'network'), 'id'))->toBe(['c', 'b', 'a']); +});