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]

Reply via email to