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 e230e078bc6 [feature](fe) Let an FE declare and broadcast its local 
resource group (#65611)
e230e078bc6 is described below

commit e230e078bc6c48754a0405e3292942afad42f44e
Author: deardeng <[email protected]>
AuthorDate: Thu Jul 16 10:37:03 2026 +0800

    [feature](fe) Let an FE declare and broadcast its local resource group 
(#65611)
    
    Adds the FE-side topology metadata only. No scheduling, replica
    selection or load behavior changes.
    
    A FE can now declare which resource group (BE `tag.location`) it sits
    in, so that operators and later features can reason about cross-AZ /
    cross-IDC deployments:
    
    - `local_resource_group` FE config, overridable by the
    `--local_resource_group` start_fe.sh option or the
    `DORIS_LOCAL_RESOURCE_GROUP` environment variable. Precedence is command
    line > environment > fe.conf. The value must be a valid `tag.location`
    name, otherwise the FE refuses to start.
    - The value is reported through the FE heartbeat
    (TFrontendPingFrontendResult) and kept on Frontend as runtime-only
    state, so the master can see every FE's group.
    - Exposed as a new `LocalResourceGroup` column, appended at the end of
    `SHOW FRONTENDS` and `frontends()` so existing column positions do not
    move.
    
    Because the command line value has to override fe.conf, it can only be
    resolved once Config is loaded. DorisFE.parseArgs() is therefore split
    into parsing (parseArgs) and mode selection (buildCommandLineOptions).
    Both halves are still called at exactly the point where parseArgs() used
    to be, so the version / helper / image modes keep returning before the
    recovery and drop-backends system properties are applied, and those
    flags remain ignored in those modes as before. Only
    resolveLocalResourceGroup() runs after Config.init().
---
 bin/start_fe.sh                                    | 16 ++++---
 .../main/java/org/apache/doris/common/Config.java  |  7 ++++
 .../src/main/java/org/apache/doris/DorisFE.java    | 49 +++++++++++++++++++++-
 .../main/java/org/apache/doris/catalog/Env.java    | 20 +++++++++
 .../doris/common/proc/FrontendsProcNode.java       |  1 +
 .../apache/doris/service/FrontendServiceImpl.java  |  1 +
 .../java/org/apache/doris/system/Frontend.java     | 13 ++++++
 .../apache/doris/system/FrontendHbResponse.java    |  9 +++-
 .../java/org/apache/doris/system/HeartbeatMgr.java |  5 ++-
 .../FrontendsTableValuedFunction.java              |  3 +-
 gensrc/thrift/FrontendService.thrift               |  1 +
 .../tvf/test_frontends_tvf.groovy                  | 11 ++---
 12 files changed, 120 insertions(+), 16 deletions(-)

diff --git a/bin/start_fe.sh b/bin/start_fe.sh
index 941e8c5a52d..2de1145ac6f 100755
--- a/bin/start_fe.sh
+++ b/bin/start_fe.sh
@@ -31,6 +31,7 @@ OPTS="$(getopt \
     -l 'daemon' \
     -l 'helper:' \
     -l 'image:' \
+    -l 'local_resource_group:' \
     -l 'version' \
     -l 'metadata_failure_recovery' \
     -l 'recovery_journal_id:' \
@@ -47,6 +48,7 @@ HELPER=''
 IMAGE_PATH=''
 IMAGE_TOOL=''
 OPT_VERSION=''
+declare -a LOCAL_RESOURCE_GROUP_ARGS=()
 declare -a HELPER_ARGS=()
 declare -a METADATA_FAILURE_RECOVERY_ARGS=()
 declare -a RECOVERY_JOURNAL_ID_ARGS=()
@@ -83,6 +85,10 @@ while true; do
         IMAGE_PATH="$2"
         shift 2
         ;;
+    --local_resource_group)
+        LOCAL_RESOURCE_GROUP_ARGS=("--local_resource_group" "$2")
+        shift 2
+        ;;
     --cluster_snapshot)
         CLUSTER_SNAPSHOT_ARGS=("--cluster_snapshot" "$2")
         shift 2
