/*
* Copyright 2015 the original author or authors.
* @https://github.com/scouter-project/scouter
*
* Licensed 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.
*
*/
package scouter.client.xlog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import scouter.client.model.TextProxy;
import scouter.client.model.XLogData;
import scouter.client.model.XLogProxy;
import scouter.client.server.GroupPolicyConstants;
import scouter.client.server.Server;
import scouter.client.server.ServerManager;
import scouter.client.util.ColorUtil;
import scouter.client.util.SqlMakerUtil;
import scouter.client.xlog.views.XLogProfileView;
import scouter.lang.CountryCode;
import scouter.lang.enumeration.ParameterizedMessageLevel;
import scouter.lang.step.*;
import scouter.util.*;
import java.io.BufferedReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
public class ProfileText {
public static void build(final String date, StyledText text, XLogData xperf, Step[] profiles, int spaceCnt,
int serverId) {
build(date, text, xperf, profiles, serverId, false);
}
public static void build(final String date, StyledText text, XLogData xperf, Step[] profiles,
int serverId, boolean bindSqlParam) {
build(date, text, xperf, profiles, serverId, bindSqlParam, false);
}
public static Color getColor(ParameterizedMessageLevel level) {
switch (level) {
case DEBUG:
return ColorUtil.getInstance().getColor("gray2");
case INFO:
return ColorUtil.getInstance().getColor("gray3");
case WARN:
return ColorUtil.getInstance().getColor("dark orange");
case ERROR:
return ColorUtil.getInstance().getColor("light red2");
case FATAL:
return ColorUtil.getInstance().getColor("red");
}
return ColorUtil.getInstance().getColor("dark gray");
};
public static void build(final String date, StyledText text, XLogData xperf, Step[] profiles,
int serverId, boolean bindSqlParam, boolean isSimplified) {
boolean truncated = false;
if (profiles == null) {
profiles = new Step[0];
}
profiles = SortUtil.sort(profiles);
XLogUtil.loadStepText(serverId, date, profiles);
String error = TextProxy.error.getLoadText(date, xperf.p.error, serverId);
Color blue = text.getDisplay().getSystemColor(SWT.COLOR_BLUE);
Color dmagenta = text.getDisplay().getSystemColor(SWT.COLOR_DARK_MAGENTA);
Color red = text.getDisplay().getSystemColor(SWT.COLOR_RED);
Color dred = text.getDisplay().getSystemColor(SWT.COLOR_DARK_RED);
Color dgreen = text.getDisplay().getSystemColor(SWT.COLOR_DARK_GREEN);
Color dblue = text.getDisplay().getSystemColor(SWT.COLOR_DARK_BLUE);
Color dcyan = text.getDisplay().getSystemColor(SWT.COLOR_DARK_CYAN);
Color dyellow = text.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW);
Color dgray = text.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY);
java.util.List<StyleRange> sr = new ArrayList<StyleRange>();
int slen = 0;
final StringBuffer sb = new StringBuffer();
sb.append("► txid = ");
slen = sb.length();
sb.append(Hexa32.toString32(xperf.p.txid)).append("\n");
sr.add(underlineStyle(slen, sb.length() - slen, dmagenta, SWT.NORMAL, SWT.UNDERLINE_LINK));
if (xperf.p.gxid != 0) {
sb.append("► gxid = ");
slen = sb.length();
sb.append(Hexa32.toString32(xperf.p.gxid));
sr.add(underlineStyle(slen, sb.length() - slen, dmagenta, SWT.NORMAL, SWT.UNDERLINE_LINK));
slen = sb.length();
sb.append(" <<- click to open XLog flow map").append("\n");
sr.add(style(slen, sb.length() - slen, dyellow, SWT.NORMAL));
}
if (xperf.p.caller != 0) {
sb.append("► caller = ");
slen = sb.length();
sb.append(Hexa32.toString32(xperf.p.caller)).append("\n");
sr.add(underlineStyle(slen, sb.length() - slen, dmagenta, SWT.NORMAL, SWT.UNDERLINE_LINK));
}
sb.append("► objName = ").append(xperf.objName).append("\n");
sb.append("► thread = ").append(TextProxy.hashMessage.getLoadText(date, xperf.p.threadNameHash, serverId)).append("\n");
sb.append("► endtime = ").append(FormatUtil.print(new Date(xperf.p.endTime), "yyyyMMdd HH:mm:ss.SSS")).append("\n");
sb.append("► elapsed = ").append(FormatUtil.print(xperf.p.elapsed, "#,##0")).append(" ms\n");
sb.append("► service = ").append(TextProxy.service.getText(xperf.p.service)).append("\n");
if (error != null) {
sb.append("► error = ");
slen = sb.length();
sb.append(error).append("\n");
sr.add(style(slen, sb.length() - slen, red, SWT.NORMAL));
}
sb.append("► ipaddr=" + IPUtil.toString(xperf.p.ipaddr) + ", ");
sb.append("userid=" + xperf.p.userid);
sb.append("\n► cpu=" + FormatUtil.print(xperf.p.cpu, "#,##0") + " ms, ");
sb.append("kbytes=" + xperf.p.kbytes);
// sb.append("bytes=" + xperf.p.bytes + ", ");
// sb.append("status=" + xperf.p.status);
if (xperf.p.sqlCount > 0) {
sb.append("\n► sqlCount=" + xperf.p.sqlCount + ", ");
sb.append("sqlTime=" + FormatUtil.print(xperf.p.sqlTime, "#,##0") + " ms");
}
if (xperf.p.apicallCount > 0) {
sb.append("\n► ApiCallCount=" + xperf.p.apicallCount + ", ");
sb.append("ApiCallTime=" + FormatUtil.print(xperf.p.apicallTime, "#,##0") + " ms");
}
String t = TextProxy.userAgent.getLoadText(date, xperf.p.userAgent, serverId);
if (StringUtil.isNotEmpty(t)) {
sb.append("\n► userAgent=" + t);
}
t = TextProxy.referer.getLoadText(date, xperf.p.referer, serverId);
if (StringUtil.isNotEmpty(t)) {
sb.append("\n► referer=" + t);
}
t = TextProxy.group.getLoadText(date, xperf.p.group, serverId);
if (StringUtil.isNotEmpty(t)) {
sb.append("\n► group=" + t);
}
if (StringUtil.isNotEmpty(xperf.p.countryCode)) {
sb.append("\n► country=" + CountryCode.getCountryName(xperf.p.countryCode));
}
t = TextProxy.city.getLoadText(date, xperf.p.city, serverId);
if (StringUtil.isNotEmpty(t)) {
sb.append("\n► city=" + t);
}
t = TextProxy.web.getLoadText(date, xperf.p.webHash, serverId);
if (StringUtil.isNotEmpty(t)) {
sb.append("\n► webName=" + t).append(" webTime=" + xperf.p.webTime + " ms");
}
t = TextProxy.login.getLoadText(date, xperf.p.login, serverId);
if (StringUtil.isNotEmpty(t)) {
sb.append("\n► login=" + t);
}
t = TextProxy.desc.getLoadText(date, xperf.p.desc, serverId);
if (StringUtil.isNotEmpty(t)) {
sb.append("\n► desc=" + t);
}
if (StringUtil.isNotEmpty(xperf.p.text1)) {
sb.append("\n► text1=" + xperf.p.text1);
}
if (StringUtil.isNotEmpty(xperf.p.text2)) {
sb.append("\n► text1=" + xperf.p.text2);
}
if (xperf.p.hasDump == 1) {
sb.append("\n► dump=Y");
}
sb.append("\n");
sb.append("------------------------------------------------------------------------------------------\n");
sb.append(" p# # TIME T-GAP CPU CONTENTS\n");
sb.append("------------------------------------------------------------------------------------------\n");
if (profiles.length == 0) {
sb.append("\n ( No xlog profile collected ) ");
text.setText(sb.toString());
// for (int i = 0; i < sr.size(); i++) {
text.setStyleRanges(sr.toArray(new StyleRange[sr.size()]));
// }
return;
}
long stime = xperf.p.endTime - xperf.p.elapsed;
long prev_tm = stime;
long prev_cpu = 0;
sb.append(" ");
sb.append(" ");
sb.append("[******]");
sb.append(" ");
sb.append(FormatUtil.print(new Date(stime), "HH:mm:ss.SSS"));
sb.append(" ");
sb.append(String.format("%6s", "0"));
sb.append(" ");
sb.append(String.format("%6s", "0"));
sb.append(" start transaction \n");
// sr.add(style(slen, sb.length() - slen, dblue, SWT.NORMAL));
long tm = xperf.p.endTime;
long cpu = xperf.p.cpu;
int sumCnt = 1;
HashMap<Integer, Integer> indent = new HashMap<Integer, Integer>();
for (int i = 0; i < profiles.length; i++) {
if (truncated)
break;
if (profiles[i] instanceof StepSummary) {
sb.append(" ").append(" ");
sb.append(String.format("[%06d]", sumCnt++));
sb.append(" ");
StepSummary sum = (StepSummary) profiles[i];
switch (sum.getStepType()) {
case StepEnum.METHOD_SUM:
XLogProfileView.isSummary = true;
MethodSum p = (MethodSum) sum;
slen = sb.length();
String m = TextProxy.method.getText(p.hash);
if (m == null)
m = Hexa32.toString32(p.hash);
sb.append(m).append(" ");
sr.add(style(slen, sb.length() - slen, blue, SWT.NORMAL));
sb.append(" count=").append(FormatUtil.print(p.count, "#,##0"));
sb.append(" time=").append(FormatUtil.print(p.elapsed, "#,##0")).append(" ms");
sb.append(" cpu=").append(FormatUtil.print(p.cputime, "#,##0"));
sb.append("\n");
break;
case StepEnum.SQL_SUM:
XLogProfileView.isSummary = true;
SqlSum sql = (SqlSum) sum;
slen = sb.length();
toString(sb, sql, serverId);
sr.add(style(slen, sb.length() - slen, blue, SWT.NORMAL));
sb.append("\n");
break;
case StepEnum.APICALL_SUM:
XLogProfileView.isSummary = true;
ApiCallSum apicall = (ApiCallSum) sum;
slen = sb.length();
toString(sb, apicall);
sr.add(style(slen, sb.length() - slen, dmagenta, SWT.NORMAL));
sb.append("\n");
break;
case StepEnum.SOCKET_SUM:
XLogProfileView.isSummary = true;
SocketSum socketSum = (SocketSum) sum;
slen = sb.length();
toString(sb, socketSum);
sr.add(style(slen, sb.length() - slen, dmagenta, SWT.NORMAL));
sb.append("\n");
break;
case StepEnum.CONTROL:
sb.delete(sb.length() - 9, sb.length());
sb.append("[******]");
sb.append(" ");
sb.append(FormatUtil.print(new Date(tm), "HH:mm:ss.SSS"));
sb.append(" ");
sb.append(String.format("%6s", FormatUtil.print(tm - prev_tm, "#,##0")));
sb.append(" ");
sb.append(String.format("%6s", FormatUtil.print(cpu - prev_cpu, "#,##0")));
sb.append(" ");
slen = sb.length();
toString(sb, (StepControl) sum);
sr.add(style(slen, sb.length() - slen, dred, SWT.NORMAL));
sb.append("\n");
truncated = true;
break;
}
continue;
}
StepSingle stepSingle = (StepSingle) profiles[i];
if (stepSingle.getStepType() == StepEnum.THREAD_CALL_POSSIBLE) {
ThreadCallPossibleStep threadStep = (ThreadCallPossibleStep)stepSingle;
XLogData threadStepXlog = null;
if(threadStep.txid != 0L) {
threadStepXlog = XLogProxy.getXLogData(xperf.serverId, DateUtil.yyyymmdd(xperf.p.endTime), threadStep.txid);
}
if(threadStepXlog != null) {
threadStep.threaded = 1;
threadStep.elapsed = threadStepXlog.p.elapsed;
}
if(threadStep.threaded == 0) {
continue;
}
}
tm = stepSingle.start_time + stime;
cpu = stepSingle.start_cpu;
boolean ignoreCpu = false;
if(cpu < 0) ignoreCpu = true;
// sr.add(style(sb.length(), 6, blue, SWT.NORMAL));
int p1 = sb.length();
String pid = String.format("[%06d]", stepSingle.parent);
sb.append((stepSingle.parent == -1) ? " - " : pid);
sb.append(" ");
sb.append(String.format("[%06d]", stepSingle.index));
sb.append(" ");
sb.append(FormatUtil.print(new Date(tm), "HH:mm:ss.SSS"));
sb.append(" ");
slen = sb.length();
sb.append(String.format("%6s", FormatUtil.print(tm - prev_tm, "#,##0")));
int gapTime = CastUtil.cint(tm - prev_tm);
int elapsedRate = xperf.p.elapsed == 0 ? 0 : CastUtil.cint((gapTime / (double)xperf.p.elapsed)*100);
if (elapsedRate > 50) {
sr.add(style(slen, 6, dred, SWT.BOLD));
} else if (elapsedRate > 20) {
sr.add(style(slen, 6, dblue, SWT.BOLD));
} else if (elapsedRate > 10) {
sr.add(style(slen, 6, dgreen, SWT.BOLD));
}
sb.append(" ");
if(ignoreCpu) {
sb.append(String.format("%6s", FormatUtil.print(0, "#,##0")));
} else {
sb.append(String.format("%6s", FormatUtil.print(XLogUtil.getCpuTime(stepSingle), "#,##0")));
}
sb.append(" ");
int lineHead = sb.length() - p1;
int space = 0;
if (indent.containsKey(stepSingle.parent)) {
space = indent.get(stepSingle.parent) + 1;
}
indent.put(stepSingle.index, space);
lineHead += space;
while (space > 0) {
sb.append(" ");
space--;
}
int dotPos;
switch (stepSingle.getStepType()) {
case StepEnum.METHOD:
slen = sb.length();
dotPos = toString(sb, (MethodStep) stepSingle, isSimplified);
sr.add(style(slen, 1, dyellow, SWT.BOLD));
if(isSimplified && dotPos > 0) {
sr.add(style(slen+1, dotPos, dyellow, SWT.NORMAL));
sr.add(style(slen+dotPos+1, 1, dyellow, SWT.BOLD));
sr.add(style(slen+dotPos+2, sb.length() - (slen+dotPos+2), dyellow, SWT.NORMAL));
} else {
sr.add(style(slen+1, sb.length() - slen+1, dyellow, SWT.NORMAL));
}
break;
case StepEnum.METHOD2:
slen = sb.length();
dotPos = toString(sb, (MethodStep) stepSingle, isSimplified);
sr.add(style(slen, 1, dyellow, SWT.BOLD));
sr.add(style(slen+1, sb.length() - slen+1, dyellow, SWT.NORMAL));
//sr.add(style(slen+dotPos, 1, dyellow, SWT.BOLD));
MethodStep2 m2 = (MethodStep2) stepSingle;
if (m2.error != 0) {
slen = sb.length();
sb.append("\n").append(TextProxy.error.getText(m2.error));
sr.add(style(slen, sb.length() - slen, red, SWT.NORMAL));
}
break;
case StepEnum.SQL:
case StepEnum.SQL2:
case StepEnum.SQL3:
SqlStep sql = (SqlStep) stepSingle;
slen = sb.length();
toString(sb, sql, serverId, lineHead, bindSqlParam);
sr.add(style(slen, sb.length() - slen, blue, SWT.NORMAL));
if (sql.error != 0) {
slen = sb.length();
sb.append("\n").append(TextProxy.error.getText(sql.error));
sr.add(style(slen, sb.length() - slen, red, SWT.NORMAL));
}
break;
case StepEnum.MESSAGE:
slen = sb.length();
toString(sb, (MessageStep) stepSingle);
sr.add(style(slen, sb.length() - slen, dgreen, SWT.NORMAL));
break;
case StepEnum.HASHED_MESSAGE:
slen = sb.length();
toString(sb, (HashedMessageStep) stepSingle);
sr.add(style(slen, sb.length() - slen, dgreen, SWT.NORMAL));
break;
case StepEnum.PARAMETERIZED_MESSAGE:
slen = sb.length();
ParameterizedMessageStep pmStep = (ParameterizedMessageStep) stepSingle;
toString(sb, pmStep);
sr.add(style(slen, sb.length() - slen, getColor(pmStep.getLevel()), SWT.NORMAL));
break;
case StepEnum.DUMP:
slen = sb.length();
toString(sb, (DumpStep) stepSingle, lineHead);
sr.add(style(slen, sb.length() - slen, dgray, SWT.NORMAL));
break;
case StepEnum.APICALL:
case StepEnum.APICALL2:
ApiCallStep apicall = (ApiCallStep) stepSingle;
slen = sb.length();
toString(sb, apicall);
sr.add(underlineStyle(slen, sb.length() - slen, dmagenta, SWT.NORMAL, SWT.UNDERLINE_LINK));
if (apicall.error != 0) {
slen = sb.length();
sb.append("\n").append(TextProxy.error.getText(apicall.error));
sr.add(style(slen, sb.length() - slen, red, SWT.NORMAL));
}
break;
case StepEnum.DISPATCH:
DispatchStep dispatchStep = (DispatchStep) stepSingle;
slen = sb.length();
toString(sb, dispatchStep);
sr.add(underlineStyle(slen, sb.length() - slen, dmagenta, SWT.NORMAL, SWT.UNDERLINE_LINK));
if (dispatchStep.error != 0) {
slen = sb.length();
sb.append("\n").append(TextProxy.error.getText(dispatchStep.error));
sr.add(style(slen, sb.length() - slen, red, SWT.NORMAL));
}
break;
case StepEnum.THREAD_CALL_POSSIBLE:
ThreadCallPossibleStep tcSteap = (ThreadCallPossibleStep) stepSingle;
slen = sb.length();
toString(sb, tcSteap);
sr.add(underlineStyle(slen, sb.length() - slen, dmagenta, SWT.NORMAL, SWT.UNDERLINE_LINK));
break;
case StepEnum.THREAD_SUBMIT:
ThreadSubmitStep threadSubmit = (ThreadSubmitStep) stepSingle;
slen = sb.length();
toString(sb, threadSubmit);
sr.add(underlineStyle(slen, sb.length() - slen, dmagenta, SWT.NORMAL, SWT.UNDERLINE_LINK));
if (threadSubmit.error != 0) {
slen = sb.length();
sb.append("\n").append(TextProxy.error.getText(threadSubmit.error));
sr.add(style(slen, sb.length() - slen, red, SWT.NORMAL));
}
break;
case StepEnum.SOCKET:
SocketStep socket = (SocketStep) stepSingle;
slen = sb.length();
toString(sb, socket);
sr.add(style(slen, sb.length() - slen, dmagenta, SWT.NORMAL));
if (socket.error != 0) {
slen = sb.length();
sb.append("\n").append(TextProxy.error.getText(socket.error));
sr.add(style(slen, sb.length() - slen, red, SWT.NORMAL));
}
break;
}
sb.append("\n");
if(!ignoreCpu) {
prev_cpu = cpu;
}
prev_tm = tm;
}
if (!truncated) {
tm = xperf.p.endTime;
cpu = xperf.p.cpu;
sb.append(" ");
sb.append(" ");
sb.append("[******]");
sb.append(" ");
sb.append(FormatUtil.print(new Date(tm), "HH:mm:ss.SSS"));
sb.append(" ");
sb.append(String.format("%6s", FormatUtil.print(tm - prev_tm, "#,##0")));
sb.append(" ");
sb.append(String.format("%6s", FormatUtil.print(cpu - prev_cpu, "#,##0")));
sb.append(" end of transaction \n");
}
sb.append("------------------------------------------------------------------------------------------\n");
text.setText(sb.toString());
text.setStyleRanges(sr.toArray(new StyleRange[sr.size()]));
}
public static void buildThreadProfile(XLogData data, StyledText text, Step[] profiles) {
if (profiles == null) {
profiles = new Step[0];
}
int serverId = data.serverId;
String date = DateUtil.yyyymmdd(data.p.endTime);
profiles = SortUtil.sort(profiles);
XLogUtil.loadStepText(serverId, date, profiles);
Color blue = text.getDisplay().getSystemColor(SWT.COLOR_BLUE);
Color dmagenta = text.getDisplay().getSystemColor(SWT.COLOR_DARK_MAGENTA);
Color red = text.getDisplay().getSystemColor(SWT.COLOR_RED);
Color dred = text.getDisplay().getSystemColor(SWT.COLOR_DARK_RED);
Color dgreen = text.getDisplay().getSystemColor(SWT.COLOR_DARK_GREEN);
java.util.List<StyleRange> sr = new ArrayList<StyleRange>();
int slen = 0;
final StringBuffer sb = new StringBuffer();
sb.append("------------------------------------------------------------------------------------------\n");
sb.append(" p# # TIME T-GAP CPU CONTENTS\n");
sb.append("------------------------------------------------------------------------------------------\n");
if (profiles.length == 0) {
sb.append("\n ( No xlog profile collected ) ");
text.setText(sb.toString());
text.setStyleRanges(sr.toArray(new StyleRange[sr.size()]));
return;
}
long stime = data.p.endTime - data.p.elapsed;
long prev_tm = stime;
long tm = stime;
int prev_cpu = -1;
int cpu = 0;
int sumCnt = 1;
HashMap<Integer, Integer> indent = new HashMap<Integer, Integer>();
for (int i = 0; i < profiles.length; i++) {
if (profiles[i] instanceof StepSummary) {
sb.append(" ").append(" ");
sb.append(String.format("[%06d]", sumCnt++));
sb.append(" ");
StepSummary sum = (StepSummary) profiles[i];
switch (sum.getStepType()) {
case StepEnum.METHOD_SUM:
MethodSum p = (MethodSum) sum;
slen = sb.length();
String m = TextProxy.method.getText(p.hash);
if (m == null)
m = Hexa32.toString32(p.hash);
sb.append(m).append(" ");
sr.add(style(slen, sb.length() - slen, blue, SWT.NORMAL));
sb.append(" count=").append(FormatUtil.print(p.count, "#,##0"));
sb.append(" time=").append(FormatUtil.print(p.elapsed, "#,##0")).append(" ms");
sb.append(" cpu=").append(FormatUtil.print(p.cputime, "#,##0"));
sb.append("\n");
break;
case StepEnum.SQL_SUM:
SqlSum sql = (SqlSum) sum;
slen = sb.length();
toString(sb, sql, serverId);
sr.add(style(slen, sb.length() - slen, blue, SWT.NORMAL));
sb.append("\n");
break;
case StepEnum.APICALL_SUM:
ApiCallSum apicall = (ApiCallSum) sum;
slen = sb.length();
toString(sb, apicall);
sr.add(style(slen, sb.length() - slen, dmagenta, SWT.NORMAL));
sb.append("\n");
break;
case StepEnum.SOCKET_SUM:
SocketSum socketSum = (SocketSum) sum;
slen = sb.length();
toString(sb, socketSum);
sr.add(style(slen, sb.length() - slen, dmagenta, SWT.NORMAL));
sb.append("\n");
break;
case StepEnum.CONTROL:
sb.delete(sb.length() - 9, sb.length());
sb.append("[******]");
sb.append(" ");
sb.append(FormatUtil.print(new Date(data.p.endTime), "HH:mm:ss.SSS"));
sb.append(" ");
sb.append(String.format("%6s", FormatUtil.print(data.p.elapsed, "#,##0")));
sb.append(" ");
sb.append(String.format("%6s", FormatUtil.print(data.p.cpu, "#,##0")));
sb.append(" ");
slen = sb.length();
toString(sb, (StepControl) sum);
sr.add(style(slen, sb.length() - slen, dred, SWT.NORMAL));
sb.append("\n");
break;
}
continue;
}
StepSingle stepSingle = (StepSingle) profiles[i];
if (stepSingle.getStepType() == StepEnum.THREAD_CALL_POSSIBLE) {
if(((ThreadCallPossibleStep)stepSingle).threaded == 0) continue;
}
tm = stime + stepSingle.start_time;
cpu = stepSingle.start_cpu;
// sr.add(style(sb.length(), 6, blue, SWT.NORMAL));
int p1 = sb.length();
String pid = String.format("[%06d]", stepSingle.parent);
sb.append((stepSingle.parent == -1) ? " - " : pid);
sb.append(" ");
sb.append(String.format("[%06d]", stepSingle.index));
sb.append(" ");
sb.append(FormatUtil.print(new Date(tm), "HH:mm:ss.SSS"));
sb.append(" ");
sb.append(String.format("%6s", FormatUtil.print(tm - prev_tm, "#,##0")));
sb.append(" ");
if (prev_cpu == -1) {
sb.append(String.format("%6s", FormatUtil.print(0, "#,##0")));
} else {
sb.append(String.format("%6s", FormatUtil.print(XLogUtil.getCpuTime(stepSingle), "#,##0")));
}
sb.append(" ");
int lineHead = sb.length() - p1;
int space = 0;
if (indent.containsKey(stepSingle.parent)) {
space = indent.get(stepSingle.parent) + 1;
}
indent.put(stepSingle.index, space);
lineHead += space;
while (space > 0) {
sb.append(" ");
space--;
}
switch (stepSingle.getStepType()) {
case StepEnum.METHOD:
toString(sb, (MethodStep) stepSingle, false);
break;
case StepEnum.METHOD2:
toString(sb, (MethodStep) stepSingle, false);
MethodStep2 m2 = (MethodStep2) stepSingle;
if (m2.error != 0) {
slen = sb.length();
sb.append("\n").append(TextProxy.error.getText(m2.error));
sr.add(style(slen, sb.length() - slen, red, SWT.NORMAL));
}
break;
case StepEnum.SQL:
case StepEnum.SQL2:
case StepEnum.SQL3:
SqlStep sql = (SqlStep) stepSingle;
slen = sb.length();
toString(sb, sql, serverId, lineHead, false);
sr.add(style(slen, sb.length() - slen, blue, SWT.NORMAL));
if (sql.error != 0) {
slen = sb.length();
sb.append("\n").append(TextProxy.error.getText(sql.error));
sr.add(style(slen, sb.length() - slen, red, SWT.NORMAL));
}
break;
case StepEnum.MESSAGE:
slen = sb.length();
toString(sb, (MessageStep) stepSingle);
sr.add(style(slen, sb.length() - slen, dgreen, SWT.NORMAL));
break;
case StepEnum.HASHED_MESSAGE:
slen = sb.length();
toString(sb, (HashedMessageStep) stepSingle);
sr.add(style(slen, sb.length() - slen, dgreen, SWT.NORMAL));
break;
case StepEnum.PARAMETERIZED_MESSAGE:
slen = sb.length();
ParameterizedMessageStep pmStep = (ParameterizedMessageStep) stepSingle;
toString(sb, pmStep);
sr.add(style(slen, sb.length() - slen, getColor(pmStep.getLevel()), SWT.NORMAL));
break;
case StepEnum.DUMP:
slen = sb.length();
toString(sb, (DumpStep) stepSingle, lineHead);
sr.add(style(slen, sb.length() - slen, dgreen, SWT.NORMAL));
break;
case StepEnum.APICALL:
case StepEnum.APICALL2:
ApiCallStep apicall = (ApiCallStep) stepSingle;
slen = sb.length();
toString(sb, apicall);
sr.add(underlineStyle(slen, sb.length() - slen, dmagenta, SWT.NORMAL, SWT.UNDERLINE_LINK));
if (apicall.error != 0) {
slen = sb.length();
sb.append("\n").append(TextProxy.error.getText(apicall.error));
sr.add(style(slen, sb.length() - slen, red, SWT.NORMAL));
}
break;
case StepEnum.DISPATCH:
DispatchStep step = (DispatchStep) stepSingle;
slen = sb.length();
toString(sb, step);
sr.add(underlineStyle(slen, sb.length() - slen, dmagenta, SWT.NORMAL, SWT.UNDERLINE_LINK));
if (step.error != 0) {
slen = sb.length();
sb.append("\n").append(TextProxy.error.getText(step.error));
sr.add(style(slen, sb.length() - slen, red, SWT.NORMAL));
}
break;
case StepEnum.THREAD_CALL_POSSIBLE:
ThreadCallPossibleStep tcSteap = (ThreadCallPossibleStep) stepSingle;
slen = sb.length();
toString(sb, tcSteap);
sr.add(underlineStyle(slen, sb.length() - slen, dmagenta, SWT.NORMAL, SWT.UNDERLINE_LINK));
break;
case StepEnum.THREAD_SUBMIT:
ThreadSubmitStep threadSubmit = (ThreadSubmitStep) stepSingle;
slen = sb.length();
toString(sb, threadSubmit);
sr.add(underlineStyle(slen, sb.length() - slen, dmagenta, SWT.NORMAL, SWT.UNDERLINE_LINK));
if (threadSubmit.error != 0) {
slen = sb.length();
sb.append("\n").append(TextProxy.error.getText(threadSubmit.error));
sr.add(style(slen, sb.length() - slen, red, SWT.NORMAL));
}
break;
case StepEnum.SOCKET:
SocketStep socket = (SocketStep) stepSingle;
slen = sb.length();
toString(sb, socket);
sr.add(style(slen, sb.length() - slen, dmagenta, SWT.NORMAL));
if (socket.error != 0) {
slen = sb.length();
sb.append("\n").append(TextProxy.error.getText(socket.error));
sr.add(style(slen, sb.length() - slen, red, SWT.NORMAL));
}
break;
}
sb.append("\n");
prev_cpu = cpu;
prev_tm = tm;
}
sb.append("------------------------------------------------------------------------------------------\n");
text.setText(sb.toString());
text.setStyleRanges(sr.toArray(new StyleRange[sr.size()]));
}
public static void toString(StringBuffer sb, ApiCallStep p) {
String m = TextProxy.apicall.getText(p.hash);
if (m == null)
m = Hexa32.toString32(p.hash);
sb.append("call: ").append(m).append(" ").append(FormatUtil.print(p.elapsed, "#,##0")).append(" ms");
if (p.txid != 0) {
if(p instanceof ApiCallStep2) {
if(((ApiCallStep2)p).async == 1) {
sb.append(" [async]");
}
}
if(p.address != null) {
sb.append(" [" + p.address + "]");
}
}
if (p.txid != 0) {
sb.append(" <" + Hexa32.toString32(p.txid) + ">");
}
}
public static void toString(StringBuffer sb, DispatchStep step) {
String m = TextProxy.apicall.getText(step.hash);
if (m == null)
m = Hexa32.toString32(step.hash);
sb.append("call: ").append(m).append(" ").append(FormatUtil.print(step.elapsed, "#,##0")).append(" ms");
if (step.txid != 0) {
sb.append(" <" + Hexa32.toString32(step.txid) + ">");
}
}
public static void toString(StringBuffer sb, ThreadCallPossibleStep step) {
String m = TextProxy.apicall.getText(step.hash);
if (m == null)
m = Hexa32.toString32(step.hash);
sb.append("call:thread: ").append(m).append(" ").append(FormatUtil.print(step.elapsed, "#,##0")).append(" ms");
if (step.txid != 0) {
sb.append(" <" + Hexa32.toString32(step.txid) + ">");
}
}
public static void toString(StringBuffer sb, HashedMessageStep p) {
String m = TextProxy.hashMessage.getText(p.hash);
if (m == null)
m = Hexa32.toString32(p.hash);
if(p.time != -1) {
sb.append(m).append(" #").append(FormatUtil.print(p.value, "#,##0")).append(" ").append(FormatUtil.print(p.time, "#,##0")).append(" ms");
} else {
sb.append(m);
}
}
public static void toString(StringBuffer sb, ParameterizedMessageStep pmStep) {
String messageFormat = TextProxy.hashMessage.getText(pmStep.getHash());
String message;
if (messageFormat == null) {
message = Hexa32.toString32(pmStep.getHash());
} else {
message = pmStep.buildMessasge(messageFormat);
}
if(pmStep.getElapsed() != -1) {
sb.append("[").append(FormatUtil.print(pmStep.getElapsed(), "#,##0")).append(" ms] ");
}
sb.append(message);
}
public static void toString(StringBuffer sb, DumpStep p, int lineHead) {
sb.append("<auto generated thread dump>:[").append(p.threadId).append("] ").append(p.threadName).append('\n');
sb.append(StringUtil.leftPad("", lineHead)).append(" -> State : ").append(p.threadState).append('\n');
if(StringUtil.isNotEmpty(p.lockName)) {
sb.append(StringUtil.leftPad("", lineHead)).append(" -> Lock : ").append(p.lockName).append('\n');
}
if(StringUtil.isNotEmpty(p.lockOwnerName)) {
sb.append(StringUtil.leftPad("", lineHead)).append(" -> Lock Owner : ").append(p.lockOwnerName).append('\n');
}
if(p.lockOwnerId > 0) {
sb.append(StringUtil.leftPad("", lineHead)).append(" -> Lock Owner Id ").append(p.lockOwnerId).append('\n');
}
for(int stackElementHash : p.stacks) {
String m = TextProxy.stackElement.getText(stackElementHash);
if(m == null) {
m = Hexa32.toString32(stackElementHash);
}
sb.append(StringUtil.leftPad("", lineHead)).append(m).append('\n');
}
}
public static void toString(StringBuffer sb, ThreadSubmitStep p) {
String m = TextProxy.apicall.getText(p.hash);
if (m == null)
m = Hexa32.toString32(p.hash);
sb.append("thread: ").append(m).append(" ").append(FormatUtil.print(p.elapsed, "#,##0")).append(" ms");
if (p.txid != 0) {
sb.append(" <" + Hexa32.toString32(p.txid) + ">");
}
}
public static void toString(StringBuffer sb, SocketStep p) {
String ip = IPUtil.toString(p.ipaddr);
sb.append("socket: ").append(ip == null ? "unknown" : ip).append(":").append(p.port + " ")
.append(FormatUtil.print(p.elapsed, "#,##0")).append(" ms");
}
public static void toString(StringBuffer sb, ApiCallSum p) {
String m = TextProxy.apicall.getText(p.hash);
if (m == null)
m = Hexa32.toString32(p.hash);
sb.append("call: ").append(m).append(" ");
sb.append(" count=").append(FormatUtil.print(p.count, "#,##0"));
sb.append(" time=").append(FormatUtil.print(p.elapsed, "#,##0")).append(" ms");
sb.append(" cpu=").append(FormatUtil.print(p.cputime, "#,##0"));
if (p.error > 0) {
sb.append(" error=").append(FormatUtil.print(p.error, "#,##0"));
}
}
public static void toString(StringBuffer sb, SocketSum p) {
String ip = IPUtil.toString(p.ipaddr);
sb.append("socket: ").append(ip == null ? "unknown" : ip).append(":").append(p.port + " ");
sb.append(" count=").append(FormatUtil.print(p.count, "#,##0"));
sb.append(" time=").append(FormatUtil.print(p.elapsed, "#,##0")).append(" ms");
if (p.error > 0) {
sb.append(" error=").append(FormatUtil.print(p.error, "#,##0"));
}
}
public static void toString(StringBuffer sb, SqlStep p, int serverId, int lineHead, boolean bindParam) {
if (p instanceof SqlStep2) {
sb.append(SqlXType.toString(((SqlStep2) p).xtype));
}
String m = TextProxy.sql.getText(p.hash);
m = spacing(m, lineHead);
if (m == null)
m = Hexa32.toString32(p.hash);
Server server = ServerManager.getInstance().getServer(serverId);
boolean showParam = true;
if (server != null) {
showParam = server.isAllowAction(GroupPolicyConstants.ALLOW_SQLPARAMETER);
}
if (showParam && bindParam) {
sb.append(SqlMakerUtil.replaceSQLParameter(m, p.param));
} else {
sb.append(m);
}
if (StringUtil.isEmpty(p.param) == false) {
if (bindParam == false) {
sb.append("\n").append(StringUtil.leftPad("", lineHead));
sb.append("[").append(showParam ? p.param : "******").append("]");
}
}
if (p instanceof SqlStep3) {
int updatedCount = ((SqlStep3) p).updated;
if (updatedCount > SqlStep3.EXECUTE_RESULT_SET) {
sb.append(" <Affected Rows : " + updatedCount + ">");
} else if (updatedCount == SqlStep3.EXECUTE_UNKNOWN_COUNT) {
sb.append(" <Affected Rows : unknown>");
}
}
sb.append(" ").append(FormatUtil.print(p.elapsed, "#,##0")).append(" ms");
}
public static String spacing(String m, int lineHead) {
if (m == null)
return m;
String dummy = StringUtil.leftPad("", lineHead);
StringBuffer sb = new StringBuffer();
try {
BufferedReader sr = new BufferedReader(new StringReader(m));
String s = null;
while ((s = sr.readLine()) != null) {
s = StringUtil.trim(s);
if (s.length() > 0) {
if (sb.length() > 0) {
sb.append("\n").append(dummy);
}
sb.append(s);
}
}
} catch (Exception e) {
}
return sb.toString();
}
public static void toString(StringBuffer sb, SqlSum p, int serverId) {
String m = TextProxy.sql.getText(p.hash);
if (m == null)
m = Hexa32.toString32(p.hash);
sb.append(m);
if (StringUtil.isEmpty(p.param) == false) {
Server server = ServerManager.getInstance().getServer(serverId);
boolean showParam = server.isAllowAction(GroupPolicyConstants.ALLOW_SQLPARAMETER);
sb.append(" [").append(showParam ? p.param : "******").append("]");
}
sb.append(" count=").append(FormatUtil.print(p.count, "#,##0"));
sb.append(" time=").append(FormatUtil.print(p.elapsed, "#,##0")).append(" ms");
sb.append(" cpu=").append(FormatUtil.print(p.cputime, "#,##0"));
if (p.error > 0) {
sb.append(" error=").append(FormatUtil.print(p.error, "#,##0"));
}
}
public static void toString(StringBuffer sb, MessageStep p) {
sb.append(p.message);
}
public static void toString(StringBuffer sb, StepControl p) {
sb.append(p.message);
}
/**
* @return class and method deliminator position ( Class.method -> return 5)
*/
public static int toString(StringBuffer sb, MethodStep p, boolean isSimplified) {
String m = TextProxy.method.getText(p.hash);
if (m == null) {
m = Hexa32.toString32(p.hash);
}
if(isSimplified) {
String simple = simplifyMethod(m);
sb.append(simple).append(" [").append(FormatUtil.print(p.elapsed, "#,##0")).append("ms]").append(" -- ").append(m);
return simple.indexOf('#');
} else {
sb.append(m).append(" ").append(FormatUtil.print(p.elapsed, "#,##0")).append(" ms");
return m.indexOf('.');
}
}
public static String simplifyMethod(String method) {
String[] parts = StringUtil.split(method, '.');
if(parts.length >= 2) {
String methodName = parts[parts.length - 1];
int bracePos = methodName.indexOf('(');
if(bracePos <= 0) return method;
return parts[parts.length - 2] + "#" + methodName.substring(0, bracePos) + "()";
} else {
return method;
}
}
public static StyleRange style(int start, int length, Color c, int f) {
StyleRange t = new StyleRange();
t.start = start;
t.length = length;
t.foreground = c;
t.fontStyle = f;
return t;
}
public static StyleRange style(int start, int length, int f) {
StyleRange t = new StyleRange();
t.start = start;
t.length = length;
t.fontStyle = f;
return t;
}
public static StyleRange style(int start, int length, Color c, int f, Color backc) {
StyleRange t = new StyleRange();
t.start = start;
t.length = length;
t.foreground = c;
t.fontStyle = f;
t.background = backc;
return t;
}
public static StyleRange underlineStyle(int start, int length, Color c, int fontStyle, int underlineStyle) {
StyleRange t = new StyleRange();
t.start = start;
t.length = length;
t.foreground = c;
t.fontStyle = fontStyle;
t.underline = true;
t.underlineStyle = underlineStyle;
return t;
}
}