Files
coolify/tests/Unit/Metrics/HasMetricsMappingTest.php
T
Aditya Tripathi f8ec007403 fix(metrics): pick the root disk on the server Metrics page like the Fleet page
The server Metrics page now uses SentinelMetricsClient::rootMountName():
/, else /app/db (Sentinel 1.1.2 and older), else /data/coolify or /data
(Sentinel 1.1.3 and newer). Before, it kept only /, so the disk chart was
empty when Sentinel did not report a / mount.
2026-10-27 09:54:29 +01:00

102 lines
3.4 KiB
PHP

<?php
use App\Traits\HasMetrics;
/**
* Test double exposing the new metric mappers without SSH: overrides the fetch step
* to return canned Sentinel rows.
*/
class MetricsMappingDouble
{
use HasMetrics;
/** @var array<string, ?array> type => rows */
public array $rowsByType = [];
public string $uuid = 'app-uuid';
protected function fetchMetricRows(string $type, int $mins): ?array
{
return $this->rowsByType[$type] ?? null;
}
public function endpoint(string $type, int $mins): string
{
return $this->getMetricsEndpoint($type, '2026-01-01T00:00:00Z', $mins);
}
}
it('keeps only the root mount for disk metrics', function () {
$d = new MetricsMappingDouble;
$d->rowsByType['disk'] = [
['time' => 1000, 'mount' => '/boot', 'usedPercent' => 90.0],
['time' => 1000, 'mount' => '/', 'usedPercent' => 40.0],
['time' => 2000, 'mount' => '/', 'usedPercent' => 42.0],
];
expect($d->getDiskMetrics(5))->toBe([[1000, 40.0], [2000, 42.0]]);
});
it('splits network metrics into rx and tx series', function () {
$d = new MetricsMappingDouble;
$d->rowsByType['network'] = [
['time' => 1000, 'rxBytesPerSec' => 100.0, 'txBytesPerSec' => 10.0],
['time' => 2000, 'rxBytesPerSec' => 200.0, 'txBytesPerSec' => 20.0],
];
expect($d->getNetworkMetrics(5))->toBe([
'rx' => [[1000, 100.0], [2000, 200.0]],
'tx' => [[1000, 10.0], [2000, 20.0]],
]);
});
it('maps the one minute load average', function () {
$d = new MetricsMappingDouble;
$d->rowsByType['load'] = [
['time' => 1000, 'load1' => 0.5, 'load5' => 1.0, 'load15' => 1.5],
];
expect($d->getLoadMetrics(5))->toBe([[1000, 0.5]]);
});
it('returns null for a metric when metrics are unavailable', function () {
$d = new MetricsMappingDouble; // rowsByType empty -> fetch returns null
expect($d->getDiskMetrics(5))->toBeNull();
expect($d->getNetworkMetrics(5))->toBeNull();
expect($d->getLoadMetrics(5))->toBeNull();
});
it('does not use non-root mounts when root disk samples are missing', function () {
$double = new MetricsMappingDouble;
$double->rowsByType['disk'] = [['time' => 1000, 'mount' => '/boot', 'usedPercent' => 90]];
expect($double->getDiskMetrics(5))->toBe([]);
});
it('uses the Sentinel data mount for disk metrics when no root mount is reported', function () {
$double = new MetricsMappingDouble;
$double->rowsByType['disk'] = [
['time' => 1000, 'mount' => '/boot', 'usedPercent' => 90],
['time' => 1000, 'mount' => '/app/db', 'usedPercent' => 30],
];
expect($double->getDiskMetrics(5))->toBe([[1000, 30.0]]);
});
it('supports older disk rows without a mount field', function () {
$double = new MetricsMappingDouble;
$double->rowsByType['disk'] = [['time' => 1000, 'usedPercent' => 40]];
expect($double->getDiskMetrics(5))->toBe([[1000, 40.0]]);
});
it('asks sentinel to bucket ranges over an hour into at most 1000 whole-minute rows', function () {
$double = new MetricsMappingDouble;
expect($double->endpoint('cpu', 60))->not->toContain('bucket_ms')
->and($double->endpoint('cpu', 720))->toBe('http://localhost:8888/api/container/app-uuid/cpu/history?from=2026-01-01T00:00:00Z&bucket_ms=60000')
->and($double->endpoint('cpu', 10080))->toEndWith('&bucket_ms=660000')
->and($double->endpoint('cpu', 43200))->toEndWith('&bucket_ms=2640000');
});