@@ -428,23 +434,23 @@ fi
 
 if [[ "${OPT_VERSION}" != "" ]]; then
     export DORIS_LOG_TO_STDERR=1
-    ${LIMIT:+${LIMIT}} "${JAVA}" org.apache.doris.DorisFE --version
+    ${LIMIT:+${LIMIT}} "${JAVA}" org.apache.doris.DorisFE 
"${LOCAL_RESOURCE_GROUP_ARGS[@]}" --version
     exit 0
 fi
 
 if [[ "${IMAGE_TOOL}" -eq 1 ]]; then
     if [[ -n "${IMAGE_PATH}" ]]; then
-        ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE -i "${IMAGE_PATH}"
+        ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE 
"${LOCAL_RESOURCE_GROUP_ARGS[@]}" -i "${IMAGE_PATH}"
     else
         echo "Internal error, USE IMAGE_TOOL like: ./start_fe.sh --image 
image_path"
     fi
 elif [[ "${RUN_DAEMON}" -eq 1 ]]; then
-    nohup ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
-XX:-OmitStackTraceInFastThrow -XX:OnOutOfMemoryError="kill -9 %p" 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE "${HELPER_ARGS[@]}" 
"${METADATA_FAILURE_RECOVERY_ARGS[@]}" "${RECOVERY_JOURNAL_ID_ARGS[@]}" 
"${CLUSTER_SNAPSHOT_ARGS[@]}" "${DROP_BACKENDS_ARGS[@]}" "$@" 
>>"${STDOUT_LOGGER}" 2>&1 </dev/null &
+    nohup ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
-XX:-OmitStackTraceInFastThrow -XX:OnOutOfMemoryError="kill -9 %p" 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE "${HELPER_ARGS[@]}" 
"${LOCAL_RESOURCE_GROUP_ARGS[@]}" "${METADATA_FAILURE_RECOVERY_ARGS[@]}" 
"${RECOVERY_JOURNAL_ID_ARGS[@]}" "${CLUSTER_SNAPSHOT_ARGS[@]}" 
"${DROP_BACKENDS_ARGS[@]}" "$@" >>"${STDOUT_LOGGER}" 2>&1 </dev/null &
 elif [[ "${RUN_CONSOLE}" -eq 1 ]]; then
     export DORIS_LOG_TO_STDERR=1
-    ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
-XX:-OmitStackTraceInFastThrow -XX:OnOutOfMemoryError="kill -9 %p" 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE "${HELPER_ARGS[@]}" 
${OPT_VERSION:+${OPT_VERSION}} "${METADATA_FAILURE_RECOVERY_ARGS[@]}" 
"${RECOVERY_JOURNAL_ID_ARGS[@]}" "${CLUSTER_SNAPSHOT_ARGS[@]}" 
"${DROP_BACKENDS_ARGS[@]}" "$@" >>"${STDOUT_LOGGER}" </dev/null
+    ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
-XX:-OmitStackTraceInFastThrow -XX:OnOutOfMemoryError="kill -9 %p" 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE "${HELPER_ARGS[@]}" 
"${LOCAL_RESOURCE_GROUP_ARGS[@]}" ${OPT_VERSION:+${OPT_VERSION}} 
"${METADATA_FAILURE_RECOVERY_ARGS[@]}" "${RECOVERY_JOURNAL_ID_ARGS[@]}" 
"${CLUSTER_SNAPSHOT_ARGS[@]}" "${DROP_BACKENDS_ARGS[@]}" "$@" 
>>"${STDOUT_LOGGER}" </dev/null
 else
