This is an automated email from the ASF dual-hosted git repository.
jt2594838 pushed a commit to branch optimize_prometheus_report
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/optimize_prometheus_report by
this push:
new 8b6d0f65435 Fix Prometheus reporter initial snapshot race
8b6d0f65435 is described below
commit 8b6d0f65435e3c5749e4578ee34eddd542e97254
Author: Tian Jiang <[email protected]>
AuthorDate: Wed Sep 2 11:14:09 2026 +0800
Fix Prometheus reporter initial snapshot race
---
.../reporter/prometheus/PrometheusReporter.java | 34 +++++++++++++++++++---
1 file changed, 30 insertions(+), 4 deletions(-)
diff --git
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/prometheus/PrometheusReporter.java
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/prometheus/PrometheusReporter.java
index 0316e4fffe9..fa5695e9621 100644
---
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/prometheus/PrometheusReporter.java
+++
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/prometheus/PrometheusReporter.java
@@ -79,7 +79,10 @@ public class PrometheusReporter implements Reporter {
private final AbstractMetricManager metricManager;
private volatile ScheduledExecutorService snapshotUpdateExecutor;
private volatile DisposableServer httpServer;
- private volatile String metricsSnapshot = "";
+
+ /** A null snapshot means that no complete scrape has been published yet. */
+ private volatile String metricsSnapshot;
+
private volatile ScheduledFuture<?> snapshotUpdateFuture;
private static final String REALM = "metrics";
@@ -107,6 +110,8 @@ public class PrometheusReporter implements Reporter {
LOGGER.warn(MetricsMessages.PROMETHEUS_REPORTER_ALREADY_START);
return false;
}
+ // A reporter can be started again after its metric manager has been reset.
+ metricsSnapshot = null;
try {
HttpServer serverTransport =
HttpServer.create()
@@ -124,7 +129,7 @@ public class PrometheusReporter implements Reporter {
}
String metrics =
METRIC_CONFIG.isPrometheusReporterAsyncUpdate()
- ? metricsSnapshot
+ ? getMetricsSnapshot()
: scrape();
return res.header(HttpHeaderNames.CONTENT_TYPE,
"text/plain")
.sendString(Mono.just(metrics));
@@ -180,14 +185,24 @@ public class PrometheusReporter implements Reporter {
return thread;
});
}
+ // Delay the first background scrape until metric sets have been bound by
the metric service.
snapshotUpdateFuture =
snapshotUpdateExecutor.scheduleAtFixedRate(
- this::updateSnapshot, 0,
PROMETHEUS_DEFAULT_SCRAPE_INTERVAL_SECONDS, TimeUnit.SECONDS);
+ this::updateSnapshot,
+ PROMETHEUS_DEFAULT_SCRAPE_INTERVAL_SECONDS,
+ PROMETHEUS_DEFAULT_SCRAPE_INTERVAL_SECONDS,
+ TimeUnit.SECONDS);
}
private void updateSnapshot() {
try {
- metricsSnapshot = scrape();
+ String snapshot = scrape();
+ // Do not publish an empty scrape taken before metric sets are bound.
The request path will
+ // synchronously scrape until the first complete snapshot is available.
Empty snapshots are
+ // published after initialization so removed metrics are not kept in the
cache indefinitely.
+ if (!snapshot.isEmpty() || metricsSnapshot != null) {
+ metricsSnapshot = snapshot;
+ }
} catch (Throwable t) {
LOGGER.error(
MetricsMessages
@@ -196,6 +211,17 @@ public class PrometheusReporter implements Reporter {
}
}
+ private String getMetricsSnapshot() {
+ String snapshot = metricsSnapshot;
+ if (snapshot == null) {
+ snapshot = scrape();
+ if (!snapshot.isEmpty()) {
+ metricsSnapshot = snapshot;
+ }
+ }
+ return snapshot;
+ }
+
private void stopSnapshotUpdater() {
if (snapshotUpdateFuture != null) {
snapshotUpdateFuture.cancel(false);