feat(openmetrics): export more resilient if exception happens

Signed-off-by: Benjamin Gaussorgues <benjamin.gaussorgues@nextcloud.com>
This commit is contained in:
Benjamin Gaussorgues 2026-05-18 12:10:07 +02:00
parent 35484a9e39
commit 99bac310d1
No known key found for this signature in database

View file

@ -1,6 +1,7 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@ -51,13 +52,9 @@ class OpenMetricsController extends Controller {
return new Response(Http::STATUS_FORBIDDEN);
}
return new StreamTraversableResponse(
$this->generate(),
Http::STATUS_OK,
[
'Content-Type' => 'application/openmetrics-text; version=1.0.0; charset=utf-8',
]
);
return new StreamTraversableResponse($this->generate(), Http::STATUS_OK, [
'Content-Type' => 'application/openmetrics-text; version=1.0.0; charset=utf-8',
]);
}
private function isRemoteAddressAllowed(): bool {
@ -80,7 +77,16 @@ class OpenMetricsController extends Controller {
private function generate(): \Generator {
foreach ($this->exporterManager->export() as $family) {
yield $this->formatFamily($family);
try {
yield $this->formatFamily($family);
} catch (\Exception $e) {
// Skip family and return a valid result
$this->logger->error('Exception caught when exporting family {family}', [
'app' => 'metrics',
'family' => $family->name(),
'exception' => $e,
]);
}
}
$elapsed = (string)(microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']);
@ -131,11 +137,7 @@ class OpenMetricsController extends Controller {
}
private function escapeString(string $string): string {
return json_encode(
$string,
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR,
1
);
return json_encode($string, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR, 1);
}
private function formatValue(Metric $metric): string {