-    ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
-XX:-OmitStackTraceInFastThrow -XX:OnOutOfMemoryError="kill -9 %p" 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE "${HELPER_ARGS[@]}" 
${OPT_VERSION:+${OPT_VERSION}} "${METADATA_FAILURE_RECOVERY_ARGS[@]}" 
"${RECOVERY_JOURNAL_ID_ARGS[@]}" "${CLUSTER_SNAPSHOT_ARGS[@]}" 
"${DROP_BACKENDS_ARGS[@]}" "$@" >>"${STDOUT_LOGGER}" 2>&1 </dev/null
+    ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
-XX:-OmitStackTraceInFastThrow -XX:OnOutOfMemoryError="kill -9 %p" 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE "${HELPER_ARGS[@]}" 
"${LOCAL_RESOURCE_GROUP_ARGS[@]}" ${OPT_VERSION:+${OPT_VERSION}} 
"${METADATA_FAILURE_RECOVERY_ARGS[@]}" "${RECOVERY_JOURNAL_ID_ARGS[@]}" 
"${CLUSTER_SNAPSHOT_ARGS[@]}" "${DROP_BACKENDS_ARGS[@]}" "$@" 
>>"${STDOUT_LOGGER}" 2>&1 </dev/null
 fi
 
 if [[ "${OPT_VERSION}" != "" ]]; then
diff --git a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java 
b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
index 00526509177..39f29b958d5 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
@@ -135,6 +135,13 @@ public class Config extends ConfigBase {
             description = {"Whether to check for table lock leaks"})
     public static boolean check_table_lock_leaky = false;
 
