diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/proc/BackendsProcDir.java b/fe/fe-core/src/main/java/org/apache/doris/common/proc/BackendsProcDir.java index 92ef9f09e0377c..a7c59ec8c376e9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/proc/BackendsProcDir.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/proc/BackendsProcDir.java @@ -26,12 +26,12 @@ import org.apache.doris.common.util.TimeUtils; import org.apache.doris.system.Backend; import org.apache.doris.system.SystemInfoService; +import org.apache.doris.tablefunction.BackendsTableValuedFunction; import org.apache.doris.thrift.TUnit; import com.google.common.base.Preconditions; import com.google.common.base.Stopwatch; import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.gson.Gson; import org.apache.logging.log4j.LogManager; @@ -45,19 +45,6 @@ public class BackendsProcDir implements ProcDirInterface { private static final Logger LOG = LogManager.getLogger(BackendsProcDir.class); - public static final ImmutableList TITLE_NAMES = new ImmutableList.Builder().add("BackendId") - .add("Host").add("HeartbeatPort").add("BePort").add("HttpPort").add("BrpcPort").add("ArrowFlightSqlPort") - .add("LastStartTime").add("LastHeartbeat").add("Alive").add("SystemDecommissioned").add("TabletNum") - .add("DataUsedCapacity").add("TrashUsedCapacity").add("AvailCapacity").add("TotalCapacity").add("UsedPct") - .add("MaxDiskUsedPct").add("RemoteUsedCapacity").add("Tag").add("ErrMsg").add("Version").add("Status") - .add("HeartbeatFailureCounter").add("NodeRole").add("CpuCores").add("Memory").add("LiveSince") - .add("RunningTasks").build(); - - public static final ImmutableList DISK_TITLE_NAMES = new ImmutableList.Builder() - .add("BackendId").add("Host").add("RootPath").add("DirType").add("DiskState") - .add("TotalCapacity").add("UsedCapacity").add("AvailableCapacity").add("UsedPct") - .build(); - private SystemInfoService systemInfoService; public BackendsProcDir(SystemInfoService systemInfoService) { @@ -69,7 +56,7 @@ public ProcResult fetchResult() throws AnalysisException { Preconditions.checkNotNull(systemInfoService); BaseProcResult result = new BaseProcResult(); - result.setNames(TITLE_NAMES); + result.setNames(BackendsTableValuedFunction.getBackendsTitleNames()); final List> backendInfos = getBackendInfos(); for (List backendInfo : backendInfos) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowBackendsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowBackendsCommand.java index 64cb8e282a2a5c..ac73e5e3342c64 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowBackendsCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowBackendsCommand.java @@ -33,6 +33,7 @@ import org.apache.doris.qe.ShowResultSet; import org.apache.doris.qe.ShowResultSetMetaData; import org.apache.doris.qe.StmtExecutor; +import org.apache.doris.tablefunction.BackendsTableValuedFunction; import java.util.Comparator; import java.util.List; @@ -51,7 +52,7 @@ public ShowBackendsCommand() { public ShowResultSetMetaData getMetaData() { ShowResultSetMetaData.Builder builder = ShowResultSetMetaData.builder(); - for (String title : BackendsProcDir.TITLE_NAMES) { + for (String title : BackendsTableValuedFunction.getBackendsTitleNames()) { builder.addColumn(new Column(title, ScalarType.createVarchar(30))); } return builder.build(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/BackendsTableValuedFunction.java b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/BackendsTableValuedFunction.java index aca6779fc64f23..63a14a35e76ccb 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/BackendsTableValuedFunction.java +++ b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/BackendsTableValuedFunction.java @@ -69,16 +69,24 @@ public class BackendsTableValuedFunction extends MetadataTableValuedFunction { new Column("Version", ScalarType.createStringType()), new Column("Status", ScalarType.createStringType()), new Column("HeartbeatFailureCounter", ScalarType.createType(PrimitiveType.INT)), + new Column("CpuCores", ScalarType.createType(PrimitiveType.INT)), + new Column("Memory", ScalarType.createStringType()), + new Column("LiveSince", ScalarType.createStringType()), + new Column("RunningTasks", ScalarType.createType(PrimitiveType.BIGINT)), new Column("NodeRole", ScalarType.createStringType())); private static final ImmutableMap COLUMN_TO_INDEX; + private static final ImmutableList TITLE_NAMES; static { ImmutableMap.Builder builder = new ImmutableMap.Builder(); + ImmutableList.Builder immutableListBuilder = ImmutableList.builder(); for (int i = 0; i < SCHEMA.size(); i++) { builder.put(SCHEMA.get(i).getName().toLowerCase(), i); + immutableListBuilder.add(SCHEMA.get(i).getName()); } COLUMN_TO_INDEX = builder.build(); + TITLE_NAMES = immutableListBuilder.build(); } public static Integer getColumnIndexFromColumnName(String columnName) { @@ -121,4 +129,11 @@ public String getTableName() { public List getTableColumns() throws AnalysisException { return SCHEMA; } + + /** + * unify title names for backends function and show backends command + */ + public static ImmutableList getBackendsTitleNames() { + return TITLE_NAMES; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java index 4a4026ee31372c..a37e67bc875ecd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java @@ -46,6 +46,7 @@ import org.apache.doris.common.Pair; import org.apache.doris.common.proc.FrontendsProcNode; import org.apache.doris.common.proc.PartitionsProcDir; +import org.apache.doris.common.profile.RuntimeProfile; import org.apache.doris.common.util.DebugUtil; import org.apache.doris.common.util.NetUtils; import org.apache.doris.common.util.TimeUtils; @@ -105,6 +106,7 @@ import org.apache.doris.thrift.TStatus; import org.apache.doris.thrift.TStatusCode; import org.apache.doris.thrift.TTasksMetadataParams; +import org.apache.doris.thrift.TUnit; import org.apache.doris.thrift.TUserIdentity; import com.codahale.metrics.Snapshot; @@ -498,6 +500,15 @@ private static TFetchSchemaTableDataResult backendsMetadataResult(TMetadataTable trow.addToColumnValue(new TCell().setStringVal(new Gson().toJson(backend.getBackendStatus()))); // heartbeat failure counter trow.addToColumnValue(new TCell().setIntVal(backend.getHeartbeatFailureCounter())); + // cpu cores + trow.addToColumnValue(new TCell().setIntVal(backend.getCputCores())); + // memory + trow.addToColumnValue(new TCell() + .setStringVal(RuntimeProfile.printCounter(backend.getBeMemory(), TUnit.BYTES))); + // live since + trow.addToColumnValue(new TCell().setStringVal(TimeUtils.longToTimeString(backend.getLiveSince()))); + // running tasks + trow.addToColumnValue(new TCell().setLongVal(backend.getRunningTasks())); // node role, show the value only when backend is alive. trow.addToColumnValue(new TCell().setStringVal(backend.isAlive() ? backend.getNodeRoleTag().value : "")); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowBackendsCommandTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowBackendsCommandTest.java index 6e4b03d2cded23..33c481094a58a4 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowBackendsCommandTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowBackendsCommandTest.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.trees.plans.commands; +import org.apache.doris.catalog.Column; import org.apache.doris.catalog.Env; import org.apache.doris.catalog.InfoSchemaDb; import org.apache.doris.common.AnalysisException; @@ -25,12 +26,17 @@ import org.apache.doris.mysql.privilege.AccessControllerManager; import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.ShowResultSet; +import org.apache.doris.tablefunction.BackendsTableValuedFunction; +import com.google.common.collect.ImmutableList; import mockit.Expectations; import mockit.Mocked; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.List; + public class ShowBackendsCommandTest { private static final String internalCtl = InternalCatalog.INTERNAL_CATALOG_NAME; private static final String infoDB = InfoSchemaDb.DATABASE_NAME; @@ -80,7 +86,13 @@ private void runBefore() throws Exception { public void testNormal() throws Exception { runBefore(); ShowBackendsCommand command = new ShowBackendsCommand(); - Assertions.assertDoesNotThrow(() -> command.doRun(ctx, null)); + ShowResultSet showResultSet = command.doRun(ctx, null); + List columnList = showResultSet.getMetaData().getColumns(); + ImmutableList backendsTitleNames = BackendsTableValuedFunction.getBackendsTitleNames(); + Assertions.assertTrue(!columnList.isEmpty() && columnList.size() == backendsTitleNames.size()); + for (int i = 0; i < backendsTitleNames.size(); i++) { + Assertions.assertTrue(columnList.get(i).getName().equalsIgnoreCase(backendsTitleNames.get(i))); + } } @Test diff --git a/fe/fe-core/src/test/java/org/apache/doris/utframe/DemoMultiBackendsTest.java b/fe/fe-core/src/test/java/org/apache/doris/utframe/DemoMultiBackendsTest.java index 800af43aaa1b72..fba2b882689ff9 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/utframe/DemoMultiBackendsTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/utframe/DemoMultiBackendsTest.java @@ -42,12 +42,14 @@ import org.apache.doris.qe.StmtExecutor; import org.apache.doris.resource.Tag; import org.apache.doris.system.Backend; +import org.apache.doris.tablefunction.BackendsTableValuedFunction; import org.apache.doris.thrift.TDisk; import org.apache.doris.thrift.TStorageMedium; import org.apache.doris.utframe.MockedFrontend.EnvVarNotSetException; import org.apache.doris.utframe.MockedFrontend.FeStartException; import org.apache.doris.utframe.MockedFrontend.NotInitException; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -207,16 +209,17 @@ public void testCreateDbAndTable() throws Exception { // test show backends; BackendsProcDir dir = new BackendsProcDir(Env.getCurrentSystemInfo()); ProcResult result = dir.fetchResult(); - Assert.assertEquals(BackendsProcDir.TITLE_NAMES.size(), result.getColumnNames().size()); + ImmutableList backendsTitleNames = BackendsTableValuedFunction.getBackendsTitleNames(); + Assert.assertEquals(backendsTitleNames.size(), result.getColumnNames().size()); Assert.assertEquals("{\"location\" : \"default\"}", - result.getRows().get(0).get(BackendsProcDir.TITLE_NAMES.size() - 10)); + result.getRows().get(0).get(backendsTitleNames.size() - 10)); Assert.assertEquals( "{\"lastSuccessReportTabletsTime\":\"N/A\",\"lastStreamLoadTime\":-1,\"isQueryDisabled\":false," + "\"isLoadDisabled\":false,\"isActive\":true,\"isShutdown\":false,\"currentFragmentNum\":0," + "\"lastFragmentUpdateTime\":0}", - result.getRows().get(0).get(BackendsProcDir.TITLE_NAMES.size() - 7)); - Assert.assertEquals("0", result.getRows().get(0).get(BackendsProcDir.TITLE_NAMES.size() - 6)); - Assert.assertEquals(Tag.VALUE_MIX, result.getRows().get(0).get(BackendsProcDir.TITLE_NAMES.size() - 5)); + result.getRows().get(0).get(backendsTitleNames.size() - 7)); + Assert.assertEquals("0", result.getRows().get(0).get(backendsTitleNames.size() - 6)); + Assert.assertEquals(Tag.VALUE_MIX, result.getRows().get(0).get(backendsTitleNames.size() - 5)); } protected void alterTable(String sql, ConnectContext connectContext) throws Exception { diff --git a/regression-test/data/nereids_p0/ddl/describe/describe_command.out b/regression-test/data/nereids_p0/ddl/describe/describe_command.out index 9e27c418c4fdb2..ba03c2bd56ddc8 100644 --- a/regression-test/data/nereids_p0/ddl/describe/describe_command.out +++ b/regression-test/data/nereids_p0/ddl/describe/describe_command.out @@ -40,6 +40,10 @@ ErrMsg text No false \N NONE Version text No false \N NONE Status text No false \N NONE HeartbeatFailureCounter int No false \N NONE +CpuCores int No false \N NONE +Memory text No false \N NONE +LiveSince text No false \N NONE +RunningTasks bigint No false \N NONE NodeRole text No false \N NONE -- !cmd -- diff --git a/regression-test/suites/external_table_p0/tvf/test_backends_tvf.groovy b/regression-test/suites/external_table_p0/tvf/test_backends_tvf.groovy index 241e15d6f6a378..fa001b6fdb8d83 100644 --- a/regression-test/suites/external_table_p0/tvf/test_backends_tvf.groovy +++ b/regression-test/suites/external_table_p0/tvf/test_backends_tvf.groovy @@ -19,7 +19,38 @@ suite("test_backends_tvf","p0,external,tvf,external_docker") { List> table = sql """ select * from backends(); """ assertTrue(table.size() > 0) - assertEquals(25, table[0].size()) + assertEquals(29, table[0].size()) + + List> titleNames = sql """ describe function backends(); """ + assertTrue(titleNames[0][0] =="BackendId") + assertTrue(titleNames[1][0] =="Host") + assertTrue(titleNames[2][0] =="HeartbeatPort") + assertTrue(titleNames[3][0] =="BePort") + assertTrue(titleNames[4][0] =="HttpPort") + assertTrue(titleNames[5][0] =="BrpcPort") + assertTrue(titleNames[6][0] =="ArrowFlightSqlPort") + assertTrue(titleNames[7][0] =="LastStartTime") + assertTrue(titleNames[8][0] =="LastHeartbeat") + assertTrue(titleNames[9][0] =="Alive") + assertTrue(titleNames[10][0] =="SystemDecommissioned") + assertTrue(titleNames[11][0] =="TabletNum") + assertTrue(titleNames[12][0] =="DataUsedCapacity") + assertTrue(titleNames[13][0] =="TrashUsedCapacity") + assertTrue(titleNames[14][0] =="AvailCapacity") + assertTrue(titleNames[15][0] =="TotalCapacity") + assertTrue(titleNames[16][0] =="UsedPct") + assertTrue(titleNames[17][0] =="MaxDiskUsedPct") + assertTrue(titleNames[18][0] =="RemoteUsedCapacity") + assertTrue(titleNames[19][0] =="Tag") + assertTrue(titleNames[20][0] =="ErrMsg") + assertTrue(titleNames[21][0] =="Version") + assertTrue(titleNames[22][0] =="Status") + assertTrue(titleNames[23][0] =="HeartbeatFailureCounter") + assertTrue(titleNames[24][0] =="CpuCores") + assertTrue(titleNames[25][0] =="Memory") + assertTrue(titleNames[26][0] =="LiveSince") + assertTrue(titleNames[27][0] =="RunningTasks") + assertTrue(titleNames[28][0] =="NodeRole") // filter columns table = sql """ select BackendId, Host, Alive, TotalCapacity, Version, NodeRole from backends();""" @@ -56,7 +87,7 @@ suite("test_backends_tvf","p0,external,tvf,external_docker") { SystemDecommissioned, tabletnum DataUsedCapacity, AvailCapacity, TotalCapacity, UsedPct MaxDiskUsedPct, RemoteUsedCapacity, Tag, ErrMsg, Version, Status - HeartbeatFailureCounter, NodeRole from backends(); + HeartbeatFailureCounter, CpuCores, Memory, LiveSince, RunningTasks, NodeRole from backends(); """ diff --git a/regression-test/suites/nereids_syntax_p0/information_schema.groovy b/regression-test/suites/nereids_syntax_p0/information_schema.groovy index 477fc5c88be195..2676142d28f7e4 100644 --- a/regression-test/suites/nereids_syntax_p0/information_schema.groovy +++ b/regression-test/suites/nereids_syntax_p0/information_schema.groovy @@ -20,7 +20,7 @@ import java.util.regex.Pattern; suite("information_schema") { List> table = sql """ select * from backends(); """ assertTrue(table.size() > 0) - assertTrue(table[0].size() == 25) + assertTrue(table[0].size() == 29) sql "SELECT DATABASE();" sql "select USER();"