This is an automated email from the ASF dual-hosted git repository.
deardeng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 472f5c9f317 [improvement](fe) Add cloud tablet rebalancer metrics
(#66576)
472f5c9f317 is described below
commit 472f5c9f317702527a5a85f356126fa6089b39d3
Author: deardeng <[email protected]>
AuthorDate: Mon Aug 10 10:47:06 2026 +0800
[improvement](fe) Add cloud tablet rebalancer metrics (#66576)
Problem Summary: Cloud tablet rebalancer memory optimizations can only
be inferred from process-wide JVM metrics. Record per-round thread
allocation, duration, and tablet-route scan work so allocation changes
can be compared per round and per work item. Use ThreadMXBean when
supported and expose -1 for the last-round allocation when unavailable.
after Related PR: https://github.com/apache/doris/pull/66378,
https://github.com/apache/doris/pull/66389,
https://github.com/apache/doris/pull/66451, #66447 fix
<img width="3210" height="552" alt="image"
src="https://github.com/user-attachments/assets/ab7bbf2e-4ae0-4fbb-89b8-4fa1cf231c55"
/>
<img width="2428" height="476" alt="image"
src="https://github.com/user-attachments/assets/2dcf7860-bb24-4cac-9411-adc8f8a300be"
/>
### Release note
Expose CloudTabletRebalancer round, allocation, duration, and
tablet-scan metrics in FE metrics.
### Check List (For Author)
- Test: Unit Test
- ./run-fe-ut.sh --run
org.apache.doris.cloud.catalog.CloudTabletRebalancerMetricsTest
- ./run-fe-ut.sh --coverage --run
org.apache.doris.cloud.catalog.CloudTabletRebalancerMetricsTest,org.apache.doris.metric.MetricsTest
- mvn checkstyle:check -pl fe-core
- Behavior changed: Yes (adds FE observability metrics without changing
rebalance decisions)
- Does this need documentation: No
---
.../doris/cloud/catalog/CloudTabletRebalancer.java | 80 +++++++++++--------
.../catalog/CloudTabletRebalancerMetrics.java | 78 +++++++++++++++++++
.../java/org/apache/doris/metric/CloudMetrics.java | 37 +++++++++
.../java/org/apache/doris/metric/MetricRepo.java | 15 ++++
.../catalog/CloudTabletRebalancerMetricsTest.java | 90 ++++++++++++++++++++++
.../java/org/apache/doris/metric/MetricsTest.java | 42 ++++++++++
6 files changed, 310 insertions(+), 32 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudTabletRebalancer.java
b/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudTabletRebalancer.java
index 92477e3cc32..b8a6f833d7a 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudTabletRebalancer.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudTabletRebalancer.java
@@ -82,6 +82,9 @@ import java.util.stream.Collectors;
public class CloudTabletRebalancer extends MasterDaemon {
private static final Logger LOG =
LogManager.getLogger(CloudTabletRebalancer.class);
+ private final CloudTabletRebalancerMetrics rebalancerMetrics;
+ private long currentRoundTabletScanCount;
+
private volatile ConcurrentHashMap<Long, Set<Long>> beToTabletsGlobal =
new ConcurrentHashMap<Long, Set<Long>>();
@@ -245,8 +248,14 @@ public class CloudTabletRebalancer extends MasterDaemon {
}
public CloudTabletRebalancer(CloudSystemInfoService
cloudSystemInfoService) {
+ this(cloudSystemInfoService, CloudTabletRebalancerMetrics.create());
+ }
+
+ CloudTabletRebalancer(CloudSystemInfoService cloudSystemInfoService,
+ CloudTabletRebalancerMetrics rebalancerMetrics) {
super("cloud tablet rebalancer",
Config.cloud_tablet_rebalancer_interval_second * 1000);
this.cloudSystemInfoService = cloudSystemInfoService;
+ this.rebalancerMetrics = rebalancerMetrics;
}
private void initializeWarmupExecutorsIfNeeded() {
@@ -505,45 +514,51 @@ public class CloudTabletRebalancer extends MasterDaemon {
}
LOG.info("cloud tablet rebalance begin");
- long start = System.currentTimeMillis();
- refreshActiveTabletIdsIfNeeded();
- globalBalanceTypeEnum =
BalanceTypeEnum.getCloudWarmUpForRebalanceTypeEnum();
+ CloudTabletRebalancerMetrics.Round metricRound =
rebalancerMetrics.startRound();
+ currentRoundTabletScanCount = 0L;
+ try {
+ long start = System.currentTimeMillis();
+ refreshActiveTabletIdsIfNeeded();
+ globalBalanceTypeEnum =
BalanceTypeEnum.getCloudWarmUpForRebalanceTypeEnum();
- buildClusterToBackendMap();
- if (!completeRouteInfo()) {
- return;
- }
+ buildClusterToBackendMap();
+ if (!completeRouteInfo()) {
+ return;
+ }
- statRouteInfo();
- boolean migrated = migrateTabletsForSmoothUpgrade();
- if (migrated) {
statRouteInfo();
- }
+ boolean migrated = migrateTabletsForSmoothUpgrade();
+ if (migrated) {
+ statRouteInfo();
+ }
- indexBalanced = true;
- tableBalanced = true;
+ indexBalanced = true;
+ tableBalanced = true;
- performBalancing();
+ performBalancing();
- checkDecommissionState(clusterToBes);
- inited = true;
- long sleepSeconds = Config.cloud_tablet_rebalancer_interval_second;
- if (sleepSeconds < 0L) {
- LOG.warn("cloud tablet rebalance interval second is negative,
change it to default 1s");
- sleepSeconds = 1L;
- }
- long balanceEnd = System.currentTimeMillis();
- if
(DebugPointUtil.isEnable("CloudTabletRebalancer.balanceEnd.tooLong")) {
- LOG.info("debug pointCloudTabletRebalancer.balanceEnd.tooLong");
- // slower the balance end time to trigger next balance immediately
- balanceEnd += (Config.cloud_tablet_rebalancer_interval_second +
10L) * 1000L;
- }
- if (balanceEnd - start >
Config.cloud_tablet_rebalancer_interval_second * 1000L) {
- sleepSeconds = 1L;
+ checkDecommissionState(clusterToBes);
+ inited = true;
+ long sleepSeconds = Config.cloud_tablet_rebalancer_interval_second;
+ if (sleepSeconds < 0L) {
+ LOG.warn("cloud tablet rebalance interval second is negative,
change it to default 1s");
+ sleepSeconds = 1L;
+ }
+ long balanceEnd = System.currentTimeMillis();
+ if
(DebugPointUtil.isEnable("CloudTabletRebalancer.balanceEnd.tooLong")) {
+ LOG.info("debug
pointCloudTabletRebalancer.balanceEnd.tooLong");
+ // slower the balance end time to trigger next balance
immediately
+ balanceEnd += (Config.cloud_tablet_rebalancer_interval_second
+ 10L) * 1000L;
+ }
+ if (balanceEnd - start >
Config.cloud_tablet_rebalancer_interval_second * 1000L) {
+ sleepSeconds = 1L;
+ }
+ setInterval(sleepSeconds * 1000L);
+ LOG.info("finished to rebalancer. cost: {} ms, rebalancer sche
interval {} s",
+ (System.currentTimeMillis() - start), sleepSeconds);
+ } finally {
+ rebalancerMetrics.finishRound(metricRound,
currentRoundTabletScanCount);
}
- setInterval(sleepSeconds * 1000L);
- LOG.info("finished to rebalancer. cost: {} ms, rebalancer sche
interval {} s",
- (System.currentTimeMillis() - start), sleepSeconds);
}
private void buildClusterToBackendMap() {
@@ -1277,6 +1292,7 @@ public class CloudTabletRebalancer extends MasterDaemon {
for (MaterializedIndex index :
partition.getMaterializedIndices(IndexExtState.VISIBLE, true)) {
for (Map.Entry<String, List<Long>> entry :
clusterToBes.entrySet()) {
String cluster = entry.getKey();
+ currentRoundTabletScanCount +=
index.getTablets().size();
operator.op(db, table, partition, index,
cluster);
}
} // end for indices
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudTabletRebalancerMetrics.java
b/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudTabletRebalancerMetrics.java
new file mode 100644
index 00000000000..84250a8465f
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudTabletRebalancerMetrics.java
@@ -0,0 +1,78 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.cloud.catalog;
+
+import org.apache.doris.metric.MetricRepo;
+
+import java.lang.management.ManagementFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.function.LongSupplier;
+
+final class CloudTabletRebalancerMetrics {
+ private static final long ALLOCATED_BYTES_UNAVAILABLE = -1L;
+
+ private final LongSupplier nanoTimeSupplier;
+ private final LongSupplier allocatedBytesSupplier;
+
+ CloudTabletRebalancerMetrics(LongSupplier nanoTimeSupplier, LongSupplier
allocatedBytesSupplier) {
+ this.nanoTimeSupplier = nanoTimeSupplier;
+ this.allocatedBytesSupplier = allocatedBytesSupplier;
+ }
+
+ static CloudTabletRebalancerMetrics create() {
+ com.sun.management.ThreadMXBean threadMxBean =
+
ManagementFactory.getPlatformMXBean(com.sun.management.ThreadMXBean.class);
+ return new CloudTabletRebalancerMetrics(System::nanoTime,
createAllocatedBytesSupplier(threadMxBean));
+ }
+
+ Round startRound() {
+ return new Round(nanoTimeSupplier.getAsLong(),
allocatedBytesSupplier.getAsLong());
+ }
+
+ void finishRound(Round round, long tabletScanCount) {
+ long durationMs =
TimeUnit.NANOSECONDS.toMillis(nanoTimeSupplier.getAsLong() - round.startNanos);
+ long currentAllocatedBytes = allocatedBytesSupplier.getAsLong();
+ long allocatedBytes = round.startAllocatedBytes < 0L ||
currentAllocatedBytes < 0L
+ ? ALLOCATED_BYTES_UNAVAILABLE : currentAllocatedBytes -
round.startAllocatedBytes;
+ MetricRepo.updateCloudTabletRebalancerMetrics(durationMs,
allocatedBytes, tabletScanCount);
+ }
+
+ static LongSupplier
createAllocatedBytesSupplier(com.sun.management.ThreadMXBean threadMxBean) {
+ if (threadMxBean == null ||
!threadMxBean.isThreadAllocatedMemorySupported()) {
+ return () -> ALLOCATED_BYTES_UNAVAILABLE;
+ }
+ if (!threadMxBean.isThreadAllocatedMemoryEnabled()) {
+ try {
+ threadMxBean.setThreadAllocatedMemoryEnabled(true);
+ } catch (SecurityException | UnsupportedOperationException e) {
+ return () -> ALLOCATED_BYTES_UNAVAILABLE;
+ }
+ }
+ return threadMxBean::getCurrentThreadAllocatedBytes;
+ }
+
+ static final class Round {
+ private final long startNanos;
+ private final long startAllocatedBytes;
+
+ private Round(long startNanos, long startAllocatedBytes) {
+ this.startNanos = startNanos;
+ this.startAllocatedBytes = startAllocatedBytes;
+ }
+ }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/metric/CloudMetrics.java
b/fe/fe-core/src/main/java/org/apache/doris/metric/CloudMetrics.java
index 7649b3b1c67..a663348a27f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/metric/CloudMetrics.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/metric/CloudMetrics.java
@@ -55,6 +55,13 @@ public class CloudMetrics {
protected static AutoMappedMetric<LongCounterMetric>
CLUSTER_CLOUD_WARM_UP_CACHE_BALANCE_NUM;
protected static AutoMappedMetric<LongCounterMetric>
VIRTUAL_COMPUTE_GROUP_SWITCH_COUNTER;
+ protected static LongCounterMetric CLOUD_TABLET_REBALANCER_ROUND_TOTAL;
+ protected static LongCounterMetric
CLOUD_TABLET_REBALANCER_ALLOCATED_BYTES_TOTAL;
+ protected static GaugeMetricImpl<Long>
CLOUD_TABLET_REBALANCER_LAST_ROUND_ALLOCATED_BYTES;
+ protected static LongCounterMetric
CLOUD_TABLET_REBALANCER_DURATION_MS_TOTAL;
+ protected static GaugeMetricImpl<Long>
CLOUD_TABLET_REBALANCER_LAST_ROUND_DURATION_MS;
+ protected static LongCounterMetric
CLOUD_TABLET_REBALANCER_TABLET_SCAN_TOTAL;
+
// Per-method meta-service RPC metrics
public static AutoMappedMetric<LongCounterMetric> META_SERVICE_RPC_TOTAL;
public static AutoMappedMetric<LongCounterMetric> META_SERVICE_RPC_FAILED;
@@ -151,6 +158,8 @@ public class CloudMetrics {
"virtual_compute_group_switch_total", MetricUnit.NOUNIT,
"virtual compute group active standby switch count"));
+ initCloudTabletRebalancerMetrics();
+
// Per-method meta-service RPC metrics
META_SERVICE_RPC_TOTAL = MetricRepo.addLabeledMetrics("method", () ->
new LongCounterMetric("meta_service_rpc_total", MetricUnit.NOUNIT,
@@ -202,4 +211,32 @@ public class CloudMetrics {
MetricUnit.NOUNIT, "meta service RPC requests per second (all
methods)", 0.0);
MetricRepo.DORIS_METRIC_REGISTER.addMetrics(META_SERVICE_RPC_ALL_PER_SECOND);
}
+
+ static void initCloudTabletRebalancerMetrics() {
+ CLOUD_TABLET_REBALANCER_ROUND_TOTAL = new LongCounterMetric(
+ "cloud_tablet_rebalancer_round_total", MetricUnit.OPERATIONS,
+ "total cloud tablet rebalancer rounds");
+ CLOUD_TABLET_REBALANCER_ALLOCATED_BYTES_TOTAL = new LongCounterMetric(
+ "cloud_tablet_rebalancer_allocated_bytes_total",
MetricUnit.BYTES,
+ "total bytes allocated by cloud tablet rebalancer rounds");
+ CLOUD_TABLET_REBALANCER_LAST_ROUND_ALLOCATED_BYTES = new
GaugeMetricImpl<>(
+ "cloud_tablet_rebalancer_last_round_allocated_bytes",
MetricUnit.BYTES,
+ "bytes allocated by the last cloud tablet rebalancer round, or
-1 when unavailable", -1L);
+ CLOUD_TABLET_REBALANCER_DURATION_MS_TOTAL = new LongCounterMetric(
+ "cloud_tablet_rebalancer_duration_ms_total",
MetricUnit.MILLISECONDS,
+ "total cloud tablet rebalancer round duration in
milliseconds");
+ CLOUD_TABLET_REBALANCER_LAST_ROUND_DURATION_MS = new GaugeMetricImpl<>(
+ "cloud_tablet_rebalancer_last_round_duration_ms",
MetricUnit.MILLISECONDS,
+ "duration of the last cloud tablet rebalancer round in
milliseconds", 0L);
+ CLOUD_TABLET_REBALANCER_TABLET_SCAN_TOTAL = new LongCounterMetric(
+ "cloud_tablet_rebalancer_tablet_scan_total",
MetricUnit.OPERATIONS,
+ "total tablet route entries scanned by cloud tablet rebalancer
rounds");
+
+
MetricRepo.DORIS_METRIC_REGISTER.addMetrics(CLOUD_TABLET_REBALANCER_ROUND_TOTAL);
+
MetricRepo.DORIS_METRIC_REGISTER.addMetrics(CLOUD_TABLET_REBALANCER_ALLOCATED_BYTES_TOTAL);
+
MetricRepo.DORIS_METRIC_REGISTER.addMetrics(CLOUD_TABLET_REBALANCER_LAST_ROUND_ALLOCATED_BYTES);
+
MetricRepo.DORIS_METRIC_REGISTER.addMetrics(CLOUD_TABLET_REBALANCER_DURATION_MS_TOTAL);
+
MetricRepo.DORIS_METRIC_REGISTER.addMetrics(CLOUD_TABLET_REBALANCER_LAST_ROUND_DURATION_MS);
+
MetricRepo.DORIS_METRIC_REGISTER.addMetrics(CLOUD_TABLET_REBALANCER_TABLET_SCAN_TOTAL);
+ }
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/metric/MetricRepo.java
b/fe/fe-core/src/main/java/org/apache/doris/metric/MetricRepo.java
index c7399577310..b3a40988e24 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/metric/MetricRepo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/metric/MetricRepo.java
@@ -2253,6 +2253,21 @@ public final class MetricRepo {
MetricRepo.DORIS_METRIC_REGISTER.addMetrics(counter);
}
+ public static void updateCloudTabletRebalancerMetrics(long durationMs,
long allocatedBytes,
+ long
tabletScanCount) {
+ if (!MetricRepo.isInit || Config.isNotCloudMode()) {
+ return;
+ }
+ CloudMetrics.CLOUD_TABLET_REBALANCER_ROUND_TOTAL.increase(1L);
+
CloudMetrics.CLOUD_TABLET_REBALANCER_DURATION_MS_TOTAL.increase(durationMs);
+
CloudMetrics.CLOUD_TABLET_REBALANCER_LAST_ROUND_DURATION_MS.setValue(durationMs);
+
CloudMetrics.CLOUD_TABLET_REBALANCER_TABLET_SCAN_TOTAL.increase(tabletScanCount);
+
CloudMetrics.CLOUD_TABLET_REBALANCER_LAST_ROUND_ALLOCATED_BYTES.setValue(allocatedBytes);
+ if (allocatedBytes >= 0L) {
+
CloudMetrics.CLOUD_TABLET_REBALANCER_ALLOCATED_BYTES_TOTAL.increase(allocatedBytes);
+ }
+ }
+
public static void increaseVirtualComputeGroupSwitch(String
virtualComputeGroupId, String virtualComputeGroupName,
String
srcComputeGroupId, String srcComputeGroupName,
String
dstComputeGroupId, String dstComputeGroupName) {
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/cloud/catalog/CloudTabletRebalancerMetricsTest.java
b/fe/fe-core/src/test/java/org/apache/doris/cloud/catalog/CloudTabletRebalancerMetricsTest.java
new file mode 100644
index 00000000000..36e79c190b2
--- /dev/null
+++
b/fe/fe-core/src/test/java/org/apache/doris/cloud/catalog/CloudTabletRebalancerMetricsTest.java
@@ -0,0 +1,90 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.cloud.catalog;
+
+import org.apache.doris.metric.MetricRepo;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.LongSupplier;
+
+public class CloudTabletRebalancerMetricsTest {
+
+ @Test
+ public void testCreateUsesCurrentJvmThreadAllocationSupport() {
+ CloudTabletRebalancerMetrics metrics =
CloudTabletRebalancerMetrics.create();
+ Assertions.assertNotNull(metrics.startRound());
+ }
+
+ @Test
+ public void testAllocatedBytesSupplierHandlesJvmCapabilities() {
+ com.sun.management.ThreadMXBean unsupported =
Mockito.mock(com.sun.management.ThreadMXBean.class);
+
Mockito.when(unsupported.isThreadAllocatedMemorySupported()).thenReturn(false);
+ LongSupplier unsupportedSupplier =
CloudTabletRebalancerMetrics.createAllocatedBytesSupplier(unsupported);
+ Assertions.assertEquals(-1L, unsupportedSupplier.getAsLong());
+
+ com.sun.management.ThreadMXBean denied =
Mockito.mock(com.sun.management.ThreadMXBean.class);
+
Mockito.when(denied.isThreadAllocatedMemorySupported()).thenReturn(true);
+
Mockito.when(denied.isThreadAllocatedMemoryEnabled()).thenReturn(false);
+ Mockito.doThrow(new
SecurityException()).when(denied).setThreadAllocatedMemoryEnabled(true);
+ LongSupplier deniedSupplier =
CloudTabletRebalancerMetrics.createAllocatedBytesSupplier(denied);
+ Assertions.assertEquals(-1L, deniedSupplier.getAsLong());
+
+ com.sun.management.ThreadMXBean enabled =
Mockito.mock(com.sun.management.ThreadMXBean.class);
+
Mockito.when(enabled.isThreadAllocatedMemorySupported()).thenReturn(true);
+
Mockito.when(enabled.isThreadAllocatedMemoryEnabled()).thenReturn(true);
+
Mockito.when(enabled.getCurrentThreadAllocatedBytes()).thenReturn(1234L);
+ LongSupplier enabledSupplier =
CloudTabletRebalancerMetrics.createAllocatedBytesSupplier(enabled);
+ Assertions.assertEquals(1234L, enabledSupplier.getAsLong());
+ }
+
+ @Test
+ public void testFinishRoundRecordsDurationAllocationAndWork() {
+ AtomicLong nanoTime = new AtomicLong(1_000_000_000L);
+ AtomicLong allocatedBytes = new AtomicLong(10_000L);
+ CloudTabletRebalancerMetrics metrics =
+ new CloudTabletRebalancerMetrics(nanoTime::get,
allocatedBytes::get);
+
+ CloudTabletRebalancerMetrics.Round round = metrics.startRound();
+ nanoTime.set(1_012_000_000L);
+ allocatedBytes.set(10_777L);
+
+ try (MockedStatic<MetricRepo> metricRepo =
Mockito.mockStatic(MetricRepo.class)) {
+ metrics.finishRound(round, 42L);
+ metricRepo.verify(() ->
MetricRepo.updateCloudTabletRebalancerMetrics(12L, 777L, 42L));
+ }
+ }
+
+ @Test
+ public void testFinishRoundMarksAllocationUnavailable() {
+ AtomicLong nanoTime = new AtomicLong(2_000_000_000L);
+ CloudTabletRebalancerMetrics metrics = new
CloudTabletRebalancerMetrics(nanoTime::get, () -> -1L);
+
+ CloudTabletRebalancerMetrics.Round round = metrics.startRound();
+ nanoTime.set(2_003_000_000L);
+
+ try (MockedStatic<MetricRepo> metricRepo =
Mockito.mockStatic(MetricRepo.class)) {
+ metrics.finishRound(round, 7L);
+ metricRepo.verify(() ->
MetricRepo.updateCloudTabletRebalancerMetrics(3L, -1L, 7L));
+ }
+ }
+}
diff --git a/fe/fe-core/src/test/java/org/apache/doris/metric/MetricsTest.java
b/fe/fe-core/src/test/java/org/apache/doris/metric/MetricsTest.java
index 19b73fcc03f..f3c2a403d1d 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/metric/MetricsTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/metric/MetricsTest.java
@@ -250,6 +250,48 @@ public class MetricsTest {
}
}
+ @Test
+ public void testCloudTabletRebalancerMetrics() {
+ String originCloudUniqueId = Config.cloud_unique_id;
+ try {
+ Config.cloud_unique_id = "test_cloud_unique_id";
+ CloudMetrics.initCloudTabletRebalancerMetrics();
+
+ MetricRepo.updateCloudTabletRebalancerMetrics(125L, 4096L, 200L);
+
+ String metricResult = getPrometheusMetrics();
+ Assert.assertTrue(metricResult.contains("# TYPE
doris_fe_cloud_tablet_rebalancer_round_total counter"));
+
Assert.assertTrue(metricResult.contains("doris_fe_cloud_tablet_rebalancer_round_total
1"));
+ Assert.assertTrue(metricResult.contains(
+ "doris_fe_cloud_tablet_rebalancer_allocated_bytes_total
4096"));
+ Assert.assertTrue(metricResult.contains(
+
"doris_fe_cloud_tablet_rebalancer_last_round_allocated_bytes 4096"));
+ Assert.assertTrue(metricResult.contains(
+ "doris_fe_cloud_tablet_rebalancer_duration_ms_total 125"));
+ Assert.assertTrue(metricResult.contains(
+ "doris_fe_cloud_tablet_rebalancer_last_round_duration_ms
125"));
+ Assert.assertTrue(metricResult.contains(
+ "doris_fe_cloud_tablet_rebalancer_tablet_scan_total 200"));
+
+ MetricRepo.updateCloudTabletRebalancerMetrics(25L, -1L, 50L);
+
+ metricResult = getPrometheusMetrics();
+
Assert.assertTrue(metricResult.contains("doris_fe_cloud_tablet_rebalancer_round_total
2"));
+ Assert.assertTrue(metricResult.contains(
+ "doris_fe_cloud_tablet_rebalancer_allocated_bytes_total
4096"));
+ Assert.assertTrue(metricResult.contains(
+
"doris_fe_cloud_tablet_rebalancer_last_round_allocated_bytes -1"));
+ Assert.assertTrue(metricResult.contains(
+ "doris_fe_cloud_tablet_rebalancer_duration_ms_total 150"));
+ Assert.assertTrue(metricResult.contains(
+ "doris_fe_cloud_tablet_rebalancer_last_round_duration_ms
25"));
+ Assert.assertTrue(metricResult.contains(
+ "doris_fe_cloud_tablet_rebalancer_tablet_scan_total 250"));
+ } finally {
+ Config.cloud_unique_id = originCloudUniqueId;
+ }
+ }
+
@Test
public void testCloudWarmUpSyncJobMetricsReadStatsDirectlyFromJob() {
String oldCloudUniqueId = Config.cloud_unique_id;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]