[feat](profile) Print changed session var in profile #41016 (#41317)

cherry pick from #41016
This commit is contained in:
zhiqiang
2024-09-27 09:55:43 +08:00
committed by GitHub
parent c487fc0e5f
commit 21b8887b54
4 changed files with 113 additions and 1 deletions

View File

@ -59,8 +59,8 @@ public class Profile {
private List<ExecutionProfile> executionProfiles = Lists.newArrayList();
private boolean isFinished;
private Map<Integer, String> planNodeMap;
private int profileLevel = 3;
private String changedSessionVarCache = "";
public Profile(String name, boolean isEnable, int profileLevel, boolean isPipelineX) {
this.name = name;
@ -122,6 +122,7 @@ public class Profile {
// add summary to builder
summaryProfile.prettyPrint(builder);
waitProfileCompleteIfNeeded();
getChangedSessionVars(builder);
// Only generate merged profile for select, insert into select.
// Not support broker load now.
if (this.profileLevel == MergedProfileLevel && this.executionProfiles.size() == 1) {
@ -186,4 +187,18 @@ public class Profile {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
return gson.toJson(rootProfile.toBrief());
}
public void setChangedSessionVar(String changedSessionVar) {
this.changedSessionVarCache = changedSessionVar;
}
private void getChangedSessionVars(StringBuilder builder) {
if (builder == null) {
builder = new StringBuilder();
}
builder.append("\nChanged Session Variables:\n");
builder.append(changedSessionVarCache);
builder.append("\n");
}
}

View File

@ -26,6 +26,7 @@ import com.google.common.base.Strings;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.DecimalFormat;
import java.util.List;
import java.util.UUID;
public class DebugUtil {
@ -177,4 +178,62 @@ public class DebugUtil {
e.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
public static String prettyPrintChangedSessionVar(List<List<String>> nestedList) {
if (nestedList == null || nestedList.isEmpty()) {
return "";
}
StringBuilder output = new StringBuilder();
// Assuming each inner list has exactly 3 columns
int[] columnWidths = new int[3];
// Calculate the maximum width of each column
// First consider the header widths: "VarName", "CurrentValue", "DefaultValue"
String[] headers = {"VarName", "CurrentValue", "DefaultValue"};
for (int i = 0; i < headers.length; i++) {
columnWidths[i] = headers[i].length(); // Initialize with header length
}
// Update column widths based on data
for (List<String> row : nestedList) {
for (int i = 0; i < row.size(); i++) {
columnWidths[i] = Math.max(columnWidths[i], row.get(i).length());
}
}
// Build the table header
for (int i = 0; i < headers.length; i++) {
output.append(String.format("%-" + columnWidths[i] + "s", headers[i]));
if (i < headers.length - 1) {
output.append(" | "); // Separator between columns
}
}
output.append("\n"); // Newline after the header
// Add a separator line for better readability (optional)
for (int i = 0; i < headers.length; i++) {
output.append(String.format("%-" + columnWidths[i] + "s", Strings.repeat("-", columnWidths[i])));
if (i < headers.length - 1) {
output.append("-|-"); // Separator between columns
}
}
output.append("\n"); // Newline after the separator
// Build the table body with proper alignment based on column widths
for (List<String> row : nestedList) {
for (int i = 0; i < row.size(); i++) {
String element = row.get(i);
// Pad with spaces if the element is shorter than the column width
output.append(String.format("%-" + columnWidths[i] + "s", element));
if (i < row.size() - 1) {
output.append(" | "); // Separator between columns
}
}
output.append("\n"); // Newline after each row
}
return output.toString();
}
}

View File

@ -648,6 +648,8 @@ public class StmtExecutor {
context.setQueryId(queryId);
context.setStartTime();
profile.getSummaryProfile().setQueryBeginTime();
List<List<String>> changedSessionVar = VariableMgr.dumpChangedVars(context.getSessionVariable());
profile.setChangedSessionVar(DebugUtil.prettyPrintChangedSessionVar(changedSessionVar));
context.setStmtId(STMT_ID_GENERATOR.incrementAndGet());
parseByNereids();

View File

@ -795,6 +795,42 @@ public class VariableMgr {
return changedRows;
}
public static List<List<String>> dumpChangedVars(SessionVariable sessionVar) {
// Hold the read lock when session dump, because this option need to access global variable.
rlock.lock();
List<List<String>> changedRows = Lists.newArrayList();
try {
for (Map.Entry<String, VarContext> entry : ctxByDisplayVarName.entrySet()) {
VarContext ctx = entry.getValue();
List<String> row = Lists.newArrayList();
String varName = entry.getKey();
String curValue = getValue(sessionVar, ctx.getField());
String defaultValue = ctx.getDefaultValue();
if (VariableVarConverters.hasConverter(varName)) {
try {
defaultValue = VariableVarConverters.decode(varName, Long.valueOf(defaultValue));
curValue = VariableVarConverters.decode(varName, Long.valueOf(curValue));
} catch (DdlException e) {
LOG.warn("Decode session variable {} failed, reason: {}", varName, e.getMessage());
}
}
if (curValue.equals(defaultValue)) {
continue;
}
row.add(varName);
row.add(curValue);
row.add(defaultValue);
changedRows.add(row);
}
} finally {
rlock.unlock();
}
return changedRows;
}
@Retention(RetentionPolicy.RUNTIME)
public @interface VarAttr {
// Name in show variables and set statement;