+    @ConfField(mutable = false, description = {"当前 FE 节点所属的 Resource 
Group。可通过命令行参数 "
+            + "`--local_resource_group` 或环境变量 `DORIS_LOCAL_RESOURCE_GROUP` 
覆盖。空字符串表示未设置。",
+            "The Resource Group that the current FE node belongs to. It can be 
overridden by the "
+                    + "`--local_resource_group` command line option or the "
+                    + "`DORIS_LOCAL_RESOURCE_GROUP` environment variable. An 
empty string means unset."})
+    public static String local_resource_group = "";
+
     @ConfField(mutable = true, masterOnly = false,
             description = {"PreparedStatement stmtId starting position, used 
for testing only"})
     public static long prepared_stmt_start_id = -1;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java 
b/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java
index bda379dad2f..d313467b127 100755
--- a/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java
@@ -42,6 +42,7 @@ import org.apache.doris.qe.Coordinator;
 import org.apache.doris.qe.QeProcessorImpl;
 import org.apache.doris.qe.QeService;
 import org.apache.doris.qe.SimpleScheduler;
+import org.apache.doris.resource.Tag;
 import org.apache.doris.service.ExecuteEnv;
 import org.apache.doris.service.FrontendOptions;
 import org.apache.doris.tls.server.FeServerStarterFactory;
@@ -89,6 +90,8 @@ public class DorisFE {
     private static String LOCK_FILE_PATH;
 
     private static final String LOCK_FILE_NAME = "process.lock";
+    private static final String LOCAL_RESOURCE_GROUP_ENV = 
"DORIS_LOCAL_RESOURCE_GROUP";
+    private static String effectiveLocalResourceGroupSource = "DEFAULT";
     private static FileChannel processLockFileChannel;
     private static FileLock processFileLock;
 
@@ -136,7 +139,8 @@ public class DorisFE {
             return;
         }
 
-        CommandLineOptions cmdLineOpts = parseArgs(args);
+        CommandLine commandLine = parseArgs(args);
+        CommandLineOptions cmdLineOpts = buildCommandLineOptions(commandLine);
 
         try {
             // init config
@@ -146,6 +150,9 @@ public class DorisFE {
             // Because the path of custom config file is defined in fe.conf
             config.initCustom(Config.custom_config_dir + "/fe_custom.conf");
 
+            // The command line value overrides fe.conf, so this can only run 
once Config is loaded.
+            resolveLocalResourceGroup(commandLine);
+
             LdapConfig ldapConfig = new LdapConfig();
             if (new File(dorisHomeDir + "/conf/ldap.conf").exists()) {
                 ldapConfig.init(dorisHomeDir + "/conf/ldap.conf");
@@ -164,6 +171,8 @@ public class DorisFE {
                 Log4jConfig.foreground = true;
             }
             Log4jConfig.initLogging(dorisHomeDir + "/conf/");
+            LOG.info("effective local_resource_group={}, source={}",
+                    Config.local_resource_group, 
effectiveLocalResourceGroupSource);
             // Add shutdown hook for graceful exit
             Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                 LOG.info("Received shutdown signal, starting graceful 
shutdown...");
@@ -361,7 +370,7 @@ public class DorisFE {
      *              Specify the meta version to decode log value
      *
      */
-    private static CommandLineOptions parseArgs(String[] args) {
+    private static CommandLine parseArgs(String[] args) {
         CommandLineParser commandLineParser = new DefaultParser();
         Options options = new Options();
         options.addOption("v", "version", false, "Print the version of Doris 
Frontend");
@@ -382,6 +391,8 @@ public class DorisFE {
         options.addOption("c", "cluster_snapshot", true, "Specify the cluster 
snapshot json file");
         
options.addOption(Option.builder().longOpt(FeConstants.DROP_BACKENDS_KEY)
                 .desc("When this FE becomes MASTER, drop all backends from 
cluster metadata (destructive)").build());
+        options.addOption(null, "local_resource_group", true,
+                "Specify the local resource group for the current FE");
 
         CommandLine cmd = null;
         try {
@@ -392,6 +403,12 @@ public class DorisFE {
             System.exit(-1);
         }
 
+        return cmd;
+    }
+
+    // Keeps the original decision order: the version / helper / image modes 
return before the
+    // recovery and drop-backends system properties are applied, so those 
flags stay ignored there.
+    private static CommandLineOptions buildCommandLineOptions(CommandLine cmd) 
{
         // version
         if (cmd.hasOption('v') || cmd.hasOption("version")) {
             return new CommandLineOptions(true, "", null, "");
@@ -494,6 +511,34 @@ public class DorisFE {
         return new CommandLineOptions(false, null, null, "");
     }
 
+    // Precedence: command line option, environment variable, fe.conf.
+    private static void resolveLocalResourceGroup(CommandLine cmd) {
+        String localResourceGroup = 
Strings.nullToEmpty(Config.local_resource_group);
+        String source = localResourceGroup.isEmpty() ? "DEFAULT" : "FE_CONF";
+        if (System.getenv().containsKey(LOCAL_RESOURCE_GROUP_ENV)) {
+            localResourceGroup = 
Strings.nullToEmpty(System.getenv(LOCAL_RESOURCE_GROUP_ENV));
+            source = "ENV";
+        }
+        if (cmd.hasOption("local_resource_group")) {
+            localResourceGroup = 
Strings.nullToEmpty(cmd.getOptionValue("local_resource_group"));
+            source = "CMDLINE";
+        }
+
+        Config.local_resource_group = localResourceGroup;
+        if (!localResourceGroup.isEmpty()) {
+            try {
+                // Must be a valid tag.location value, it is matched against 
the backends' location tag.
+                Tag.create(Tag.TYPE_LOCATION, localResourceGroup);
+            } catch (Exception e) {
+                // Logging is not initialized yet at this point, so report on 
stderr.
+                System.err.println("Invalid local_resource_group: " + 
localResourceGroup + ", " + e.getMessage());
+                System.exit(-1);
+            }
+        }
+        // Logging is initialized later; the effective value is logged there.
+        effectiveLocalResourceGroupSource = source;
+    }
+
     private static void printVersion() {
         LogUtils.stdout("Build version: " + Version.DORIS_BUILD_VERSION);
         LogUtils.stdout("Build time: " + Version.DORIS_BUILD_TIME);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
index 4c5937e4e55..dc8cac76500 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
@@ -1242,6 +1242,7 @@ public class Env {
         // 3. Load image first and replay edits
         this.editLog = new EditLog(nodeName);
         loadImage(this.imageDir); // load image file
+        seedSelfLocalResourceGroup();
         migrateConstraintsFromTables(); // migrate old table-based constraints
         editLog.open(); // open bdb env
         this.globalTransactionMgr.setEditLog(editLog);
@@ -1272,6 +1273,23 @@ public class Env {
         StmtExecutor.initBlockSqlAstNames();
     }
 
+    private static void seedSelfLocalResourceGroup() {
+        Env env = getCurrentEnv();
+        String selfNodeName = env.getNodeName();
+        if (Strings.isNullOrEmpty(selfNodeName)) {
+            LOG.debug("skip seeding local resource group because self node 
name is not initialized");
+            return;
+        }
+
+        Frontend selfFrontend = env.frontends.get(selfNodeName);
+        if (selfFrontend == null) {
+            LOG.debug("skip seeding local resource group because self frontend 
{} is not found", selfNodeName);
+            return;
+        }
+
+        selfFrontend.setLocalResourceGroup(Config.local_resource_group);
+    }
+
     // wait until FE is ready.
     public void waitForReady() throws InterruptedException {
         long counter = 0;
@@ -1392,6 +1410,7 @@ public class Env {
                 isFirstTimeStartUp = true;
                 Frontend self = new Frontend(role, nodeName, 
selfNode.getHost(),
                         selfNode.getPort());
+                self.setLocalResourceGroup(Config.local_resource_group);
                 // Set self alive to true, the 
BDBEnvironment.getReplicationGroupAdmin() will rely on this to get
                 // helper node, before the heartbeat thread is started.
                 self.setIsAlive(true);
@@ -1874,6 +1893,7 @@ public class Env {
 
             MetricRepo.init();
 
+            seedSelfLocalResourceGroup();
             toMasterProgress = "finished";
             canRead.set(true);
             isReady.set(true);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/common/proc/FrontendsProcNode.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/proc/FrontendsProcNode.java
index 58fc49ae4c3..7b780314411 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/common/proc/FrontendsProcNode.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/common/proc/FrontendsProcNode.java
@@ -164,6 +164,7 @@ public class FrontendsProcNode implements ProcNodeInterface 
{
             // To indicate which FE we currently connected
             info.add(fe.getHost().equals(selfNode) ? "Yes" : "No");
             info.add(TimeUtils.longToTimeString(fe.getLiveSince()));
+            info.add(fe.getLocalResourceGroup());
 
             infos.add(info);
         }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java 
b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
index ef405f907a1..b737ed2bc94 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
@@ -3327,6 +3327,7 @@ public class FrontendServiceImpl implements 
FrontendService.Iface {
                 result.setRpcPort(Config.rpc_port);
                 result.setArrowFlightSqlPort(Config.arrow_flight_sql_port);
                 result.setVersion(Version.DORIS_BUILD_VERSION + "-" + 
Version.DORIS_BUILD_SHORT_HASH);
+                result.setLocalResourceGroup(Config.local_resource_group);
                 result.setLastStartupTime(exeEnv.getStartupTime());
                 result.setProcessUUID(exeEnv.getProcessUUID());
                 if (exeEnv.getDiskInfos() != null) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/system/Frontend.java 
b/fe/fe-core/src/main/java/org/apache/doris/system/Frontend.java
index 2de174c86ef..62970a9315c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/system/Frontend.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/system/Frontend.java
@@ -50,6 +50,7 @@ public class Frontend implements Writable {
     private String cloudUniqueId;
 
     private String version;
+    private transient String localResourceGroup = "";
 
     private int queryPort;
     private int rpcPort;
@@ -92,6 +93,10 @@ public class Frontend implements Writable {
         return version;
     }
 
+    public String getLocalResourceGroup() {
+        return localResourceGroup;
+    }
+
     public String getNodeName() {
         return nodeName;
     }
@@ -152,6 +157,10 @@ public class Frontend implements Writable {
         this.cloudUniqueId = cloudUniqueId;
     }
 
+    public void setLocalResourceGroup(String localResourceGroup) {
+        this.localResourceGroup = localResourceGroup;
+    }
+
     public String getCloudUniqueId() {
         return cloudUniqueId;
     }
@@ -183,6 +192,9 @@ public class Frontend implements Writable {
             heartbeatErrMsg = "";
             lastStartupTime = hbResponse.getFeStartTime();
             diskInfos = hbResponse.getDiskInfos();
+            if (hbResponse.getLocalResourceGroup() != null) {
+                setLocalResourceGroup(hbResponse.getLocalResourceGroup());
+            }
             isChanged = true;
             processUUID = hbResponse.getProcessUUID();
         } else {
@@ -196,6 +208,7 @@ public class Frontend implements Writable {
                 isChanged = true;
             }
             heartbeatErrMsg = hbResponse.getMsg() == null ? "Unknown error" : 
hbResponse.getMsg();
+            setLocalResourceGroup("");
         }
         return isChanged;
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/system/FrontendHbResponse.java 
b/fe/fe-core/src/main/java/org/apache/doris/system/FrontendHbResponse.java
index be8eecfc193..3a16cfd5a97 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/system/FrontendHbResponse.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/system/FrontendHbResponse.java
@@ -44,6 +44,7 @@ public class FrontendHbResponse extends HeartbeatResponse 
implements Writable {
     private long feStartTime;
     private long processUUID;
     private List<FeDiskInfo> diskInfos;
+    private String localResourceGroup;
 
     public FrontendHbResponse() {
         super(HeartbeatResponse.Type.FRONTEND);
@@ -52,7 +53,7 @@ public class FrontendHbResponse extends HeartbeatResponse 
implements Writable {
     public FrontendHbResponse(String name, int queryPort, int rpcPort, int 
arrowFlightSqlPort,
             long replayedJournalId, long hbTime, String version,
             long feStartTime, List<FeDiskInfo> diskInfos,
-            long processUUID) {
+            long processUUID, String localResourceGroup) {
         super(HeartbeatResponse.Type.FRONTEND);
         this.status = HbStatus.OK;
         this.name = name;
@@ -65,6 +66,7 @@ public class FrontendHbResponse extends HeartbeatResponse 
implements Writable {
         this.feStartTime = feStartTime;
         this.diskInfos = diskInfos;
         this.processUUID = processUUID;
+        this.localResourceGroup = localResourceGroup;
     }
 
     public FrontendHbResponse(String name, String errMsg) {
@@ -111,6 +113,10 @@ public class FrontendHbResponse extends HeartbeatResponse 
implements Writable {
         return diskInfos;
     }
 
+    public String getLocalResourceGroup() {
+        return localResourceGroup;
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -123,6 +129,7 @@ public class FrontendHbResponse extends HeartbeatResponse 
implements Writable {
         sb.append(", replayedJournalId: ").append(replayedJournalId);
         sb.append(", feStartTime: ").append(feStartTime);
         sb.append(", processUUID: ").append(processUUID);
+        sb.append(", localResourceGroup: ").append(localResourceGroup);
         return sb.toString();
     }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/system/HeartbeatMgr.java 
b/fe/fe-core/src/main/java/org/apache/doris/system/HeartbeatMgr.java
index f23af939399..dbd36715d53 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/system/HeartbeatMgr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/system/HeartbeatMgr.java
@@ -419,7 +419,7 @@ public class HeartbeatMgr extends MasterDaemon {
                             System.currentTimeMillis(),
                             Version.DORIS_BUILD_VERSION + "-" + 
Version.DORIS_BUILD_SHORT_HASH,
                             ExecuteEnv.getInstance().getStartupTime(), 
ExecuteEnv.getInstance().getDiskInfos(),
-                            ExecuteEnv.getInstance().getProcessUUID());
+                            ExecuteEnv.getInstance().getProcessUUID(), 
Config.local_resource_group);
                 } else {
                     return new FrontendHbResponse(fe.getNodeName(), "not 
ready");
                 }
@@ -442,7 +442,8 @@ public class HeartbeatMgr extends MasterDaemon {
                     return new FrontendHbResponse(fe.getNodeName(), 
result.getQueryPort(),
                             result.getRpcPort(), 
result.getArrowFlightSqlPort(), result.getReplayedJournalId(),
                             System.currentTimeMillis(), result.getVersion(), 
result.getLastStartupTime(),
-                            FeDiskInfo.fromThrifts(result.getDiskInfos()), 
result.getProcessUUID());
+                            FeDiskInfo.fromThrifts(result.getDiskInfos()), 
result.getProcessUUID(),
+                            result.getLocalResourceGroup());
                 } else {
                     return new FrontendHbResponse(fe.getNodeName(), 
result.getMsg());
                 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsTableValuedFunction.java
 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsTableValuedFunction.java
index 05b709cd523..9df36a534a5 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsTableValuedFunction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsTableValuedFunction.java
@@ -64,7 +64,8 @@ public class FrontendsTableValuedFunction extends 
MetadataTableValuedFunction {
             new Column("ErrMsg", ScalarType.createStringType()),
             new Column("Version", ScalarType.createStringType()),
             new Column("CurrentConnected", ScalarType.createStringType()),
-            new Column("LiveSince", ScalarType.createStringType())
+            new Column("LiveSince", ScalarType.createStringType()),
+            new Column("LocalResourceGroup", ScalarType.createStringType())
     );
     private static final ImmutableMap<String, Integer> COLUMN_TO_INDEX;
     private static final ImmutableList<String> TITLE_NAMES;
diff --git a/gensrc/thrift/FrontendService.thrift 
b/gensrc/thrift/FrontendService.thrift
index 2bc093da9b9..33c0a117821 100644
--- a/gensrc/thrift/FrontendService.thrift
+++ b/gensrc/thrift/FrontendService.thrift
@@ -864,6 +864,7 @@ struct TFrontendPingFrontendResult {
     8: optional list<TDiskInfo> diskInfos
     9: optional i64 processUUID
     10: optional i32 arrowFlightSqlPort
+    11: optional string localResourceGroup
 }
 
 struct TPropertyVal {
diff --git 
a/regression-test/suites/external_table_p0/tvf/test_frontends_tvf.groovy 
b/regression-test/suites/external_table_p0/tvf/test_frontends_tvf.groovy
index 24bc167f6c2..3f51be591b2 100644
--- a/regression-test/suites/external_table_p0/tvf/test_frontends_tvf.groovy
+++ b/regression-test/suites/external_table_p0/tvf/test_frontends_tvf.groovy
@@ -20,7 +20,7 @@ suite("test_frontends_tvf", "p0,external") {
     List<List<Object>> table =  sql """ select * from `frontends`(); """
     logger.info("${table}")
     assertTrue(table.size() > 0)
-    assertTrue(table[0].size() == 20)
+    assertTrue(table[0].size() == 21)
 
     List<List<Object>> titleNames =  sql """ describe function frontends(); """
     assertTrue(titleNames[0][0] == "Name")
@@ -43,6 +43,7 @@ suite("test_frontends_tvf", "p0,external") {
     assertTrue(titleNames[17][0] == "Version")
     assertTrue(titleNames[18][0] == "CurrentConnected")
     assertTrue(titleNames[19][0] == "LiveSince")
+    assertTrue(titleNames[20][0] == "LocalResourceGroup")
 
     // filter columns
     table = sql """ select Name from `frontends`();"""
@@ -65,10 +66,10 @@ suite("test_frontends_tvf", "p0,external") {
     def res = sql """ select count(*) from frontends() where alive = 'true'; 
"""
     assertTrue(res[0][0] > 0)
 
-    sql """ select Name, Host, EditLogPort
-            HttpPort, QueryPort, RpcPort, ArrowFlightSqlPort, `Role`, 
IsMaster, ClusterId
-            `Join`, Alive, ReplayedJournalId, LastHeartbeat
-            IsHelper, ErrMsg, Version, CurrentConnected, LiveSince from 
frontends();
+    sql """ select Name, Host, EditLogPort, HttpPort, QueryPort, RpcPort, 
ArrowFlightSqlPort,
+            `Role`, IsMaster, ClusterId, `Join`, Alive, ReplayedJournalId, 
LastStartTime,
+            LastHeartbeat, IsHelper, ErrMsg, Version, CurrentConnected, 
LiveSince,
+            LocalResourceGroup from frontends();
     """
 
     // test exception


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to