Commit 7c094a26 authored by liang.tang's avatar liang.tang
Browse files

arthas-master

parents
Pipeline #220 failed with stages
in 0 seconds
package com.taobao.arthas.core.command.monitor200;
import com.alibaba.arthas.deps.org.slf4j.Logger;
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
import com.taobao.arthas.core.advisor.AccessPoint;
import com.taobao.arthas.core.advisor.Advice;
import com.taobao.arthas.core.advisor.AdviceListenerAdapter;
import com.taobao.arthas.core.advisor.ArthasMethod;
import com.taobao.arthas.core.command.model.ObjectVO;
import com.taobao.arthas.core.command.model.WatchModel;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.LogUtil;
import com.taobao.arthas.core.util.ThreadLocalWatch;
import java.util.Date;
/**
* @author beiwei30 on 29/11/2016.
*/
class WatchAdviceListener extends AdviceListenerAdapter {
private static final Logger logger = LoggerFactory.getLogger(WatchAdviceListener.class);
private final ThreadLocalWatch threadLocalWatch = new ThreadLocalWatch();
private WatchCommand command;
private CommandProcess process;
public WatchAdviceListener(WatchCommand command, CommandProcess process, boolean verbose) {
this.command = command;
this.process = process;
super.setVerbose(verbose);
}
private boolean isFinish() {
return command.isFinish() || !command.isBefore() && !command.isException() && !command.isSuccess();
}
@Override
public void before(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args)
throws Throwable {
// 开始计算本次方法调用耗时
threadLocalWatch.start();
if (command.isBefore()) {
watching(Advice.newForBefore(loader, clazz, method, target, args));
}
}
@Override
public void afterReturning(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args,
Object returnObject) throws Throwable {
Advice advice = Advice.newForAfterReturning(loader, clazz, method, target, args, returnObject);
if (command.isSuccess()) {
watching(advice);
}
finishing(advice);
}
@Override
public void afterThrowing(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args,
Throwable throwable) {
Advice advice = Advice.newForAfterThrowing(loader, clazz, method, target, args, throwable);
if (command.isException()) {
watching(advice);
}
finishing(advice);
}
private void finishing(Advice advice) {
if (isFinish()) {
watching(advice);
}
}
private void watching(Advice advice) {
try {
// 本次调用的耗时
double cost = threadLocalWatch.costInMillis();
boolean conditionResult = isConditionMet(command.getConditionExpress(), advice, cost);
if (this.isVerbose()) {
process.write("Condition express: " + command.getConditionExpress() + " , result: " + conditionResult + "\n");
}
if (conditionResult) {
// TODO: concurrency issues for process.write
Object value = getExpressionResult(command.getExpress(), advice, cost);
WatchModel model = new WatchModel();
model.setTs(new Date());
model.setCost(cost);
model.setValue(new ObjectVO(value, command.getExpand()));
model.setSizeLimit(command.getSizeLimit());
model.setClassName(advice.getClazz().getName());
model.setMethodName(advice.getMethod().getName());
if (advice.isBefore()) {
model.setAccessPoint(AccessPoint.ACCESS_BEFORE.getKey());
} else if (advice.isAfterReturning()) {
model.setAccessPoint(AccessPoint.ACCESS_AFTER_RETUNING.getKey());
} else if (advice.isAfterThrowing()) {
model.setAccessPoint(AccessPoint.ACCESS_AFTER_THROWING.getKey());
}
process.appendResult(model);
process.times().incrementAndGet();
if (isLimitExceeded(command.getNumberOfLimit(), process.times().get())) {
abortProcess(process, command.getNumberOfLimit());
}
}
} catch (Throwable e) {
logger.warn("watch failed.", e);
process.end(-1, "watch failed, condition is: " + command.getConditionExpress() + ", express is: "
+ command.getExpress() + ", " + e.getMessage() + ", visit " + LogUtil.loggingFile()
+ " for more details.");
}
}
}
package com.taobao.arthas.core.command.monitor200;
import java.util.Arrays;
import com.taobao.arthas.core.GlobalOptions;
import com.taobao.arthas.core.advisor.AdviceListener;
import com.taobao.arthas.core.command.Constants;
import com.taobao.arthas.core.shell.cli.Completion;
import com.taobao.arthas.core.shell.cli.CompletionUtils;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.SearchUtils;
import com.taobao.arthas.core.util.matcher.Matcher;
import com.taobao.arthas.core.view.ObjectView;
import com.taobao.middleware.cli.annotations.Argument;
import com.taobao.middleware.cli.annotations.DefaultValue;
import com.taobao.middleware.cli.annotations.Description;
import com.taobao.middleware.cli.annotations.Name;
import com.taobao.middleware.cli.annotations.Option;
import com.taobao.middleware.cli.annotations.Summary;
@Name("watch")
@Summary("Display the input/output parameter, return object, and thrown exception of specified method invocation")
@Description(Constants.EXPRESS_DESCRIPTION + "\nExamples:\n" +
" watch org.apache.commons.lang.StringUtils isBlank\n" +
" watch org.apache.commons.lang.StringUtils isBlank '{params, target, returnObj, throwExp}' -x 2\n" +
" watch *StringUtils isBlank params[0] params[0].length==1\n" +
" watch *StringUtils isBlank params '#cost>100'\n" +
" watch -f *StringUtils isBlank params\n" +
" watch *StringUtils isBlank params[0]\n" +
" watch -E -b org\\.apache\\.commons\\.lang\\.StringUtils isBlank params[0]\n" +
" watch javax.servlet.Filter * --exclude-class-pattern com.demo.TestFilter\n" +
" watch OuterClass$InnerClass\n" +
Constants.WIKI + Constants.WIKI_HOME + "watch")
public class WatchCommand extends EnhancerCommand {
private String classPattern;
private String methodPattern;
private String express;
private String conditionExpress;
private boolean isBefore = false;
private boolean isFinish = false;
private boolean isException = false;
private boolean isSuccess = false;
private Integer expand = 1;
private Integer sizeLimit = 10 * 1024 * 1024;
private boolean isRegEx = false;
private int numberOfLimit = 100;
@Argument(index = 0, argName = "class-pattern")
@Description("The full qualified class name you want to watch")
public void setClassPattern(String classPattern) {
this.classPattern = classPattern;
}
@Argument(index = 1, argName = "method-pattern")
@Description("The method name you want to watch")
public void setMethodPattern(String methodPattern) {
this.methodPattern = methodPattern;
}
@Argument(index = 2, argName = "express", required = false)
@DefaultValue("{params, target, returnObj}")
@Description("The content you want to watch, written by ognl. Default value is '{params, target, returnObj}'\n" + Constants.EXPRESS_EXAMPLES)
public void setExpress(String express) {
this.express = express;
}
@Argument(index = 3, argName = "condition-express", required = false)
@Description(Constants.CONDITION_EXPRESS)
public void setConditionExpress(String conditionExpress) {
this.conditionExpress = conditionExpress;
}
@Option(shortName = "b", longName = "before", flag = true)
@Description("Watch before invocation")
public void setBefore(boolean before) {
isBefore = before;
}
@Option(shortName = "f", longName = "finish", flag = true)
@Description("Watch after invocation, enable by default")
public void setFinish(boolean finish) {
isFinish = finish;
}
@Option(shortName = "e", longName = "exception", flag = true)
@Description("Watch after throw exception")
public void setException(boolean exception) {
isException = exception;
}
@Option(shortName = "s", longName = "success", flag = true)
@Description("Watch after successful invocation")
public void setSuccess(boolean success) {
isSuccess = success;
}
@Option(shortName = "M", longName = "sizeLimit")
@Description("Upper size limit in bytes for the result (10 * 1024 * 1024 by default)")
public void setSizeLimit(Integer sizeLimit) {
this.sizeLimit = sizeLimit;
}
@Option(shortName = "x", longName = "expand")
@Description("Expand level of object (1 by default), the max value is " + ObjectView.MAX_DEEP)
public void setExpand(Integer expand) {
this.expand = expand;
}
@Option(shortName = "E", longName = "regex", flag = true)
@Description("Enable regular expression to match (wildcard matching by default)")
public void setRegEx(boolean regEx) {
isRegEx = regEx;
}
@Option(shortName = "n", longName = "limits")
@Description("Threshold of execution times")
public void setNumberOfLimit(int numberOfLimit) {
this.numberOfLimit = numberOfLimit;
}
public String getClassPattern() {
return classPattern;
}
public String getMethodPattern() {
return methodPattern;
}
public String getExpress() {
return express;
}
public String getConditionExpress() {
return conditionExpress;
}
public boolean isBefore() {
return isBefore;
}
public boolean isFinish() {
return isFinish;
}
public boolean isException() {
return isException;
}
public boolean isSuccess() {
return isSuccess;
}
public Integer getExpand() {
return expand;
}
public Integer getSizeLimit() {
return sizeLimit;
}
public boolean isRegEx() {
return isRegEx;
}
public int getNumberOfLimit() {
return numberOfLimit;
}
@Override
protected Matcher getClassNameMatcher() {
if (classNameMatcher == null) {
classNameMatcher = SearchUtils.classNameMatcher(getClassPattern(), isRegEx());
}
return classNameMatcher;
}
@Override
protected Matcher getClassNameExcludeMatcher() {
if (classNameExcludeMatcher == null && getExcludeClassPattern() != null) {
classNameExcludeMatcher = SearchUtils.classNameMatcher(getExcludeClassPattern(), isRegEx());
}
return classNameExcludeMatcher;
}
@Override
protected Matcher getMethodNameMatcher() {
if (methodNameMatcher == null) {
methodNameMatcher = SearchUtils.classNameMatcher(getMethodPattern(), isRegEx());
}
return methodNameMatcher;
}
@Override
protected AdviceListener getAdviceListener(CommandProcess process) {
return new WatchAdviceListener(this, process, GlobalOptions.verbose || this.verbose);
}
@Override
protected void completeArgument3(Completion completion) {
CompletionUtils.complete(completion, Arrays.asList(EXPRESS_EXAMPLES));
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.Base64Model;
import com.taobao.arthas.core.shell.command.CommandProcess;
/**
*
* @author hengyunabc 2021-01-05
*
*/
public class Base64View extends ResultView<Base64Model> {
@Override
public void draw(CommandProcess process, Base64Model result) {
String content = result.getContent();
if (content != null) {
process.write(content);
}
process.write("\n");
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.CatModel;
import com.taobao.arthas.core.shell.command.CommandProcess;
/**
* Result view for CatCommand
* @author gongdewei 2020/5/11
*/
public class CatView extends ResultView<CatModel> {
@Override
public void draw(CommandProcess process, CatModel result) {
process.write(result.getContent()).write("\n");
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.klass100.ClassLoaderCommand.ClassLoaderStat;
import com.taobao.arthas.core.command.klass100.ClassLoaderCommand.ClassLoaderUrlStat;
import com.taobao.arthas.core.command.model.ClassDetailVO;
import com.taobao.arthas.core.command.model.ClassLoaderModel;
import com.taobao.arthas.core.command.model.ClassLoaderVO;
import com.taobao.arthas.core.command.model.ClassSetVO;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.ClassUtils;
import com.taobao.text.Decoration;
import com.taobao.text.ui.*;
import com.taobao.text.util.RenderUtil;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* @author gongdewei 2020/4/21
*/
public class ClassLoaderView extends ResultView<ClassLoaderModel> {
@Override
public void draw(CommandProcess process, ClassLoaderModel result) {
if (result.getMatchedClassLoaders() != null) {
process.write("Matched classloaders: \n");
drawClassLoaders(process, result.getMatchedClassLoaders(), false);
process.write("\n");
return;
}
if (result.getClassSet() != null) {
drawAllClasses(process, result.getClassSet());
}
if (result.getResources() != null) {
drawResources(process, result.getResources());
}
if (result.getLoadClass() != null) {
drawLoadClass(process, result.getLoadClass());
}
if (result.getUrls() != null) {
drawClassLoaderUrls(process, result.getUrls());
}
if (result.getClassLoaders() != null){
drawClassLoaders(process, result.getClassLoaders(), result.getTree());
}
if (result.getClassLoaderStats() != null){
drawClassLoaderStats(process, result.getClassLoaderStats());
}
if (result.getUrlStats() != null) {
drawUrlStats(process, result.getUrlStats());
}
}
private void drawUrlStats(CommandProcess process, Map<ClassLoaderVO, ClassLoaderUrlStat> urlStats) {
for (Entry<ClassLoaderVO, ClassLoaderUrlStat> entry : urlStats.entrySet()) {
ClassLoaderVO classLoaderVO = entry.getKey();
ClassLoaderUrlStat urlStat = entry.getValue();
// 忽略 sun.reflect.DelegatingClassLoader 等动态ClassLoader
if (urlStat.getUsedUrls().isEmpty() && urlStat.getUnUsedUrls().isEmpty()) {
continue;
}
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
table.row(new LabelElement(classLoaderVO.getName() + ", hash:" + classLoaderVO.getHash())
.style(Decoration.bold.bold()));
Collection<String> usedUrls = urlStat.getUsedUrls();
table.row(new LabelElement("Used URLs:").style(Decoration.bold.bold()));
for (String url : usedUrls) {
table.row(url);
}
Collection<String> UnnsedUrls = urlStat.getUnUsedUrls();
table.row(new LabelElement("Unused URLs:").style(Decoration.bold.bold()));
for (String url : UnnsedUrls) {
table.row(url);
}
process.write(RenderUtil.render(table, process.width()))
.write("\n");
}
}
private void drawClassLoaderStats(CommandProcess process, Map<String, ClassLoaderStat> classLoaderStats) {
Element element = renderStat(classLoaderStats);
process.write(RenderUtil.render(element, process.width()))
.write(com.taobao.arthas.core.util.Constants.EMPTY_STRING);
}
private static TableElement renderStat(Map<String, ClassLoaderStat> classLoaderStats) {
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
table.add(new RowElement().style(Decoration.bold.bold()).add("name", "numberOfInstances", "loadedCountTotal"));
for (Map.Entry<String, ClassLoaderStat> entry : classLoaderStats.entrySet()) {
table.row(entry.getKey(), "" + entry.getValue().getNumberOfInstance(), "" + entry.getValue().getLoadedCount());
}
return table;
}
public static void drawClassLoaders(CommandProcess process, Collection<ClassLoaderVO> classLoaders, boolean isTree) {
Element element = isTree ? renderTree(classLoaders) : renderTable(classLoaders);
process.write(RenderUtil.render(element, process.width()))
.write(com.taobao.arthas.core.util.Constants.EMPTY_STRING);
}
private void drawClassLoaderUrls(CommandProcess process, List<String> urls) {
process.write(RenderUtil.render(renderClassLoaderUrls(urls), process.width()));
process.write(com.taobao.arthas.core.util.Constants.EMPTY_STRING);
}
private void drawLoadClass(CommandProcess process, ClassDetailVO loadClass) {
process.write(RenderUtil.render(ClassUtils.renderClassInfo(loadClass), process.width()) + "\n");
}
private void drawAllClasses(CommandProcess process, ClassSetVO classSetVO) {
process.write(RenderUtil.render(renderClasses(classSetVO), process.width()));
process.write("\n");
}
private void drawResources(CommandProcess process, List<String> resources) {
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
for (String resource : resources) {
table.row(resource);
}
process.write(RenderUtil.render(table, process.width()) + "\n");
process.write(com.taobao.arthas.core.util.Constants.EMPTY_STRING);
}
private Element renderClasses(ClassSetVO classSetVO) {
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
if (classSetVO.getSegment() == 0) {
table.row(new LabelElement("hash:" + classSetVO.getClassloader().getHash() + ", " + classSetVO.getClassloader().getName())
.style(Decoration.bold.bold()));
}
for (String className : classSetVO.getClasses()) {
table.row(new LabelElement(className));
}
return table;
}
private static Element renderClassLoaderUrls(List<String> urls) {
StringBuilder sb = new StringBuilder();
for (String url : urls) {
sb.append(url).append("\n");
}
return new LabelElement(sb.toString());
}
// 统计所有的ClassLoader的信息
private static TableElement renderTable(Collection<ClassLoaderVO> classLoaderInfos) {
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
table.add(new RowElement().style(Decoration.bold.bold()).add("name", "loadedCount", "hash", "parent"));
for (ClassLoaderVO classLoaderVO : classLoaderInfos) {
table.row(classLoaderVO.getName(), "" + classLoaderVO.getLoadedCount(), classLoaderVO.getHash(), classLoaderVO.getParent());
}
return table;
}
// 以树状列出ClassLoader的继承结构
private static Element renderTree(Collection<ClassLoaderVO> classLoaderInfos) {
TreeElement root = new TreeElement();
for (ClassLoaderVO classLoader : classLoaderInfos) {
TreeElement child = new TreeElement(classLoader.getName());
root.addChild(child);
renderSubtree(child, classLoader);
}
return root;
}
private static void renderSubtree(TreeElement parent, ClassLoaderVO parentClassLoader) {
if (parentClassLoader.getChildren() == null){
return;
}
for (ClassLoaderVO childClassLoader : parentClassLoader.getChildren()) {
TreeElement child = new TreeElement(childClassLoader.getName());
parent.addChild(child);
renderSubtree(child, childClassLoader);
}
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.*;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.text.Color;
import com.taobao.text.Decoration;
import com.taobao.text.ui.RowElement;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* View of 'dashboard' command
*
* @author gongdewei 2020/4/22
*/
public class DashboardView extends ResultView<DashboardModel> {
@Override
public void draw(CommandProcess process, DashboardModel result) {
int width = process.width();
int height = process.height();
// 上半部分放thread top。下半部分再切分为田字格,其中上面两格放memory, gc的信息。下面两格放tomcat,
// runtime的信息
int totalHeight = height - 1;
int threadTopHeight;
if (totalHeight <= 24) {
//总高度较小时取1/2
threadTopHeight = totalHeight / 2;
} else {
//总高度较大时取1/3,但不少于上面的值(24/2=12)
threadTopHeight = totalHeight / 3;
if (threadTopHeight < 12) {
threadTopHeight = 12;
}
}
int lowerHalf = totalHeight - threadTopHeight;
//Memory至少保留8行, 显示metaspace信息
int memoryInfoHeight = lowerHalf / 2;
if (memoryInfoHeight < 8) {
memoryInfoHeight = Math.min(8, lowerHalf);
}
//runtime
TableElement runtimeInfoTable = drawRuntimeInfo(result.getRuntimeInfo());
//tomcat
TableElement tomcatInfoTable = drawTomcatInfo(result.getTomcatInfo());
int runtimeInfoHeight = Math.max(runtimeInfoTable.getRows().size(), tomcatInfoTable == null ? 0 : tomcatInfoTable.getRows().size());
if (runtimeInfoHeight < lowerHalf - memoryInfoHeight) {
//如果runtimeInfo高度有剩余,则增大MemoryInfo的高度
memoryInfoHeight = lowerHalf - runtimeInfoHeight;
} else {
runtimeInfoHeight = lowerHalf - memoryInfoHeight;
}
//如果MemoryInfo高度有剩余,则增大ThreadHeight
int maxMemoryInfoHeight = getMemoryInfoHeight(result.getMemoryInfo());
memoryInfoHeight = Math.min(memoryInfoHeight, maxMemoryInfoHeight);
threadTopHeight = totalHeight - memoryInfoHeight - runtimeInfoHeight;
String threadInfo = ViewRenderUtil.drawThreadInfo(result.getThreads(), width, threadTopHeight);
String memoryAndGc = drawMemoryInfoAndGcInfo(result.getMemoryInfo(), result.getGcInfos(), width, memoryInfoHeight);
String runTimeAndTomcat = drawRuntimeInfoAndTomcatInfo(runtimeInfoTable, tomcatInfoTable, width, runtimeInfoHeight);
process.write(threadInfo + memoryAndGc + runTimeAndTomcat);
}
static String drawMemoryInfoAndGcInfo(Map<String, List<MemoryEntryVO>> memoryInfo, List<GcInfoVO> gcInfos, int width, int height) {
TableElement table = new TableElement(1, 1);
TableElement memoryInfoTable = MemoryView.drawMemoryInfo(memoryInfo);
TableElement gcInfoTable = drawGcInfo(gcInfos);
table.row(memoryInfoTable, gcInfoTable);
return RenderUtil.render(table, width, height);
}
private static int getMemoryInfoHeight(Map<String, List<MemoryEntryVO>> memoryInfo) {
int height = 1;
for (List<MemoryEntryVO> memoryEntryVOS : memoryInfo.values()) {
height += memoryEntryVOS.size();
}
return height;
}
private static TableElement drawGcInfo(List<GcInfoVO> gcInfos) {
TableElement table = new TableElement(1, 1).rightCellPadding(1);
table.add(new RowElement().style(Decoration.bold.fg(Color.black).bg(Color.white)).add("GC", ""));
for (GcInfoVO gcInfo : gcInfos) {
table.add(new RowElement().style(Decoration.bold.bold()).add("gc." + gcInfo.getName() + ".count",
"" + gcInfo.getCollectionCount()));
table.row("gc." + gcInfo.getName() + ".time(ms)", "" + gcInfo.getCollectionTime());
}
return table;
}
String drawRuntimeInfoAndTomcatInfo(TableElement runtimeInfoTable, TableElement tomcatInfoTable, int width, int height) {
if (height <= 0) {
return "";
}
TableElement resultTable = new TableElement(1, 1);
if (tomcatInfoTable != null) {
resultTable.row(runtimeInfoTable, tomcatInfoTable);
} else {
resultTable = runtimeInfoTable;
}
return RenderUtil.render(resultTable, width, height);
}
private static TableElement drawRuntimeInfo(RuntimeInfoVO runtimeInfo) {
TableElement table = new TableElement(1, 1).rightCellPadding(1);
table.add(new RowElement().style(Decoration.bold.fg(Color.black).bg(Color.white)).add("Runtime", ""));
table.row("os.name", runtimeInfo.getOsName());
table.row("os.version", runtimeInfo.getOsVersion());
table.row("java.version", runtimeInfo.getJavaVersion());
table.row("java.home", runtimeInfo.getJavaHome());
table.row("systemload.average", String.format("%.2f", runtimeInfo.getSystemLoadAverage()));
table.row("processors", "" + runtimeInfo.getProcessors());
table.row("timestamp/uptime", new Date(runtimeInfo.getTimestamp()).toString() + "/" + runtimeInfo.getUptime() + "s");
return table;
}
private static String formatBytes(long size) {
int unit = 1;
String unitStr = "B";
if (size / 1024 > 0) {
unit = 1024;
unitStr = "K";
} else if (size / 1024 / 1024 > 0) {
unit = 1024 * 1024;
unitStr = "M";
}
return String.format("%d%s", size / unit, unitStr);
}
private TableElement drawTomcatInfo(TomcatInfoVO tomcatInfo) {
if (tomcatInfo == null) {
return null;
}
//header
TableElement table = new TableElement(1, 1).rightCellPadding(1);
table.add(new RowElement().style(Decoration.bold.fg(Color.black).bg(Color.white)).add("Tomcat", ""));
if (tomcatInfo.getConnectorStats() != null) {
for (TomcatInfoVO.ConnectorStats connectorStat : tomcatInfo.getConnectorStats()) {
table.add(new RowElement().style(Decoration.bold.bold()).add("connector", connectorStat.getName()));
table.row("QPS", String.format("%.2f", connectorStat.getQps()));
table.row("RT(ms)", String.format("%.2f", connectorStat.getRt()));
table.row("error/s", String.format("%.2f", connectorStat.getError()));
table.row("received/s", formatBytes(connectorStat.getReceived()));
table.row("sent/s", formatBytes(connectorStat.getSent()));
}
}
if (tomcatInfo.getThreadPools() != null) {
for (TomcatInfoVO.ThreadPool threadPool : tomcatInfo.getThreadPools()) {
table.add(new RowElement().style(Decoration.bold.bold()).add("threadpool", threadPool.getName()));
table.row("busy", "" + threadPool.getBusy());
table.row("total", "" + threadPool.getTotal());
}
}
return table;
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.DumpClassModel;
import com.taobao.arthas.core.command.model.DumpClassVO;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.ClassUtils;
import com.taobao.arthas.core.util.TypeRenderUtils;
import com.taobao.text.Color;
import com.taobao.text.Decoration;
import com.taobao.text.ui.Element;
import com.taobao.text.ui.LabelElement;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
import java.util.List;
import static com.taobao.text.ui.Element.label;
/**
* @author gongdewei 2020/4/21
*/
public class DumpClassView extends ResultView<DumpClassModel> {
@Override
public void draw(CommandProcess process, DumpClassModel result) {
if (result.getMatchedClassLoaders() != null) {
process.write("Matched classloaders: \n");
ClassLoaderView.drawClassLoaders(process, result.getMatchedClassLoaders(), false);
process.write("\n");
return;
}
if (result.getDumpedClasses() != null) {
drawDumpedClasses(process, result.getDumpedClasses());
} else if (result.getMatchedClasses() != null) {
Element table = ClassUtils.renderMatchedClasses(result.getMatchedClasses());
process.write(RenderUtil.render(table)).write("\n");
}
}
private void drawDumpedClasses(CommandProcess process, List<DumpClassVO> classVOs) {
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
table.row(new LabelElement("HASHCODE").style(Decoration.bold.bold()),
new LabelElement("CLASSLOADER").style(Decoration.bold.bold()),
new LabelElement("LOCATION").style(Decoration.bold.bold()));
for (DumpClassVO clazz : classVOs) {
table.row(label(clazz.getClassLoaderHash()).style(Decoration.bold.fg(Color.red)),
TypeRenderUtils.drawClassLoader(clazz),
label(clazz.getLocation()).style(Decoration.bold.fg(Color.red)));
}
process.write(RenderUtil.render(table, process.width()))
.write(com.taobao.arthas.core.util.Constants.EMPTY_STRING);
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.EchoModel;
import com.taobao.arthas.core.shell.command.CommandProcess;
/**
* @author gongdewei 2020/5/11
*/
public class EchoView extends ResultView<EchoModel> {
@Override
public void draw(CommandProcess process, EchoModel result) {
process.write(result.getContent()).write("\n");
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.EnhancerModel;
import com.taobao.arthas.core.shell.command.CommandProcess;
/**
* Term view for EnhancerModel
* @author gongdewei 2020/7/21
*/
public class EnhancerView extends ResultView<EnhancerModel> {
@Override
public void draw(CommandProcess process, EnhancerModel result) {
// ignore enhance result status, judge by the following output
if (result.getEffect() != null) {
process.write(ViewRenderUtil.renderEnhancerAffect(result.getEffect()));
}
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.GetStaticModel;
import com.taobao.arthas.core.command.model.ObjectVO;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.ClassUtils;
import com.taobao.arthas.core.util.StringUtils;
import com.taobao.arthas.core.view.ObjectView;
import com.taobao.text.ui.Element;
import com.taobao.text.util.RenderUtil;
/**
* @author gongdewei 2020/4/20
*/
public class GetStaticView extends ResultView<GetStaticModel> {
@Override
public void draw(CommandProcess process, GetStaticModel result) {
if (result.getMatchedClassLoaders() != null) {
process.write("Matched classloaders: \n");
ClassLoaderView.drawClassLoaders(process, result.getMatchedClassLoaders(), false);
process.write("\n");
return;
}
if (result.getField() != null) {
ObjectVO field = result.getField();
String valueStr = StringUtils.objectToString(field.needExpand() ? new ObjectView(field).draw() : field.getObject());
process.write("field: " + result.getFieldName() + "\n" + valueStr + "\n");
} else if (result.getMatchedClasses() != null) {
Element table = ClassUtils.renderMatchedClasses(result.getMatchedClasses());
process.write(RenderUtil.render(table)).write("\n");
}
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.CommandVO;
import com.taobao.arthas.core.command.model.HelpModel;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.usage.StyledUsageFormatter;
import com.taobao.middleware.cli.CLI;
import com.taobao.text.Color;
import com.taobao.text.Decoration;
import com.taobao.text.Style;
import com.taobao.text.ui.Element;
import com.taobao.text.ui.LabelElement;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
import java.util.List;
import static com.taobao.text.ui.Element.label;
import static com.taobao.text.ui.Element.row;
/**
* @author gongdewei 2020/4/3
*/
public class HelpView extends ResultView<HelpModel> {
@Override
public void draw(CommandProcess process, HelpModel result) {
if (result.getCommands() != null) {
String message = RenderUtil.render(mainHelp(result.getCommands()), process.width());
process.write(message);
} else if (result.getDetailCommand() != null) {
process.write(commandHelp(result.getDetailCommand().cli(), process.width()));
}
}
private static Element mainHelp(List<CommandVO> commands) {
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
table.row(new LabelElement("NAME").style(Style.style(Decoration.bold)), new LabelElement("DESCRIPTION"));
for (CommandVO commandVO : commands) {
table.add(row().add(label(commandVO.getName()).style(Style.style(Color.green))).add(label(commandVO.getSummary())));
}
return table;
}
private static String commandHelp(CLI command, int width) {
return StyledUsageFormatter.styledUsage(command, width);
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.ClassVO;
import com.taobao.arthas.core.command.model.JadModel;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.ClassUtils;
import com.taobao.arthas.core.util.TypeRenderUtils;
import com.taobao.text.Color;
import com.taobao.text.Decoration;
import com.taobao.text.lang.LangRenderUtil;
import com.taobao.text.ui.Element;
import com.taobao.text.ui.LabelElement;
import com.taobao.text.util.RenderUtil;
/**
* @author gongdewei 2020/4/22
*/
public class JadView extends ResultView<JadModel> {
@Override
public void draw(CommandProcess process, JadModel result) {
if (result.getMatchedClassLoaders() != null) {
process.write("Matched classloaders: \n");
ClassLoaderView.drawClassLoaders(process, result.getMatchedClassLoaders(), false);
process.write("\n");
return;
}
int width = process.width();
if (result.getMatchedClasses() != null) {
Element table = ClassUtils.renderMatchedClasses(result.getMatchedClasses());
process.write(RenderUtil.render(table, width)).write("\n");
} else {
ClassVO classInfo = result.getClassInfo();
if (classInfo != null) {
process.write("\n");
process.write(RenderUtil.render(new LabelElement("ClassLoader: ").style(Decoration.bold.fg(Color.red)), width));
process.write(RenderUtil.render(TypeRenderUtils.drawClassLoader(classInfo), width) + "\n");
}
if (result.getLocation() != null) {
process.write(RenderUtil.render(new LabelElement("Location: ").style(Decoration.bold.fg(Color.red)), width));
process.write(RenderUtil.render(new LabelElement(result.getLocation()).style(Decoration.bold.fg(Color.blue)), width) + "\n");
}
process.write(LangRenderUtil.render(result.getSource()) + "\n");
process.write(com.taobao.arthas.core.util.Constants.EMPTY_STRING);
}
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.JvmModel;
import com.taobao.arthas.core.command.model.JvmItemVO;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.StringUtils;
import com.taobao.text.Decoration;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static com.taobao.text.ui.Element.label;
/**
* View of 'jvm' command
*
* @author gongdewei 2020/4/24
*/
public class JvmView extends ResultView<JvmModel> {
@Override
public void draw(CommandProcess process, JvmModel result) {
TableElement table = new TableElement(2, 5).leftCellPadding(1).rightCellPadding(1);
for (Map.Entry<String, List<JvmItemVO>> entry : result.getJvmInfo().entrySet()) {
String group = entry.getKey();
List<JvmItemVO> items = entry.getValue();
table.row(true, label(group).style(Decoration.bold.bold()));
for (JvmItemVO item : items) {
String valueStr;
if (item.getValue() instanceof Map && item.getName().endsWith("MEMORY-USAGE")) {
valueStr = renderMemoryUsage((Map<String, Object>) item.getValue());
} else {
valueStr = renderItemValue(item.getValue());
}
if (item.getDesc() != null) {
table.row(item.getName() + "\n[" + item.getDesc() + "]", valueStr);
} else {
table.row(item.getName(), valueStr);
}
}
table.row("", "");
}
process.write(RenderUtil.render(table, process.width()));
}
private String renderCountTime(long[] value) {
//count/time
return value[0] + "/" + value[1];
}
private String renderItemValue(Object value) {
if (value == null) {
return "null";
}
if (value instanceof Collection) {
return renderCollectionValue((Collection) value);
} else if (value instanceof String[]) {
return renderArrayValue((String[]) value);
} else if (value instanceof Map) {
return renderMapValue((Map) value);
}
return String.valueOf(value);
}
private String renderCollectionValue(Collection<String> strings) {
final StringBuilder colSB = new StringBuilder();
if (strings.isEmpty()) {
colSB.append("[]");
} else {
for (String str : strings) {
colSB.append(str).append("\n");
}
}
return colSB.toString();
}
private String renderArrayValue(String... stringArray) {
final StringBuilder colSB = new StringBuilder();
if (null == stringArray
|| stringArray.length == 0) {
colSB.append("[]");
} else {
for (String str : stringArray) {
colSB.append(str).append("\n");
}
}
return colSB.toString();
}
private String renderMapValue(Map<String, Object> valueMap) {
final StringBuilder colSB = new StringBuilder();
if (valueMap != null) {
for (Map.Entry<String, Object> entry : valueMap.entrySet()) {
colSB.append(entry.getKey()).append(" : ").append(entry.getValue()).append("\n");
}
}
return colSB.toString();
}
private String renderMemoryUsage(Map<String, Object> valueMap) {
final StringBuilder colSB = new StringBuilder();
String[] keys = new String[]{"init", "used", "committed", "max"};
for (String key : keys) {
Object value = valueMap.get(key);
String valueStr = value != null ? formatMemoryByte((Long) value) : "";
colSB.append(key).append(" : ").append(valueStr).append("\n");
}
return colSB.toString();
}
private String formatMemoryByte(long bytes) {
return String.format("%s(%s)", bytes, StringUtils.humanReadableByteCount(bytes));
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.logger.LoggerHelper;
import com.taobao.arthas.core.command.model.LoggerModel;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.text.Decoration;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
import java.util.List;
import java.util.Map;
import static com.taobao.text.ui.Element.label;
/**
* View of 'logger' command
*
* @author gongdewei 2020/4/22
*/
public class LoggerView extends ResultView<LoggerModel> {
@Override
public void draw(CommandProcess process, LoggerModel result) {
if (result.getMatchedClassLoaders() != null) {
process.write("Matched classloaders: \n");
ClassLoaderView.drawClassLoaders(process, result.getMatchedClassLoaders(), false);
process.write("\n");
return;
}
process.write(renderLoggerInfo(result.getLoggerInfoMap(), process.width()));
}
private String renderLoggerInfo(Map<String, Map<String, Object>> loggerInfos, int width) {
StringBuilder sb = new StringBuilder(8192);
for (Map.Entry<String, Map<String, Object>> entry : loggerInfos.entrySet()) {
Map<String, Object> info = entry.getValue();
TableElement table = new TableElement(2, 10).leftCellPadding(1).rightCellPadding(1);
TableElement appendersTable = new TableElement().rightCellPadding(1);
Class<?> clazz = (Class<?>) info.get(LoggerHelper.clazz);
table.row(label(LoggerHelper.name).style(Decoration.bold.bold()), label("" + info.get(LoggerHelper.name)))
.row(label(LoggerHelper.clazz).style(Decoration.bold.bold()), label("" + clazz.getName()))
.row(label(LoggerHelper.classLoader).style(Decoration.bold.bold()),
label("" + info.get(LoggerHelper.classLoader)))
.row(label(LoggerHelper.classLoaderHash).style(Decoration.bold.bold()),
label("" + info.get(LoggerHelper.classLoaderHash)))
.row(label(LoggerHelper.level).style(Decoration.bold.bold()),
label("" + info.get(LoggerHelper.level)));
if (info.get(LoggerHelper.effectiveLevel) != null) {
table.row(label(LoggerHelper.effectiveLevel).style(Decoration.bold.bold()),
label("" + info.get(LoggerHelper.effectiveLevel)));
}
if (info.get(LoggerHelper.config) != null) {
table.row(label(LoggerHelper.config).style(Decoration.bold.bold()),
label("" + info.get(LoggerHelper.config)));
}
table.row(label(LoggerHelper.additivity).style(Decoration.bold.bold()),
label("" + info.get(LoggerHelper.additivity)))
.row(label(LoggerHelper.codeSource).style(Decoration.bold.bold()),
label("" + info.get(LoggerHelper.codeSource)));
@SuppressWarnings("unchecked")
List<Map<String, Object>> appenders = (List<Map<String, Object>>) info.get(LoggerHelper.appenders);
if (appenders != null && !appenders.isEmpty()) {
for (Map<String, Object> appenderInfo : appenders) {
Class<?> appenderClass = (Class<?>) appenderInfo.get(LoggerHelper.clazz);
appendersTable.row(label(LoggerHelper.name).style(Decoration.bold.bold()),
label("" + appenderInfo.get(LoggerHelper.name)));
appendersTable.row(label(LoggerHelper.clazz), label("" + appenderClass.getName()));
appendersTable.row(label(LoggerHelper.classLoader), label("" + info.get(LoggerHelper.classLoader)));
appendersTable.row(label(LoggerHelper.classLoaderHash),
label("" + info.get(LoggerHelper.classLoaderHash)));
if (appenderInfo.get(LoggerHelper.file) != null) {
appendersTable.row(label(LoggerHelper.file), label("" + appenderInfo.get(LoggerHelper.file)));
}
if (appenderInfo.get(LoggerHelper.target) != null) {
appendersTable.row(label(LoggerHelper.target),
label("" + appenderInfo.get(LoggerHelper.target)));
}
if (appenderInfo.get(LoggerHelper.blocking) != null) {
appendersTable.row(label(LoggerHelper.blocking),
label("" + appenderInfo.get(LoggerHelper.blocking)));
}
if (appenderInfo.get(LoggerHelper.appenderRef) != null) {
appendersTable.row(label(LoggerHelper.appenderRef),
label("" + appenderInfo.get(LoggerHelper.appenderRef)));
}
}
table.row(label("appenders").style(Decoration.bold.bold()), appendersTable);
}
sb.append(RenderUtil.render(table, width)).append('\n');
}
return sb.toString();
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.MBeanAttributeVO;
import com.taobao.arthas.core.command.model.MBeanModel;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.text.Color;
import com.taobao.text.Decoration;
import com.taobao.text.ui.LabelElement;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
import javax.management.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static com.taobao.text.ui.Element.label;
import static javax.management.MBeanOperationInfo.*;
/**
* View of 'mbean' command
*
* @author gongdewei 2020/4/26
*/
public class MBeanView extends ResultView<MBeanModel> {
@Override
public void draw(CommandProcess process, MBeanModel result) {
if (result.getMbeanNames() != null) {
drawMBeanNames(process, result.getMbeanNames());
} else if (result.getMbeanMetadata() != null) {
drawMBeanMetadata(process, result.getMbeanMetadata());
} else if (result.getMbeanAttribute() != null) {
drawMBeanAttributes(process, result.getMbeanAttribute());
}
}
private void drawMBeanAttributes(CommandProcess process, Map<String, List<MBeanAttributeVO>> mbeanAttributeMap) {
for (Map.Entry<String, List<MBeanAttributeVO>> entry : mbeanAttributeMap.entrySet()) {
String objectName = entry.getKey();
List<MBeanAttributeVO> attributeVOList = entry.getValue();
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
table.row(true, "OBJECT_NAME", objectName);
table.row(true, label("NAME").style(Decoration.bold.bold()),
label("VALUE").style(Decoration.bold.bold()));
for (MBeanAttributeVO attributeVO : attributeVOList) {
String attributeName = attributeVO.getName();
String valueStr;
if (attributeVO.getError() != null) {
valueStr = RenderUtil.render(new LabelElement(attributeVO.getError()).style(Decoration.bold_off.fg(Color.red)));
} else {
//convert array to list
// TODO support all array type
Object value = attributeVO.getValue();
if (value instanceof String[]) {
value = Arrays.asList((String[]) value);
} else if (value instanceof Integer[]) {
value = Arrays.asList((Integer[]) value);
} else if (value instanceof Long[]) {
value = Arrays.asList((Long[]) value);
} else if (value instanceof int[]) {
value = convertArrayToList((int[]) value);
} else if (value instanceof long[]) {
value = convertArrayToList((long[]) value);
}
//to string
valueStr = String.valueOf(value);
}
table.row(attributeName, valueStr);
}
process.write(RenderUtil.render(table, process.width()));
process.write("\n");
}
}
private List<Long> convertArrayToList(long[] longs) {
List<Long> list = new ArrayList<Long>();
for (long aLong : longs) {
list.add(aLong);
}
return list;
}
private List<Integer> convertArrayToList(int[] ints) {
List<Integer> list = new ArrayList<Integer>();
for (int anInt : ints) {
list.add(anInt);
}
return list;
}
private void drawMBeanMetadata(CommandProcess process, Map<String, MBeanInfo> mbeanMetadata) {
TableElement table = createTable();
for (Map.Entry<String, MBeanInfo> entry : mbeanMetadata.entrySet()) {
String objectName = entry.getKey();
MBeanInfo mBeanInfo = entry.getValue();
drawMetaInfo(mBeanInfo, objectName, table);
drawAttributeInfo(mBeanInfo.getAttributes(), table);
drawOperationInfo(mBeanInfo.getOperations(), table);
drawNotificationInfo(mBeanInfo.getNotifications(), table);
}
process.write(RenderUtil.render(table, process.width()));
}
private void drawMBeanNames(CommandProcess process, List<String> mbeanNames) {
for (String mbeanName : mbeanNames) {
process.write(mbeanName).write("\n");
}
}
private static TableElement createTable() {
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
table.row(true, label("NAME").style(Decoration.bold.bold()),
label("VALUE").style(Decoration.bold.bold()));
return table;
}
private void drawMetaInfo(MBeanInfo mBeanInfo, String objectName, TableElement table) {
table.row(new LabelElement("MBeanInfo").style(Decoration.bold.fg(Color.red)));
table.row(new LabelElement("Info:").style(Decoration.bold.fg(Color.yellow)));
table.row("ObjectName", objectName);
table.row("ClassName", mBeanInfo.getClassName());
table.row("Description", mBeanInfo.getDescription());
drawDescriptorInfo("Info Descriptor:", mBeanInfo, table);
MBeanConstructorInfo[] constructors = mBeanInfo.getConstructors();
if (constructors.length > 0) {
for (int i = 0; i < constructors.length; i++) {
table.row(new LabelElement("Constructor-" + i).style(Decoration.bold.fg(Color.yellow)));
table.row("Name", constructors[i].getName());
table.row("Description", constructors[i].getDescription());
}
}
}
private void drawAttributeInfo(MBeanAttributeInfo[] attributes, TableElement table) {
for (MBeanAttributeInfo attribute : attributes) {
table.row(new LabelElement("MBeanAttributeInfo").style(Decoration.bold.fg(Color.red)));
table.row(new LabelElement("Attribute:").style(Decoration.bold.fg(Color.yellow)));
table.row("Name", attribute.getName());
table.row("Description", attribute.getDescription());
table.row("Readable", String.valueOf(attribute.isReadable()));
table.row("Writable", String.valueOf(attribute.isWritable()));
table.row("Is", String.valueOf(attribute.isIs()));
table.row("Type", attribute.getType());
drawDescriptorInfo("Attribute Descriptor:", attribute, table);
}
}
private void drawOperationInfo(MBeanOperationInfo[] operations, TableElement table) {
for (MBeanOperationInfo operation : operations) {
table.row(new LabelElement("MBeanOperationInfo").style(Decoration.bold.fg(Color.red)));
table.row(new LabelElement("Operation:").style(Decoration.bold.fg(Color.yellow)));
table.row("Name", operation.getName());
table.row("Description", operation.getDescription());
String impact = "";
switch (operation.getImpact()) {
case ACTION:
impact = "action";
break;
case ACTION_INFO:
impact = "action/info";
break;
case INFO:
impact = "info";
break;
case UNKNOWN:
impact = "unknown";
break;
}
table.row("Impact", impact);
table.row("ReturnType", operation.getReturnType());
MBeanParameterInfo[] signature = operation.getSignature();
if (signature.length > 0) {
for (int i = 0; i < signature.length; i++) {
table.row(new LabelElement("Parameter-" + i).style(Decoration.bold.fg(Color.yellow)));
table.row("Name", signature[i].getName());
table.row("Type", signature[i].getType());
table.row("Description", signature[i].getDescription());
}
}
drawDescriptorInfo("Operation Descriptor:", operation, table);
}
}
private void drawNotificationInfo(MBeanNotificationInfo[] notificationInfos, TableElement table) {
for (MBeanNotificationInfo notificationInfo : notificationInfos) {
table.row(new LabelElement("MBeanNotificationInfo").style(Decoration.bold.fg(Color.red)));
table.row(new LabelElement("Notification:").style(Decoration.bold.fg(Color.yellow)));
table.row("Name", notificationInfo.getName());
table.row("Description", notificationInfo.getDescription());
table.row("NotifTypes", Arrays.toString(notificationInfo.getNotifTypes()));
drawDescriptorInfo("Notification Descriptor:", notificationInfo, table);
}
}
private void drawDescriptorInfo(String title, DescriptorRead descriptorRead, TableElement table) {
Descriptor descriptor = descriptorRead.getDescriptor();
String[] fieldNames = descriptor.getFieldNames();
if (fieldNames.length > 0) {
table.row(new LabelElement(title).style(Decoration.bold.fg(Color.yellow)));
for (String fieldName : fieldNames) {
Object fieldValue = descriptor.getFieldValue(fieldName);
table.row(fieldName, fieldValue == null ? "" : fieldValue.toString());
}
}
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.MemoryCompilerModel;
import com.taobao.arthas.core.shell.command.CommandProcess;
/**
* @author gongdewei 2020/4/20
*/
public class MemoryCompilerView extends ResultView<MemoryCompilerModel> {
@Override
public void draw(CommandProcess process, MemoryCompilerModel result) {
if (result.getMatchedClassLoaders() != null) {
process.write("Matched classloaders: \n");
ClassLoaderView.drawClassLoaders(process, result.getMatchedClassLoaders(), false);
process.write("\n");
return;
}
process.write("Memory compiler output:\n");
for (String file : result.getFiles()) {
process.write(file + '\n');
}
}
}
package com.taobao.arthas.core.command.view;
import java.lang.management.MemoryUsage;
import java.util.List;
import java.util.Map;
import com.taobao.arthas.core.command.model.MemoryEntryVO;
import com.taobao.arthas.core.command.model.MemoryModel;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.text.Color;
import com.taobao.text.Decoration;
import com.taobao.text.Style;
import com.taobao.text.ui.RowElement;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
/**
* View of 'memory' command
*
* @author hengyunabc 2022-03-01
*/
public class MemoryView extends ResultView<MemoryModel> {
@Override
public void draw(CommandProcess process, MemoryModel result) {
TableElement table = drawMemoryInfo(result.getMemoryInfo());
process.write(RenderUtil.render(table, process.width()));
}
static TableElement drawMemoryInfo(Map<String, List<MemoryEntryVO>> memoryInfo) {
TableElement table = new TableElement(3, 1, 1, 1, 1).rightCellPadding(1);
table.add(new RowElement().style(Decoration.bold.fg(Color.black).bg(Color.white)).add("Memory",
"used", "total", "max", "usage"));
List<MemoryEntryVO> heapMemoryEntries = memoryInfo.get(MemoryEntryVO.TYPE_HEAP);
//heap memory
for (MemoryEntryVO memoryEntryVO : heapMemoryEntries) {
if (MemoryEntryVO.TYPE_HEAP.equals(memoryEntryVO.getName())) {
new MemoryEntry(memoryEntryVO).addTableRow(table, Decoration.bold.bold());
} else {
new MemoryEntry(memoryEntryVO).addTableRow(table);
}
}
//non-heap memory
List<MemoryEntryVO> nonheapMemoryEntries = memoryInfo.get(MemoryEntryVO.TYPE_NON_HEAP);
for (MemoryEntryVO memoryEntryVO : nonheapMemoryEntries) {
if (MemoryEntryVO.TYPE_NON_HEAP.equals(memoryEntryVO.getName())) {
new MemoryEntry(memoryEntryVO).addTableRow(table, Decoration.bold.bold());
} else {
new MemoryEntry(memoryEntryVO).addTableRow(table);
}
}
//buffer-pool
List<MemoryEntryVO> bufferPoolMemoryEntries = memoryInfo.get(MemoryEntryVO.TYPE_BUFFER_POOL);
if (bufferPoolMemoryEntries != null) {
for (MemoryEntryVO memoryEntryVO : bufferPoolMemoryEntries) {
new MemoryEntry(memoryEntryVO).addTableRow(table);
}
}
return table;
}
static class MemoryEntry {
String name;
long used;
long total;
long max;
int unit;
String unitStr;
public MemoryEntry(String name, long used, long total, long max) {
this.name = name;
this.used = used;
this.total = total;
this.max = max;
unitStr = "K";
unit = 1024;
if (used / 1024 / 1024 > 0) {
unitStr = "M";
unit = 1024 * 1024;
}
}
public MemoryEntry(String name, MemoryUsage usage) {
this(name, usage.getUsed(), usage.getCommitted(), usage.getMax());
}
public MemoryEntry(MemoryEntryVO memoryEntryVO) {
this(memoryEntryVO.getName(), memoryEntryVO.getUsed(), memoryEntryVO.getTotal(), memoryEntryVO.getMax());
}
private String format(long value) {
String valueStr = "-";
if (value == -1) {
return "-1";
}
if (value != Long.MIN_VALUE) {
valueStr = value / unit + unitStr;
}
return valueStr;
}
public void addTableRow(TableElement table) {
double usage = used / (double) (max == -1 || max == Long.MIN_VALUE ? total : max) * 100;
if (Double.isNaN(usage) || Double.isInfinite(usage)) {
usage = 0;
}
table.row(name, format(used), format(total), format(max), String.format("%.2f%%", usage));
}
public void addTableRow(TableElement table, Style.Composite style) {
double usage = used / (double) (max == -1 || max == Long.MIN_VALUE ? total : max) * 100;
if (Double.isNaN(usage) || Double.isInfinite(usage)) {
usage = 0;
}
table.add(new RowElement().style(style).add(name, format(used), format(total), format(max),
String.format("%.2f%%", usage)));
}
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.MessageModel;
import com.taobao.arthas.core.shell.command.CommandProcess;
/**
* @author gongdewei 2020/4/2
*/
public class MessageView extends ResultView<MessageModel> {
@Override
public void draw(CommandProcess process, MessageModel result) {
writeln(process, result.getMessage());
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.MonitorModel;
import com.taobao.arthas.core.command.monitor200.MonitorData;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.text.Decoration;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import static com.taobao.text.ui.Element.label;
/**
* Term view for MonitorModel
* @author gongdewei 2020/4/28
*/
public class MonitorView extends ResultView<MonitorModel> {
@Override
public void draw(CommandProcess process, MonitorModel result) {
TableElement table = new TableElement(2, 3, 3, 1, 1, 1, 1, 1).leftCellPadding(1).rightCellPadding(1);
table.row(true, label("timestamp").style(Decoration.bold.bold()),
label("class").style(Decoration.bold.bold()),
label("method").style(Decoration.bold.bold()),
label("total").style(Decoration.bold.bold()),
label("success").style(Decoration.bold.bold()),
label("fail").style(Decoration.bold.bold()),
label("avg-rt(ms)").style(Decoration.bold.bold()),
label("fail-rate").style(Decoration.bold.bold()));
final DecimalFormat df = new DecimalFormat("0.00");
for (MonitorData data : result.getMonitorDataList()) {
table.row(
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),
data.getClassName(),
data.getMethodName(),
"" + data.getTotal(),
"" + data.getSuccess(),
"" + data.getFailed(),
df.format(div(data.getCost(), data.getTotal())),
df.format(100.0d * div(data.getFailed(), data.getTotal())) + "%"
);
}
process.write(RenderUtil.render(table, process.width()) + "\n");
}
private double div(double a, double b) {
if (b == 0) {
return 0;
}
return a / b;
}
}
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.ObjectVO;
import com.taobao.arthas.core.command.model.OgnlModel;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.StringUtils;
import com.taobao.arthas.core.view.ObjectView;
/**
* Term view of OgnlCommand
* @author gongdewei 2020/4/29
*/
public class OgnlView extends ResultView<OgnlModel> {
@Override
public void draw(CommandProcess process, OgnlModel model) {
if (model.getMatchedClassLoaders() != null) {
process.write("Matched classloaders: \n");
ClassLoaderView.drawClassLoaders(process, model.getMatchedClassLoaders(), false);
process.write("\n");
return;
}
ObjectVO objectVO = model.getValue();
String resultStr = StringUtils.objectToString(objectVO.needExpand() ? new ObjectView(objectVO).draw() : objectVO.getObject());
process.write(resultStr).write("\n");
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment