This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch dev-1.1.2
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/dev-1.1.2 by this push:
new 8e1018d1c8 [improvement](profile) add json profile and add session
context (#11279)
8e1018d1c8 is described below
commit 8e1018d1c8f0b646d8526f4b525a4078ac32cebc
Author: miswujian <[email protected]>
AuthorDate: Thu Jul 28 15:48:00 2022 +0800
[improvement](profile) add json profile and add session context (#11279)
1. Add a new session varible "session_context"
2. support export profile in json format
---
.../org/apache/doris/analysis/SchemaTableType.java | 1 +
.../org/apache/doris/catalog/PrimitiveType.java | 3 +-
.../doris/common/profile/ProfileTreeNode.java | 1 -
.../doris/common/profile/ProfileTreePrinter.java | 8 +-
.../apache/doris/common/util/ProfileManager.java | 17 ++-
.../apache/doris/common/util/RuntimeProfile.java | 2 +-
.../apache/doris/httpv2/rest/MetaInfoAction.java | 15 +--
.../httpv2/rest/manager/QueryProfileAction.java | 148 +++++++++++++--------
.../java/org/apache/doris/mysql/MysqlCommand.java | 1 +
.../java/org/apache/doris/qe/SessionVariable.java | 42 +++++-
.../java/org/apache/doris/qe/StmtExecutor.java | 1 +
.../doris/common/util/RuntimeProfileTest.java | 4 +-
12 files changed, 164 insertions(+), 79 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java
index ff3e29d6f6..32fa75c7a8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java
@@ -68,6 +68,7 @@ public enum SchemaTableType {
SCH_INVALID("NULL", "NULL", TSchemaTableType.SCH_INVALID);
private static final String dbName = "INFORMATION_SCHEMA";
private static SelectList fullSelectLists;
+
static {
fullSelectLists = new SelectList();
fullSelectLists.addItem(SelectListItem.createStarItem(null));
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/PrimitiveType.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/PrimitiveType.java
index cdc0f56980..b61e573f9e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/PrimitiveType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/PrimitiveType.java
@@ -70,6 +70,7 @@ public enum PrimitiveType {
private static final int DECIMAL_INDEX_LEN = 12;
private static ImmutableSetMultimap<PrimitiveType, PrimitiveType>
implicitCastMap;
+
static {
ImmutableSetMultimap.Builder<PrimitiveType, PrimitiveType> builder =
ImmutableSetMultimap.builder();
// Nulltype
@@ -746,7 +747,7 @@ public enum PrimitiveType {
case DATETIME: {
if (isTimeType) {
return MysqlColType.MYSQL_TYPE_TIME;
- } else {
+ } else {
return MysqlColType.MYSQL_TYPE_DATETIME;
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/common/profile/ProfileTreeNode.java
b/fe/fe-core/src/main/java/org/apache/doris/common/profile/ProfileTreeNode.java
index 10d71a58bc..9d77bca46f 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/common/profile/ProfileTreeNode.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/common/profile/ProfileTreeNode.java
@@ -137,7 +137,6 @@ public class ProfileTreeNode extends
TreeNode<ProfileTreeNode> {
return sb.toString();
}
-
public JSONObject debugStringInJson(ProfileTreePrinter.PrintLevel level,
String nodeLevel) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", nodeLevel);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/common/profile/ProfileTreePrinter.java
b/fe/fe-core/src/main/java/org/apache/doris/common/profile/ProfileTreePrinter.java
index 0028d080ed..c09a764d73 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/common/profile/ProfileTreePrinter.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/common/profile/ProfileTreePrinter.java
@@ -20,16 +20,14 @@ package org.apache.doris.common.profile;
import hu.webarticum.treeprinter.BorderTreeNodeDecorator;
import hu.webarticum.treeprinter.SimpleTreeNode;
import hu.webarticum.treeprinter.TraditionalTreePrinter;
-
import org.apache.commons.lang3.StringUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
public class ProfileTreePrinter {
- public static enum PrintLevel {
- FRAGMENT,
- INSTANCE
+ public enum PrintLevel {
+ FRAGMENT, INSTANCE
}
// Fragment tree only print the entire query plan tree with node name
@@ -57,7 +55,6 @@ public class ProfileTreePrinter {
return node;
}
-
public static JSONObject printFragmentTreeInJson(ProfileTreeNode root,
ProfileTreePrinter.PrintLevel level) {
JSONObject object = new JSONObject();
JSONArray jsonNodes = new JSONArray();
@@ -88,5 +85,4 @@ public class ProfileTreePrinter {
edges.add(edge);
}
}
-
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/common/util/ProfileManager.java
b/fe/fe-core/src/main/java/org/apache/doris/common/util/ProfileManager.java
index 05103f83ca..ac105e3bc6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/util/ProfileManager.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/ProfileManager.java
@@ -67,6 +67,7 @@ public class ProfileManager {
public static final String DEFAULT_DB = "Default Db";
public static final String SQL_STATEMENT = "Sql Statement";
public static final String IS_CACHED = "Is Cached";
+ public static final String TRACE_ID = "Trace ID";
public enum ProfileType {
QUERY,
@@ -75,7 +76,7 @@ public class ProfileManager {
public static final ArrayList<String> PROFILE_HEADERS = new ArrayList(
Arrays.asList(QUERY_ID, USER, DEFAULT_DB, SQL_STATEMENT,
QUERY_TYPE,
- START_TIME, END_TIME, TOTAL_TIME, QUERY_STATE));
+ START_TIME, END_TIME, TOTAL_TIME, QUERY_STATE, TRACE_ID));
private class ProfileElement {
public Map<String, String> infoStrings = Maps.newHashMap();
@@ -285,4 +286,18 @@ public class ProfileManager {
readLock.unlock();
}
}
+
+ public String getQueryIdByTraceId(String traceId) {
+ readLock.lock();
+ try {
+ for (Map.Entry<String, ProfileElement> entry :
queryIdToProfileMap.entrySet()) {
+ if (entry.getValue().infoStrings.getOrDefault(TRACE_ID,
"").equals(traceId)) {
+ return entry.getKey();
+ }
+ }
+ return "";
+ } finally {
+ readLock.unlock();
+ }
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/common/util/RuntimeProfile.java
b/fe/fe-core/src/main/java/org/apache/doris/common/util/RuntimeProfile.java
index 9d465020b7..de79ba6ecc 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/util/RuntimeProfile.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/RuntimeProfile.java
@@ -468,7 +468,7 @@ public class RuntimeProfile {
// Returns the value to which the specified key is mapped;
// or null if this map contains no mapping for the key.
public String getInfoString(String key) {
- return infoStrings.get(key);
+ return infoStrings.getOrDefault(key, "");
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/MetaInfoAction.java
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/MetaInfoAction.java
index e00d54ddc3..1c780f9542 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/MetaInfoAction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/MetaInfoAction.java
@@ -37,22 +37,21 @@ import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.system.SystemInfoService;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
-
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
/**
* And meta info like databases, tables and schema
@@ -227,7 +226,7 @@ public class MetaInfoAction extends RestBaseController {
Table tbl;
try {
db = Catalog.getCurrentCatalog().getDbOrMetaException(fullDbName);
- tbl = db.getTableOrMetaException(tblName, Table.TableType.OLAP);
+ tbl = db.getTableOrMetaException(tblName);
} catch (MetaNotFoundException e) {
return ResponseEntityBuilder.okWithCommonError(e.getMessage());
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/QueryProfileAction.java
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/QueryProfileAction.java
index f0b02e00d6..e3f83b9e3c 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/QueryProfileAction.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/QueryProfileAction.java
@@ -41,9 +41,9 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
-
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.jetbrains.annotations.NotNull;
import org.json.simple.JSONObject;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
@@ -58,7 +58,6 @@ import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
-
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -221,38 +220,84 @@ public class QueryProfileAction extends
RestBaseController {
return ResponseEntityBuilder.ok(querySql);
}
- // Returns the text profile for the specified query id.
- @RequestMapping(path = "/profile/text/{query_id}", method =
RequestMethod.GET)
+ /**
+ * Returns the text profile for the specified query id.
+ * There are 3 formats:
+ * 1. Text: return the entire profile of the specified query id
+ * eg: {"profile": "text_xxx"}
+ * <p>
+ * 2. Graph: return the profile in ascii graph. If fragmentId and
instanceId are specified, it will
+ * return the instance profile, otherwise, it will return the fragment
profile.
+ * eg: {"profile" : "graph_xxx"}
+ * <p>
+ * 3. Json: return the profile in json. If fragmentId and instanceId are
specified, it will
+ * return the instance profile, otherwise, it will return the fragment
profile.
+ * Json format is mainly used for front-end UI drawing.
+ * eg: {"profile" : "json_xxx"}
+ */
+ @RequestMapping(path = "/profile/{format}/{query_id}", method =
RequestMethod.GET)
public Object queryProfileText(HttpServletRequest request,
HttpServletResponse response,
- @PathVariable("query_id") String queryId,
- @RequestParam(value = IS_ALL_NODE_PARA,
required = false, defaultValue = "true")
- boolean isAllNode) {
+ @PathVariable("format") String format, @PathVariable("query_id")
String queryId,
+ @RequestParam(value = FRAGMENT_ID, required = false) String
fragmentId,
+ @RequestParam(value = INSTANCE_ID, required = false) String
instanceId,
+ @RequestParam(value = IS_ALL_NODE_PARA, required = false,
defaultValue = "true") boolean isAllNode) {
+ executeCheckPassword(request, response);
+ checkGlobalAuth(ConnectContext.get().getCurrentUserIdentity(),
PrivPredicate.ADMIN);
+
+ if (format.equals("text")) {
+ return getTextProfile(request, queryId, isAllNode);
+ } else if (format.equals("graph")) {
+ return getGraphProfile(request, queryId, fragmentId, instanceId,
isAllNode);
+ } else if (format.equals("json")) {
+ return getJsonProfile(request, queryId, fragmentId, instanceId,
isAllNode);
+ } else {
+ return ResponseEntityBuilder.badRequest("Invalid profile format: "
+ format);
+ }
+ }
+
+ /**
+ * Get query id by trace id
+ *
+ * @param request
+ * @param response
+ * @param traceId
+ * @param isAllNode
+ * @return
+ */
+ @RequestMapping(path = "/trace_id/{trace_id}", method = RequestMethod.GET)
+ public Object getQueryIdByTraceId(HttpServletRequest request,
HttpServletResponse response,
+ @PathVariable("trace_id") String traceId,
+ @RequestParam(value = IS_ALL_NODE_PARA, required = false,
defaultValue = "true") boolean isAllNode) {
executeCheckPassword(request, response);
checkGlobalAuth(ConnectContext.get().getCurrentUserIdentity(),
PrivPredicate.ADMIN);
- Map<String, String> profileMap = Maps.newHashMap();
if (isAllNode) {
- String httpPath = "/rest/v2/manager/query/profile/text/" + queryId;
+ String httpPath = "/rest/v2/manager/query/trace_id/" + traceId;
ImmutableMap<String, String> arguments = ImmutableMap.<String,
String>builder()
.put(IS_ALL_NODE_PARA, "false").build();
- List<String> dataList = requestAllFe(httpPath, arguments,
request.getHeader(NodeAction.AUTHORIZATION));
- if (!dataList.isEmpty()) {
+ List<Pair<String, Integer>> frontends = HttpUtils.getFeList();
+ ImmutableMap<String, String> header = ImmutableMap.<String,
String>builder()
+ .put(NodeAction.AUTHORIZATION,
request.getHeader(NodeAction.AUTHORIZATION)).build();
+ for (Pair<String, Integer> ipPort : frontends) {
+ String url = HttpUtils.concatUrl(ipPort, httpPath, arguments);
try {
- String profile =
-
JsonParser.parseString(dataList.get(0)).getAsJsonObject().get("profile").getAsString();
- profileMap.put("profile", profile);
- return ResponseEntityBuilder.ok(profileMap);
+ String responseJson = HttpUtils.doGet(url, header);
+ int code =
JsonParser.parseString(responseJson).getAsJsonObject().get("code").getAsInt();
+ if (code == HttpUtils.REQUEST_SUCCESS_CODE) {
+ return responseJson;
+ }
} catch (Exception e) {
- LOG.warn("parse profile text error: {}", dataList.get(0),
e);
+ LOG.warn(e);
}
}
} else {
- String profile = ProfileManager.getInstance().getProfile(queryId);
- if (!Strings.isNullOrEmpty(profile)) {
- profileMap.put("profile", profile);
+ String queryId =
ProfileManager.getInstance().getQueryIdByTraceId(traceId);
+ if (Strings.isNullOrEmpty(queryId)) {
+ return ResponseEntityBuilder.badRequest("Not found");
}
+ return ResponseEntityBuilder.ok(queryId);
}
- return ResponseEntityBuilder.ok(profileMap);
+ return ResponseEntityBuilder.badRequest("not found query id");
}
// Returns the fragments and instances for the specified query id.
@@ -267,9 +312,8 @@ public class QueryProfileAction extends RestBaseController {
// ]
@RequestMapping(path = "/profile/fragments/{query_id}", method =
RequestMethod.GET)
public Object fragments(HttpServletRequest request, HttpServletResponse
response,
- @PathVariable("query_id") String queryId,
- @RequestParam(value = IS_ALL_NODE_PARA, required =
false, defaultValue = "true")
- boolean isAllNode) {
+ @PathVariable("query_id") String queryId,
+ @RequestParam(value = IS_ALL_NODE_PARA, required = false,
defaultValue = "true") boolean isAllNode) {
executeCheckPassword(request, response);
checkGlobalAuth(ConnectContext.get().getCurrentUserIdentity(),
PrivPredicate.ADMIN);
@@ -302,56 +346,47 @@ public class QueryProfileAction extends
RestBaseController {
return ResponseEntityBuilder.badRequest("not found query id");
}
- // Returns the graph profile for the specified query id.
- @RequestMapping(path = "/profile/graph/{query_id}", method =
RequestMethod.GET)
- public Object queryProfileGraph(HttpServletRequest request,
HttpServletResponse response,
- @PathVariable("query_id") String queryId,
- @RequestParam(value = FRAGMENT_ID,
required = false) String fragmentId,
- @RequestParam(value = INSTANCE_ID,
required = false) String instanceId,
- @RequestParam(value = IS_ALL_NODE_PARA,
required = false, defaultValue = "true")
- boolean isAllNode) {
- executeCheckPassword(request, response);
- checkGlobalAuth(ConnectContext.get().getCurrentUserIdentity(),
PrivPredicate.ADMIN);
+ @NotNull
+ private ResponseEntity getTextProfile(HttpServletRequest request, String
queryId, boolean isAllNode) {
+ Map<String, String> profileMap = Maps.newHashMap();
+ if (isAllNode) {
+ return getProfileFromAllFrontends(request, "text", queryId, "",
"");
+ } else {
+ String profile = ProfileManager.getInstance().getProfile(queryId);
+ if (!Strings.isNullOrEmpty(profile)) {
+ profileMap.put("profile", profile);
+ }
+ }
+ return ResponseEntityBuilder.ok(profileMap);
+ }
+ @NotNull
+ private ResponseEntity getGraphProfile(HttpServletRequest request, String
queryId, String fragmentId,
+ String instanceId, boolean isAllNode) {
Map<String, String> graph = Maps.newHashMap();
List<String> results;
-
if (isAllNode) {
- String httpPath = "/rest/v2/manager/query/profile/graph/" +
queryId;
- Map<String, String> arguments = Maps.newHashMap();
- arguments.put(FRAGMENT_ID, fragmentId);
- arguments.put(INSTANCE_ID, instanceId);
- arguments.put(IS_ALL_NODE_PARA, "false");
- List<String> dataList = requestAllFe(httpPath, arguments,
request.getHeader(NodeAction.AUTHORIZATION));
- if (!dataList.isEmpty()) {
- try {
- String profileGraph =
-
JsonParser.parseString(dataList.get(0)).getAsJsonObject().get("graph").getAsString();
- graph.put("graph", profileGraph);
- return ResponseEntityBuilder.ok(graph);
- } catch (Exception e) {
- LOG.warn("parse profile graph error: {}", dataList.get(0),
e);
- }
- }
+ return getProfileFromAllFrontends(request, "graph", queryId,
fragmentId, instanceId);
} else {
try {
if (Strings.isNullOrEmpty(fragmentId) ||
Strings.isNullOrEmpty(instanceId)) {
ProfileTreeNode treeRoot =
ProfileManager.getInstance().getFragmentProfileTree(queryId, queryId);
results =
Lists.newArrayList(ProfileTreePrinter.printFragmentTree(treeRoot));
} else {
- ProfileTreeNode treeRoot =
ProfileManager.getInstance().getInstanceProfileTree(queryId, queryId,
- fragmentId, instanceId);
+ ProfileTreeNode treeRoot = ProfileManager.getInstance()
+ .getInstanceProfileTree(queryId, queryId,
fragmentId, instanceId);
results =
Lists.newArrayList(ProfileTreePrinter.printInstanceTree(treeRoot));
}
graph.put("graph", results.get(0));
} catch (Exception e) {
- LOG.warn("get profile graph error, queryId:{}, fragementId:{},
instanceId:{}",
- queryId, fragmentId, instanceId, e);
+ LOG.warn("get profile graph error, queryId:{}, fragementId:{},
instanceId:{}", queryId, fragmentId,
+ instanceId, e);
}
}
return ResponseEntityBuilder.ok(graph);
}
+ @NotNull
private ResponseEntity getJsonProfile(HttpServletRequest request, String
queryId, String fragmentId,
String instanceId, boolean isAllNode) {
Map<String, String> graph = Maps.newHashMap();
@@ -377,11 +412,12 @@ public class QueryProfileAction extends
RestBaseController {
return ResponseEntityBuilder.ok(graph);
}
+ @NotNull
private ResponseEntity getProfileFromAllFrontends(HttpServletRequest
request, String format, String queryId,
String fragmentId, String instanceId) {
String httpPath = "/rest/v2/manager/query/profile/" + format + "/" +
queryId;
- ImmutableMap.Builder<String, String> builder =
- ImmutableMap.<String, String>builder().put(IS_ALL_NODE_PARA,
"false");
+ ImmutableMap.Builder<String, String> builder = ImmutableMap.<String,
String>builder()
+ .put(IS_ALL_NODE_PARA, "false");
if (!Strings.isNullOrEmpty(fragmentId)) {
builder.put(FRAGMENT_ID, fragmentId);
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlCommand.java
b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlCommand.java
index 69c13f15a2..f8a03029d5 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlCommand.java
@@ -51,6 +51,7 @@ public enum MysqlCommand {
COM_RESET_CONNECTION("COM_RESET_CONNECTION", 31);
private static Map<Integer, MysqlCommand> codeMap = Maps.newHashMap();
+
static {
EnumSet<MysqlCommand> enumSet = EnumSet.allOf(MysqlCommand.class);
for (MysqlCommand command : enumSet) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
index 1a8c2c082b..204ce8dbaa 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
@@ -24,6 +24,7 @@ import org.apache.doris.qe.VariableMgr.VarAttr;
import org.apache.doris.thrift.TQueryOptions;
import org.apache.doris.thrift.TResourceLimit;
+import com.google.common.base.Strings;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.simple.JSONObject;
@@ -183,7 +184,10 @@ public class SessionVariable implements Serializable,
Writable {
public static final String ENABLE_PROJECTION = "enable_projection";
- public static final String TRIM_TAILING_SPACES_FOR_EXTERNAL_TABLE_QUERY =
"trim_tailing_spaces_for_external_table_query";
+ public static final String TRIM_TAILING_SPACES_FOR_EXTERNAL_TABLE_QUERY
+ = "trim_tailing_spaces_for_external_table_query";
+
+ static final String SESSION_CONTEXT = "session_context";
// session origin value
public Map<Field, String> sessionOriginValue = new HashMap<Field,
String>();
@@ -444,13 +448,21 @@ public class SessionVariable implements Serializable,
Writable {
// Default value is 1Gto
@VariableMgr.VarAttr(name = AUTO_BROADCAST_JOIN_THRESHOLD)
public double autoBroadcastJoinThreshold = 0.8;
-
+
@VariableMgr.VarAttr(name = ENABLE_PROJECTION)
private boolean enableProjection = true;
@VariableMgr.VarAttr(name = TRIM_TAILING_SPACES_FOR_EXTERNAL_TABLE_QUERY,
needForward = true)
public boolean trimTailingSpacesForExternalTableQuery = false;
+ /**
+ * The client can pass some special information by setting this session
variable in the format: "k1:v1;k2:v2".
+ * For example, trace_id can be passed to trace the query request sent by
the user.
+ * set session_context="trace_id:1234565678";
+ */
+ @VariableMgr.VarAttr(name = SESSION_CONTEXT, needForward = true)
+ public String sessionContext = "";
+
public String getBlockEncryptionMode() {
return blockEncryptionMode;
}
@@ -458,6 +470,7 @@ public class SessionVariable implements Serializable,
Writable {
public void setBlockEncryptionMode(String blockEncryptionMode) {
this.blockEncryptionMode = blockEncryptionMode;
}
+
public long getMaxExecMemByte() {
return maxExecMemByte;
}
@@ -1130,5 +1143,30 @@ public class SessionVariable implements Serializable,
Writable {
setLoadMemLimit(queryOptions.getLoadMemLimit());
}
}
+
+ /**
+ * The sessionContext is as follows:
+ * "k1:v1;k2:v2;..."
+ * Here we want to get value with key named "trace_id",
+ * Return empty string is not found.
+ *
+ * @return
+ */
+ public String getTraceId() {
+ if (Strings.isNullOrEmpty(sessionContext)) {
+ return "";
+ }
+ String[] parts = sessionContext.split(";");
+ for (String part : parts) {
+ String[] innerParts = part.split(":");
+ if (innerParts.length != 2) {
+ continue;
+ }
+ if (innerParts[0].equals("trace_id")) {
+ return innerParts[1];
+ }
+ }
+ return "";
+ }
}
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 191dd2da89..e874358d08 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
@@ -230,6 +230,7 @@ public class StmtExecutor implements ProfileWriter {
summaryProfile.addInfoString(ProfileManager.SQL_STATEMENT,
originStmt.originStmt);
summaryProfile.addInfoString(ProfileManager.IS_CACHED, isCached ?
"Yes" : "No");
+ summaryProfile.addInfoString(ProfileManager.TRACE_ID,
context.getSessionVariable().getTraceId());
plannerRuntimeProfile = new RuntimeProfile("Execution Summary");
summaryProfile.addChild(plannerRuntimeProfile);
profile.addChild(queryProfile);
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/common/util/RuntimeProfileTest.java
b/fe/fe-core/src/test/java/org/apache/doris/common/util/RuntimeProfileTest.java
index 6ca409c225..ca35c157be 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/common/util/RuntimeProfileTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/common/util/RuntimeProfileTest.java
@@ -25,7 +25,6 @@ import org.apache.doris.thrift.TUnit;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
-
import org.junit.Assert;
import org.junit.Test;
@@ -65,8 +64,7 @@ public class RuntimeProfileTest {
public void testInfoStrings() {
RuntimeProfile profile = new RuntimeProfile("profileName");
- // not exists key
- Assert.assertNull(profile.getInfoString("key"));
+ Assert.assertEquals("", profile.getInfoString("key"));
// normal add and get
profile.addInfoString("key", "value");
String value = profile.getInfoString("key");
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]