fix(openmetrics): ensure unit is a suffix of metric name

Signed-off-by: Benjamin Gaussorgues <benjamin.gaussorgues@nextcloud.com>
This commit is contained in:
Benjamin Gaussorgues 2026-01-26 10:47:24 +01:00
parent 873ae96c6b
commit 34fe033ace
No known key found for this signature in database
5 changed files with 30 additions and 13 deletions

View file

@ -83,10 +83,10 @@ class OpenMetricsController extends Controller {
$elapsed = (string)(microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']);
yield <<<SUMMARY
# TYPE nextcloud_exporter_duration gauge
# UNIT nextcloud_exporter_duration seconds
# HELP nextcloud_exporter_duration Exporter run time
nextcloud_exporter_duration $elapsed
# TYPE nextcloud_exporter_run_seconds gauge
# UNIT nextcloud_exporter_run_seconds seconds
# HELP nextcloud_exporter_run_seconds Exporter run time
nextcloud_exporter_run_seconds $elapsed
# EOF
SUMMARY;

View file

@ -27,7 +27,7 @@ class AppsCount implements IMetricFamily {
#[Override]
public function name(): string {
return 'apps_count';
return 'installed_applications';
}
#[Override]
@ -42,7 +42,7 @@ class AppsCount implements IMetricFamily {
#[Override]
public function help(): string {
return 'Number of apps in Nextcloud';
return 'Number of applications installed in Nextcloud';
}
#[Override]

View file

@ -27,7 +27,7 @@ class RunningJobs implements IMetricFamily {
#[Override]
public function name(): string {
return 'jobs_running';
return 'running_jobs';
}
#[Override]

View file

@ -54,10 +54,10 @@ class OpenMetricsControllerTest extends TestCase {
$this->assertEquals('200', $response->getStatus());
$this->assertEquals('application/openmetrics-text; version=1.0.0; charset=utf-8', $response->getHeaders()['Content-Type']);
$expected = <<<EXPECTED
# TYPE nextcloud_exporter_duration gauge
# UNIT nextcloud_exporter_duration seconds
# HELP nextcloud_exporter_duration Exporter run time
nextcloud_exporter_duration %f
# TYPE nextcloud_exporter_run_seconds gauge
# UNIT nextcloud_exporter_run_seconds seconds
# HELP nextcloud_exporter_run_seconds Exporter run time
nextcloud_exporter_run_seconds %f
# EOF
EXPECTED;

View file

@ -26,11 +26,28 @@ abstract class ExporterTestCase extends TestCase {
}
public function testNotEmptyData(): void {
$this->assertNotEmpty($this->exporter->name());
$this->assertNotEmpty($this->metrics);
}
public function testValidNames(): void {
public function testValidExporterName(): void {
$exporterName = $this->exporter->name();
$this->assertMatchesRegularExpression('/^[a-z_:][a-z0-9_:]*$/i', $exporterName, );
$unit = $this->exporter->unit();
if ($unit === '') {
return;
}
// Unit name must follow metric name format
$this->assertMatchesRegularExpression('/^[a-z_:][a-z0-9_:]*$/i', $unit);
// Unit name must be a suffix in exporter name
$this->assertMatchesRegularExpression(
'/(^|_)' . $unit . '$/',
$exporterName,
'Metric name "' . $exporterName . '" must contains unit "' . $unit . '" as a suffix',
);
}
public function testValidLabelKey(): void {
$labelNames = [];
foreach ($this->metrics as $metric) {
foreach ($metric->labels as $label => $value) {