This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.1 by this push:
new 98805e7796b branch-4.1: [feature](fe) Add connection max metrics
#64742 (#64785)
98805e7796b is described below
commit 98805e7796b6f9374bdeffa629c6c6241bb42bd0
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Jun 26 14:18:49 2026 +0800
branch-4.1: [feature](fe) Add connection max metrics #64742 (#64785)
Cherry-picked from #64742
Co-authored-by: morrySnow <[email protected]>
---
.../java/org/apache/doris/metric/MetricRepo.java | 74 ++++++++++++++++++++++
.../org/apache/doris/mysql/privilege/Auth.java | 14 ++++
.../doris/mysql/privilege/UserPropertyMgr.java | 8 +++
.../java/org/apache/doris/metric/MetricsTest.java | 51 +++++++++++++++
4 files changed, 147 insertions(+)
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 e6b2808b274..1d6e982861f 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
@@ -49,6 +49,7 @@ import
org.apache.doris.mtmv.MTMVPartitionInfo.MTMVPartitionType;
import org.apache.doris.mtmv.MTMVRefreshEnum.RefreshMethod;
import org.apache.doris.mtmv.MTMVRefreshEnum.RefreshTrigger;
import org.apache.doris.mtmv.MTMVUtil;
+import org.apache.doris.mysql.privilege.Auth;
import org.apache.doris.nereids.NereidsPlanner;
import org.apache.doris.persist.EditLog;
import org.apache.doris.qe.QeProcessorImpl;
@@ -131,6 +132,10 @@ public final class MetricRepo {
public static AutoMappedMetric<HistogramMetric> USER_HISTO_QUERY_LATENCY;
public static AutoMappedMetric<GaugeMetricImpl<Long>>
USER_GAUGE_QUERY_INSTANCE_NUM;
public static AutoMappedMetric<GaugeMetricImpl<Integer>>
USER_GAUGE_CONNECTIONS;
+ public static AutoMappedMetric<GaugeMetricImpl<Long>>
USER_GAUGE_CONNECTION_MAX;
+ public static GaugeMetric<Integer> GAUGE_ARROW_FLIGHT_CONNECTIONS;
+ public static GaugeMetric<Integer> GAUGE_ARROW_FLIGHT_CONNECTION_MAX;
+ public static GaugeMetric<Integer> GAUGE_CONNECTION_MAX;
public static AutoMappedMetric<LongCounterMetric>
USER_COUNTER_QUERY_INSTANCE_BEGIN;
public static AutoMappedMetric<LongCounterMetric> BE_COUNTER_QUERY_RPC_ALL;
public static AutoMappedMetric<LongCounterMetric>
BE_COUNTER_QUERY_RPC_FAILED;
@@ -420,6 +425,9 @@ public final class MetricRepo {
USER_GAUGE_CONNECTIONS = addLabeledMetrics("user", () ->
new GaugeMetricImpl<>("connection_total",
MetricUnit.CONNECTIONS,
"total connections", 0));
+ USER_GAUGE_CONNECTION_MAX = addLabeledMetrics("user", () ->
+ new GaugeMetricImpl<>("user_connection_max",
MetricUnit.CONNECTIONS,
+ "max connections for single user", 0L));
GaugeMetric<Integer> connections = new
GaugeMetric<Integer>("connection_total",
MetricUnit.CONNECTIONS, "total connections") {
@Override
@@ -430,6 +438,31 @@ public final class MetricRepo {
}
};
DORIS_METRIC_REGISTER.addMetrics(connections);
+ GAUGE_ARROW_FLIGHT_CONNECTIONS = new
GaugeMetric<Integer>("arrow_flight_connection_total",
+ MetricUnit.CONNECTIONS, "total arrow flight connections") {
+ @Override
+ public Integer getValue() {
+ return
ExecuteEnv.getInstance().getScheduler().getFlightSqlConnectPoolMgr().getConnectionNum();
+ }
+ };
+ DORIS_METRIC_REGISTER.addMetrics(GAUGE_ARROW_FLIGHT_CONNECTIONS);
+ GAUGE_CONNECTION_MAX = new GaugeMetric<Integer>("connection_max",
+ MetricUnit.CONNECTIONS, "max connections") {
+ @Override
+ public Integer getValue() {
+ return Config.qe_max_connection +
Config.arrow_flight_max_connections;
+ }
+ };
+ DORIS_METRIC_REGISTER.addMetrics(GAUGE_CONNECTION_MAX);
+ GAUGE_ARROW_FLIGHT_CONNECTION_MAX = new
GaugeMetric<Integer>("arrow_flight_connection_max",
+ MetricUnit.CONNECTIONS, "max arrow flight connections") {
+ @Override
+ public Integer getValue() {
+ return Config.arrow_flight_max_connections;
+ }
+ };
+ DORIS_METRIC_REGISTER.addMetrics(GAUGE_ARROW_FLIGHT_CONNECTION_MAX);
+ syncUserConnectionMaxMetrics();
// journal id
GaugeMetric<Long> maxJournalId = new
GaugeMetric<Long>("max_journal_id", MetricUnit.NOUNIT,
@@ -1597,6 +1630,47 @@ public final class MetricRepo {
});
}
+ public static void syncUserConnectionMaxMetrics() {
+ if (USER_GAUGE_CONNECTION_MAX == null) {
+ return;
+ }
+ Env.getServingEnv().getAuth().getMaxConnForAllUsers()
+ .forEach(MetricRepo::updateUserConnectionMaxMetric);
+ }
+
+ public static void updateUserConnectionMaxMetric(Auth auth, String user,
long maxConn) {
+ if (USER_GAUGE_CONNECTION_MAX == null || Env.getServingEnv().getAuth()
!= auth) {
+ return;
+ }
+ updateUserConnectionMaxMetric(user, maxConn);
+ }
+
+ public static void updateUserConnectionMaxMetric(String user, long
maxConn) {
+ if (USER_GAUGE_CONNECTION_MAX == null) {
+ return;
+ }
+ USER_GAUGE_CONNECTION_MAX.getOrAdd(user).setValue(maxConn);
+ }
+
+ public static void removeUserConnectionMaxMetric(Auth auth, String user) {
+ if (USER_GAUGE_CONNECTION_MAX == null || Env.getServingEnv().getAuth()
!= auth) {
+ return;
+ }
+ removeUserConnectionMaxMetric(user);
+ }
+
+ public static void removeUserConnectionMaxMetric(String user) {
+ if (USER_GAUGE_CONNECTION_MAX == null) {
+ return;
+ }
+ GaugeMetricImpl<Long> metric =
USER_GAUGE_CONNECTION_MAX.getMetrics().get(user);
+ if (metric == null) {
+ return;
+ }
+ DORIS_METRIC_REGISTER.removeMetricsByNameAndLabels(metric.getName(),
metric.getLabels());
+ USER_GAUGE_CONNECTION_MAX.remove(user);
+ }
+
public static void visitHistograms(MetricVisitor visitor) {
SortedMap<String, Histogram> histograms =
METRIC_REGISTER.getHistograms();
for (Map.Entry<String, Histogram> entry : histograms.entrySet()) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java
b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java
index b3cc5430383..128927238fc 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java
@@ -45,6 +45,7 @@ import org.apache.doris.common.UserException;
import org.apache.doris.common.io.Writable;
import org.apache.doris.datasource.CatalogIf;
import org.apache.doris.datasource.InternalCatalog;
+import org.apache.doris.metric.MetricRepo;
import org.apache.doris.mysql.MysqlPassword;
import org.apache.doris.mysql.authenticate.AuthenticateType;
import org.apache.doris.mysql.authenticate.ldap.LdapManager;
@@ -555,6 +556,8 @@ public class Auth implements Writable {
}
// other user properties
propertyMgr.addUserResource(userIdent.getQualifiedUser());
+ MetricRepo.updateUserConnectionMaxMetric(this,
userIdent.getQualifiedUser(),
+ propertyMgr.getMaxConn(userIdent.getQualifiedUser()));
// 5. update password policy
passwdPolicyManager.updatePolicy(userIdent, password,
passwordOptions);
@@ -609,6 +612,7 @@ public class Auth implements Writable {
userManager.removeUser(userIdent);
if
(CollectionUtils.isEmpty(userManager.getUserByName(userIdent.getQualifiedUser())))
{
propertyMgr.dropUser(userIdent);
+ MetricRepo.removeUserConnectionMaxMetric(this,
userIdent.getQualifiedUser());
}
if (!isReplay) {
@@ -1162,6 +1166,7 @@ public class Auth implements Writable {
writeLock();
try {
propertyMgr.updateUserProperty(user, properties, isReplay);
+ MetricRepo.updateUserConnectionMaxMetric(this, user,
propertyMgr.getMaxConn(user));
if (!isReplay) {
UserPropertyInfo propertyInfo = new UserPropertyInfo(user,
properties);
Env.getCurrentEnv().getEditLog().logUpdateUserProperty(propertyInfo);
@@ -1187,6 +1192,15 @@ public class Auth implements Writable {
}
}
+ public Map<String, Long> getMaxConnForAllUsers() {
+ readLock();
+ try {
+ return propertyMgr.getMaxConnForAllUsers();
+ } finally {
+ readUnlock();
+ }
+ }
+
public int getQueryTimeout(String qualifiedUser) {
readLock();
try {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserPropertyMgr.java
b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserPropertyMgr.java
index 3cef9ceaea6..646194f7478 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserPropertyMgr.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserPropertyMgr.java
@@ -119,6 +119,14 @@ public class UserPropertyMgr implements Writable {
return existProperty.getMaxConn();
}
+ public Map<String, Long> getMaxConnForAllUsers() {
+ Map<String, Long> maxConnByUser = Maps.newHashMap();
+ for (Entry<String, UserProperty> entry : propertyMap.entrySet()) {
+ maxConnByUser.put(entry.getKey(), entry.getValue().getMaxConn());
+ }
+ return maxConnByUser;
+ }
+
public long getMaxQueryInstances(String qualifiedUser) {
UserProperty existProperty = propertyMap.get(qualifiedUser);
existProperty = getPropertyIfNull(qualifiedUser, existProperty);
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 0fe7d33b2e6..19b73fcc03f 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
@@ -17,14 +17,18 @@
package org.apache.doris.metric;
+import org.apache.doris.catalog.Env;
import org.apache.doris.cloud.CloudWarmUpJob;
import org.apache.doris.cloud.JobWarmUpStats;
import org.apache.doris.common.Config;
import org.apache.doris.common.FeConstants;
+import org.apache.doris.common.Pair;
import org.apache.doris.common.util.JsonUtil;
import org.apache.doris.metric.Metric.MetricUnit;
import org.apache.doris.monitor.jvm.JvmService;
import org.apache.doris.monitor.jvm.JvmStats;
+import org.apache.doris.mysql.privilege.Auth;
+import org.apache.doris.mysql.privilege.UserProperty;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;
@@ -69,6 +73,53 @@ public class MetricsTest {
}
}
+ @Test
+ public void testConnectionMaxMetrics() throws Exception {
+ int originQeMaxConnection = Config.qe_max_connection;
+ int originArrowFlightMaxConnections =
Config.arrow_flight_max_connections;
+ try {
+ Config.qe_max_connection = 4321;
+ Config.arrow_flight_max_connections = 8765;
+ MetricRepo.updateUserConnectionMaxMetric("metric_user", 321L);
+
+ MetricVisitor visitor = new PrometheusMetricVisitor();
+ MetricRepo.DORIS_METRIC_REGISTER.accept(visitor);
+ String metricResult = visitor.finish();
+ Assert.assertTrue(metricResult.contains("# TYPE
doris_fe_connection_max gauge"));
+ Assert.assertTrue(metricResult.contains("doris_fe_connection_max
13086"));
+ Assert.assertTrue(metricResult.contains("# TYPE
doris_fe_arrow_flight_connection_total gauge"));
+
Assert.assertTrue(metricResult.contains("doris_fe_arrow_flight_connection_total
0"));
+ Assert.assertTrue(metricResult.contains("# TYPE
doris_fe_arrow_flight_connection_max gauge"));
+
Assert.assertTrue(metricResult.contains("doris_fe_arrow_flight_connection_max
8765"));
+ Assert.assertTrue(metricResult.contains("# TYPE
doris_fe_user_connection_max gauge"));
+
Assert.assertTrue(metricResult.contains("doris_fe_user_connection_max{user=\"metric_user\"}
321"));
+
+
Env.getServingEnv().getAuth().updateUserPropertyInternal(Auth.ROOT_USER,
Lists.newArrayList(
+ Pair.of(UserProperty.PROP_MAX_USER_CONNECTIONS, "456")),
true);
+
+ visitor = new PrometheusMetricVisitor();
+ MetricRepo.DORIS_METRIC_REGISTER.accept(visitor);
+ metricResult = visitor.finish();
+
Assert.assertTrue(metricResult.contains("doris_fe_user_connection_max{user=\"root\"}
456"));
+
+ Auth auth = new Auth();
+ auth.updateUserPropertyInternal(Auth.ROOT_USER, Lists.newArrayList(
+ Pair.of(UserProperty.PROP_MAX_USER_CONNECTIONS, "789")),
true);
+
+ visitor = new PrometheusMetricVisitor();
+ MetricRepo.DORIS_METRIC_REGISTER.accept(visitor);
+ metricResult = visitor.finish();
+
Assert.assertTrue(metricResult.contains("doris_fe_user_connection_max{user=\"root\"}
456"));
+
Assert.assertFalse(metricResult.contains("doris_fe_user_connection_max{user=\"root\"}
789"));
+ } finally {
+ Config.qe_max_connection = originQeMaxConnection;
+ Config.arrow_flight_max_connections =
originArrowFlightMaxConnections;
+ MetricRepo.removeUserConnectionMaxMetric("metric_user");
+
Env.getServingEnv().getAuth().updateUserPropertyInternal(Auth.ROOT_USER,
Lists.newArrayList(
+ Pair.of(UserProperty.PROP_MAX_USER_CONNECTIONS, "100")),
true);
+ }
+ }
+
@Test
public void testUserQueryMetrics() {
MetricRepo.USER_COUNTER_QUERY_ALL.getOrAdd("test_user").increase(1L);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]