From c9aca7d852959cad30db84645e3166af39b600b7 Mon Sep 17 00:00:00 2001 From: zhiqiang Date: Wed, 28 Aug 2024 22:06:57 +0800 Subject: [PATCH] [opt](profile) Add ExecutedByFrontend in profile #39942 (#40012) cherry pick from #39942 --- .../doris/common/profile/SummaryProfile.java | 9 +- .../org/apache/doris/qe/StmtExecutor.java | 5 ++ .../test_execute_by_frontend.groovy | 90 +++++++++++++++++++ 3 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 regression-test/suites/query_profile/test_execute_by_frontend.groovy diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/profile/SummaryProfile.java b/fe/fe-core/src/main/java/org/apache/doris/common/profile/SummaryProfile.java index 8d32b5bd21..98b572b67b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/profile/SummaryProfile.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/profile/SummaryProfile.java @@ -60,7 +60,7 @@ public class SummaryProfile { public static final String PARALLEL_FRAGMENT_EXEC_INSTANCE = "Parallel Fragment Exec Instance Num"; public static final String TRACE_ID = "Trace ID"; public static final String WORKLOAD_GROUP = "Workload Group"; - + public static final String EXECUTED_BY_FRONTEND = "Executed By Frontend"; // Execution Summary public static final String EXECUTION_SUMMARY_PROFILE_NAME = "Execution Summary"; public static final String ANALYSIS_TIME = "Analysis Time"; @@ -151,7 +151,8 @@ public class SummaryProfile { INSTANCES_NUM_PER_BE, PARALLEL_FRAGMENT_EXEC_INSTANCE, TRACE_ID, - TRANSACTION_COMMIT_TIME + TRANSACTION_COMMIT_TIME, + EXECUTED_BY_FRONTEND ); // Ident of each item. Default is 0, which doesn't need to present in this Map. @@ -746,4 +747,8 @@ public class SummaryProfile { } return new Gson().toJson(jsonObject); } + + public void setExecutedByFrontend(boolean executedByFrontend) { + summaryProfile.addInfoString(EXECUTED_BY_FRONTEND, String.valueOf(executedByFrontend)); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java index ff25014535..c78a701d27 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java @@ -1704,6 +1704,11 @@ public class StmtExecutor { sendResultSet(resultSet.get(), ((Queriable) parsedStmt).getFieldInfos()); isHandleQueryInFe = true; LOG.info("Query {} finished", DebugUtil.printId(context.queryId)); + if (context.getSessionVariable().enableProfile()) { + if (profile != null) { + this.profile.getSummaryProfile().setExecutedByFrontend(true); + } + } return; } } diff --git a/regression-test/suites/query_profile/test_execute_by_frontend.groovy b/regression-test/suites/query_profile/test_execute_by_frontend.groovy new file mode 100644 index 0000000000..40435e02d9 --- /dev/null +++ b/regression-test/suites/query_profile/test_execute_by_frontend.groovy @@ -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. + +import groovy.json.JsonOutput +import groovy.json.JsonSlurper +import groovy.json.StringEscapeUtils + +def getProfileList = { + def dst = 'http://' + context.config.feHttpAddress + def conn = new URL(dst + "/rest/v1/query_profile").openConnection() + conn.setRequestMethod("GET") + def encoding = Base64.getEncoder().encodeToString((context.config.feHttpUser + ":" + + (context.config.feHttpPassword == null ? "" : context.config.feHttpPassword)).getBytes("UTF-8")) + conn.setRequestProperty("Authorization", "Basic ${encoding}") + return conn.getInputStream().getText() +} + +def getProfile = { id -> + def dst = 'http://' + context.config.feHttpAddress + def conn = new URL(dst + "/api/profile/text/?query_id=$id").openConnection() + conn.setRequestMethod("GET") + def encoding = Base64.getEncoder().encodeToString((context.config.feHttpUser + ":" + + (context.config.feHttpPassword == null ? "" : context.config.feHttpPassword)).getBytes("UTF-8")) + conn.setRequestProperty("Authorization", "Basic ${encoding}") + // set conn parameters + + return conn.getInputStream().getText() + } + +suite('test_execute_by_frontend') { + sql """ + CREATE TABLE if not exists `test_execute_by_frontend` ( + `id` INT, + `name` varchar(32) + )ENGINE=OLAP + UNIQUE KEY(`id`) + DISTRIBUTED BY HASH(`id`) BUCKETS 1 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + ); + """ + + sql "set enable_profile=true" + def simpleSql1 = "select * from test_execute_by_frontend" + sql "${simpleSql1}" + simpleSql2 = """select cast("1" as Int)""" + sql "${simpleSql2}" + def isRecorded = false + def wholeString = getProfileList() + List profileData = new JsonSlurper().parseText(wholeString).data.rows + String queryId1 = ""; + String queryId2 = ""; + + for (final def profileItem in profileData) { + if (profileItem["Sql Statement"].toString() == simpleSql1) { + isRecorded = true + queryId1 = profileItem["Profile ID"].toString() + assertEquals("internal", profileItem["Default Catalog"].toString()) + } + if (profileItem["Sql Statement"].toString() == simpleSql2) { + queryId2 = profileItem["Profile ID"].toString() + } + } + + assertTrue(isRecorded) + + String profileContent1 = getProfile(queryId1) + def executionProfileIdx1 = profileContent1.indexOf("Executed By Frontend: true") + assertTrue(executionProfileIdx1 > 0) + String profileContent2 = getProfile(queryId2) + def executionProfileIdx2 = profileContent2.indexOf("Executed By Frontend: true") + assertTrue(executionProfileIdx2 > 0) + + sql """ SET enable_profile = false """ + sql """ DROP TABLE IF EXISTS test_execute_by_frontend """ +} \ No newline at end of file