feat(metrics): add bucket series merge and container ranking

This commit is contained in:
Aditya Tripathi
2026-09-16 07:55:50 +00:00
parent 30aadf0367
commit bc3ec590d0
2 changed files with 77 additions and 0 deletions
+44
View File
@@ -61,6 +61,50 @@ class FleetMetricsAggregator
];
}
/**
* @param array<int, array<int, array{0: int, 1: float}>> $seriesPerServer
* @return array<int, array{0: int, 1: float}>
*/
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<int, array<string, mixed>> $containers
* @return array<int, array<string, mixed>>
*/
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<int, array<string, mixed>> $rows
* @return array<int, float>
@@ -0,0 +1,33 @@
<?php
use App\Services\FleetMetricsAggregator;
it('sums series by bucket timestamp and sorts ascending', function () {
$merged = FleetMetricsAggregator::sumSeriesByBucket([
[[2000, 5.0], [1000, 1.0]],
[[1000, 2.0], [3000, 9.0]],
], 'sum');
expect($merged)->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']);
});