From 5c564fbd0fc3305a14ac5cf46030589ed227a12d Mon Sep 17 00:00:00 2001 From: gongdewei Date: Tue, 14 Jul 2020 20:27:31 +0800 Subject: [PATCH] transform command: mbean --- .../core/command/model/MBeanAttributeVO.java | 47 +++ .../arthas/core/command/model/MBeanModel.java | 55 ++++ .../core/command/monitor200/JvmCommand.java | 1 - .../core/command/monitor200/MBeanCommand.java | 268 ++++++++---------- .../arthas/core/command/view/MBeanView.java | 212 ++++++++++++++ .../core/command/view/ResultViewResolver.java | 6 + 6 files changed, 443 insertions(+), 146 deletions(-) create mode 100644 core/src/main/java/com/taobao/arthas/core/command/model/MBeanAttributeVO.java create mode 100644 core/src/main/java/com/taobao/arthas/core/command/model/MBeanModel.java create mode 100644 core/src/main/java/com/taobao/arthas/core/command/view/MBeanView.java diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/MBeanAttributeVO.java b/core/src/main/java/com/taobao/arthas/core/command/model/MBeanAttributeVO.java new file mode 100644 index 000000000..cae43de59 --- /dev/null +++ b/core/src/main/java/com/taobao/arthas/core/command/model/MBeanAttributeVO.java @@ -0,0 +1,47 @@ +package com.taobao.arthas.core.command.model; + +/** + * MBean attribute + * + * @author gongdewei 2020/4/26 + */ +public class MBeanAttributeVO { + private String name; + private Object value; + private String error; + + public MBeanAttributeVO(String name, Object value) { + this.name = name; + this.value = value; + } + + public MBeanAttributeVO(String name, Object value, String error) { + this.name = name; + this.value = value; + this.error = error; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } +} diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/MBeanModel.java b/core/src/main/java/com/taobao/arthas/core/command/model/MBeanModel.java new file mode 100644 index 000000000..105da1518 --- /dev/null +++ b/core/src/main/java/com/taobao/arthas/core/command/model/MBeanModel.java @@ -0,0 +1,55 @@ +package com.taobao.arthas.core.command.model; + +import javax.management.MBeanInfo; +import java.util.List; +import java.util.Map; + +/** + * Model of 'mbean' + * + * @author gongdewei 2020/4/26 + */ +public class MBeanModel extends ResultModel { + + private List mbeanNames; + + private Map mbeanMetadata; + + private Map> mbeanAttribute; + + public MBeanModel() { + } + + public MBeanModel(List mbeanNames) { + this.mbeanNames = mbeanNames; + } + + @Override + public String getType() { + return "mbean"; + } + + public List getMbeanNames() { + return mbeanNames; + } + + public void setMbeanNames(List mbeanNames) { + this.mbeanNames = mbeanNames; + } + + public Map getMbeanMetadata() { + return mbeanMetadata; + } + + public void setMbeanMetadata(Map mbeanMetadata) { + this.mbeanMetadata = mbeanMetadata; + } + + public Map> getMbeanAttribute() { + return mbeanAttribute; + } + + public void setMbeanAttribute(Map> mbeanAttribute) { + this.mbeanAttribute = mbeanAttribute; + } +} diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/JvmCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/JvmCommand.java index 7ff325693..44eaeafd6 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/JvmCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/JvmCommand.java @@ -1,7 +1,6 @@ package com.taobao.arthas.core.command.monitor200; import com.taobao.arthas.core.command.Constants; -import com.taobao.arthas.core.command.model.GcInfoVO; import com.taobao.arthas.core.command.model.JvmModel; import com.taobao.arthas.core.shell.command.AnnotatedCommand; import com.taobao.arthas.core.shell.command.CommandProcess; diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/MBeanCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/MBeanCommand.java index 12f7d1575..563281337 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/MBeanCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/MBeanCommand.java @@ -3,6 +3,8 @@ 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.command.Constants; +import com.taobao.arthas.core.command.model.MBeanAttributeVO; +import com.taobao.arthas.core.command.model.MBeanModel; import com.taobao.arthas.core.shell.cli.CliToken; import com.taobao.arthas.core.shell.cli.Completion; import com.taobao.arthas.core.shell.cli.CompletionUtils; @@ -22,38 +24,25 @@ 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; -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 java.lang.management.ManagementFactory; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collection; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Timer; import java.util.TimerTask; -import javax.management.Descriptor; -import javax.management.DescriptorRead; import javax.management.MBeanAttributeInfo; -import javax.management.MBeanConstructorInfo; import javax.management.MBeanInfo; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanOperationInfo; -import javax.management.MBeanParameterInfo; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; - -import static com.taobao.text.ui.Element.label; -import static javax.management.MBeanOperationInfo.ACTION; -import static javax.management.MBeanOperationInfo.ACTION_INFO; -import static javax.management.MBeanOperationInfo.INFO; -import static javax.management.MBeanOperationInfo.UNKNOWN; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.TabularData; /** * Date: 2019/4/18 @@ -63,13 +52,16 @@ import static javax.management.MBeanOperationInfo.UNKNOWN; @Name("mbean") @Summary("Display the mbean information") @Description("\nExamples:\n" + - " mbean\n" + - " mbean -m java.lang:type=Threading\n" + - " mbean java.lang:type=Threading\n" + - " mbean java.lang:type=Threading *Count\n" + - " mbean -E java.lang:type=Threading PeakThreadCount|ThreadCount|DaemonThreadCount\n" + - " mbean -i 1000 java.lang:type=Threading *Count\n" + - Constants.WIKI + Constants.WIKI_HOME + "mbean") + " mbean\n" + + " mbean -m java.lang:type=Threading\n" + + " mbean java.lang:type=Threading\n" + + " mbean java.lang:type=Threading *Count\n" + + " mbean java.lang:type=MemoryPool,name=PS\\ Old\\ Gen\n" + + " mbean java.lang:type=MemoryPool,name=*\n" + + " mbean java.lang:type=MemoryPool,name=* Usage\n" + + " mbean -E java.lang:type=Threading PeakThreadCount|ThreadCount|DaemonThreadCount\n" + + " mbean -i 1000 java.lang:type=Threading *Count\n" + + Constants.WIKI + Constants.WIKI_HOME + "mbean") public class MBeanCommand extends AnnotatedCommand { private static final Logger logger = LoggerFactory.getLogger(MBeanCommand.class); @@ -84,7 +76,12 @@ public class MBeanCommand extends AnnotatedCommand { private long count = 0; @Argument(argName = "name-pattern", index = 0, required = false) - @Description("ObjectName pattern, see javax.management.ObjectName for more detail.") + @Description("ObjectName pattern, see javax.management.ObjectName for more detail. \n" + + "It looks like this: \n" + + " domain: key-property-list\n" + + "For example: \n" + + " java.lang:name=G1 Old Gen,type=MemoryPool\n" + + " java.lang:name=*,type=MemoryPool") public void setNamePattern(String name) { this.name = name; } @@ -107,7 +104,7 @@ public class MBeanCommand extends AnnotatedCommand { isRegEx = regEx; } - @Option(shortName = "m", longName = "metadata", flag = false) + @Option(shortName = "m", longName = "metadata", flag = true) @Description("Show metadata of mbean.") public void setMetaData(boolean metaData) { this.metaData = metaData; @@ -141,6 +138,7 @@ public class MBeanCommand extends AnnotatedCommand { @Override public void process(CommandProcess process) { + //每个分支调用process.end()结束执行 if (StringUtils.isEmpty(getName())) { listMBean(process); } else if (isMetaData()) { @@ -152,10 +150,11 @@ public class MBeanCommand extends AnnotatedCommand { private void listMBean(CommandProcess process) { Set objectNames = queryObjectNames(); + List mbeanNames = new ArrayList(objectNames.size()); for (ObjectName objectName : objectNames) { - process.write(objectName.toString()); - process.write("\n"); + mbeanNames.add(objectName.toString()); } + process.appendResult(new MBeanModel(mbeanNames)); process.end(); } @@ -192,6 +191,8 @@ public class MBeanCommand extends AnnotatedCommand { } else { timer.schedule(new MBeanTimerTask(process), 0); } + + //异步执行,这里不能调用process.end(),在timer task中结束命令执行 } public synchronized void stop() { @@ -214,19 +215,18 @@ public class MBeanCommand extends AnnotatedCommand { Set objectNames = queryObjectNames(); MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); try { - TableElement table = createTable(); + MBeanModel mbeanModel = new MBeanModel(); + Map mbeanMetaData = new LinkedHashMap(); + mbeanModel.setMbeanMetadata(mbeanMetaData); for (ObjectName objectName : objectNames) { MBeanInfo mBeanInfo = mBeanServer.getMBeanInfo(objectName); - drawMetaInfo(mBeanInfo, objectName, table); - drawAttributeInfo(mBeanInfo.getAttributes(), table); - drawOperationInfo(mBeanInfo.getOperations(), table); - drawNotificationInfo(mBeanInfo.getNotifications(), table); + mbeanMetaData.put(objectName.toString(), mBeanInfo); } - process.write(RenderUtil.render(table, process.width())); + process.appendResult(mbeanModel); + process.end(); } catch (Throwable e) { logger.warn("listMetaData error", e); - } finally { - process.end(); + process.end(1, "list mbean metadata error"); } } @@ -348,102 +348,6 @@ public class MBeanCommand extends AnnotatedCommand { return isRegEx ? new RegexMatcher(attribute) : new WildcardMatcher(attribute); } - private void drawMetaInfo(MBeanInfo mBeanInfo, ObjectName 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.toString()); - 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.toString()); - } - } - } - - 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; - } public class MBeanInterruptHandler extends CommandInterruptHandler { @@ -475,16 +379,20 @@ public class MBeanCommand extends AnnotatedCommand { // stop the timer timer.cancel(); timer.purge(); - process.write("Process ends after " + getNumOfExecutions() + " time(s).\n"); - process.end(); + process.end(-1, "Process ends after " + getNumOfExecutions() + " time(s)."); return; } try { + //result model + MBeanModel mBeanModel = new MBeanModel(); + Map> mbeanAttributeMap = new LinkedHashMap>(); + mBeanModel.setMbeanAttribute(mbeanAttributeMap); + MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer(); Set objectNames = queryObjectNames(); - TableElement table = createTable(); for (ObjectName objectName : objectNames) { + List attributeVOs = null; MBeanInfo mBeanInfo = platformMBeanServer.getMBeanInfo(objectName); MBeanAttributeInfo[] attributes = mBeanInfo.getAttributes(); for (MBeanAttributeInfo attribute : attributes) { @@ -492,29 +400,99 @@ public class MBeanCommand extends AnnotatedCommand { if (!getAttributeMatcher().matching(attributeName)) { continue; } - String value; + + //create attributeVO list + if (attributeVOs == null) { + attributeVOs = new ArrayList(); + mbeanAttributeMap.put(objectName.toString(), attributeVOs); + } + if (!attribute.isReadable()) { - value = RenderUtil.render(new LabelElement("Unavailable").style(Decoration.bold_off.fg(Color.red))); + attributeVOs.add(new MBeanAttributeVO(attributeName, null, "Unavailable")); } else { - Object attributeObj = platformMBeanServer.getAttribute(objectName, attributeName); - value = String.valueOf(attributeObj); + try { + Object attributeObj = platformMBeanServer.getAttribute(objectName, attributeName); + attributeVOs.add(createMBeanAttributeVO(attributeName, attributeObj)); + } catch (Throwable e) { + logger.error("read mbean attribute failed: objectName={}, attributeName={}", objectName, attributeName, e); + String errorStr; + Throwable cause = e.getCause(); + if (cause != null && cause instanceof UnsupportedOperationException) { + errorStr = "Unsupported"; + } else { + errorStr = "Failure"; + } + attributeVOs.add(new MBeanAttributeVO(attributeName, null, errorStr)); + } } - table.row(attributeName, value); } - process.write(RenderUtil.render(table, process.width())); - process.write("\n"); } + process.appendResult(mBeanModel); } catch (Throwable e) { - logger.warn("mbean error", e); + logger.warn("read mbean error", e); + stop(); + process.end(1, "read mbean error."); + return; } count++; process.times().incrementAndGet(); - if (getInterval() <= 0) { stop(); process.end(); } } } + + private MBeanAttributeVO createMBeanAttributeVO(String attributeName, Object originAttrValue) { + Object attrValue = convertAttrValue(attributeName, originAttrValue); + + return new MBeanAttributeVO(attributeName, attrValue); + } + + private Object convertAttrValue(String attributeName, Object originAttrValue) { + Object attrValue = originAttrValue; + + try { + if (originAttrValue instanceof ObjectName) { + attrValue = String.valueOf(originAttrValue); + } else if (attrValue instanceof CompositeData) { + //mbean java.lang:type=MemoryPool,name=* + CompositeData compositeData = (CompositeData) attrValue; + attrValue = convertCompositeData(attributeName, compositeData); + } else if (attrValue instanceof CompositeData[]) { + //mbean com.sun.management:type=HotSpotDiagnostic + CompositeData[] compositeDataArray = (CompositeData[]) attrValue; + List> dataList = new ArrayList>(compositeDataArray.length); + for (CompositeData compositeData : compositeDataArray) { + dataList.add(convertCompositeData(attributeName, compositeData)); + } + attrValue = dataList; + } else if (attrValue instanceof TabularData) { + //mbean java.lang:type=GarbageCollector,name=* + TabularData tabularData = (TabularData) attrValue; + Collection compositeDataList = (Collection) tabularData.values(); + List> dataList = new ArrayList>(compositeDataList.size()); + for (CompositeData compositeData : compositeDataList) { + dataList.add(convertCompositeData(attributeName, compositeData)); + } + attrValue = dataList; + } + } catch (Throwable e) { + logger.error("convert mbean attribute error, attribute: {}={}", attributeName, originAttrValue, e); + attrValue = String.valueOf(originAttrValue); + } + return attrValue; + } + + private Map convertCompositeData(String attributeName, CompositeData compositeData) { + Set keySet = compositeData.getCompositeType().keySet(); + String[] keys = keySet.toArray(new String[0]); + Object[] values = compositeData.getAll(keys); + Map data = new LinkedHashMap(); + for (int i = 0; i < keys.length; i++) { + data.put(keys[i], convertAttrValue(attributeName + "." + keys[i], values[i])); + } + return data; + } } \ No newline at end of file diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/MBeanView.java b/core/src/main/java/com/taobao/arthas/core/command/view/MBeanView.java new file mode 100644 index 000000000..87349036a --- /dev/null +++ b/core/src/main/java/com/taobao/arthas/core/command/view/MBeanView.java @@ -0,0 +1,212 @@ +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.*; +import static javax.management.MBeanOperationInfo.UNKNOWN; + +/** + * View of 'mbean' command + * + * @author gongdewei 2020/4/26 + */ +public class MBeanView extends ResultView { + @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> mbeanAttributeMap) { + for (Map.Entry> entry : mbeanAttributeMap.entrySet()) { + String objectName = entry.getKey(); + List 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 convertArrayToList(long[] longs) { + List list = new ArrayList(); + for (long aLong : longs) { + list.add(aLong); + } + return list; + } + + private List convertArrayToList(int[] ints) { + List list = new ArrayList(); + for (int anInt : ints) { + list.add(anInt); + } + return list; + } + + private void drawMBeanMetadata(CommandProcess process, Map mbeanMetadata) { + TableElement table = createTable(); + for (Map.Entry 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 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.toString()); + } + } + } + +} diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/ResultViewResolver.java b/core/src/main/java/com/taobao/arthas/core/command/view/ResultViewResolver.java index 9891883c2..4df0afbe4 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/view/ResultViewResolver.java +++ b/core/src/main/java/com/taobao/arthas/core/command/view/ResultViewResolver.java @@ -60,8 +60,14 @@ public class ResultViewResolver { registerView(SearchMethodView.class); //logger + registerView(LoggerView.class); //monitor2000 + registerView(DashboardView.class); + registerView(JvmView.class); + registerView(MBeanView.class); + registerView(PerfCounterView.class); + registerView(ThreadView.class); } catch (Throwable e) { logger.error("register result view failed", e);