|
|
|
@ -0,0 +1,520 @@
|
|
|
|
|
package com.taobao.arthas.core.command.monitor200;
|
|
|
|
|
|
|
|
|
|
import com.taobao.arthas.core.command.Constants;
|
|
|
|
|
import com.taobao.arthas.core.shell.cli.CliToken;
|
|
|
|
|
import com.taobao.arthas.core.shell.cli.Completion;
|
|
|
|
|
import com.taobao.arthas.core.shell.cli.CompletionUtils;
|
|
|
|
|
import com.taobao.arthas.core.shell.command.AnnotatedCommand;
|
|
|
|
|
import com.taobao.arthas.core.shell.command.CommandProcess;
|
|
|
|
|
import com.taobao.arthas.core.shell.handlers.Handler;
|
|
|
|
|
import com.taobao.arthas.core.shell.handlers.command.CommandInterruptHandler;
|
|
|
|
|
import com.taobao.arthas.core.shell.handlers.shell.QExitHandler;
|
|
|
|
|
import com.taobao.arthas.core.shell.session.Session;
|
|
|
|
|
import com.taobao.arthas.core.util.LogUtil;
|
|
|
|
|
import com.taobao.arthas.core.util.StringUtils;
|
|
|
|
|
import com.taobao.arthas.core.util.TokenUtils;
|
|
|
|
|
import com.taobao.arthas.core.util.matcher.Matcher;
|
|
|
|
|
import com.taobao.arthas.core.util.matcher.RegexMatcher;
|
|
|
|
|
import com.taobao.arthas.core.util.matcher.WildcardMatcher;
|
|
|
|
|
import com.taobao.middleware.cli.annotations.Argument;
|
|
|
|
|
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.middleware.logger.Logger;
|
|
|
|
|
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.HashSet;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Date: 2019/4/18
|
|
|
|
|
*
|
|
|
|
|
* @author xuzhiyi
|
|
|
|
|
*/
|
|
|
|
|
@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")
|
|
|
|
|
public class MBeanCommand extends AnnotatedCommand {
|
|
|
|
|
|
|
|
|
|
private static final Logger logger = LogUtil.getArthasLogger();
|
|
|
|
|
|
|
|
|
|
private String name;
|
|
|
|
|
private String attribute;
|
|
|
|
|
private boolean isRegEx = false;
|
|
|
|
|
private long interval = 0;
|
|
|
|
|
private boolean metaData;
|
|
|
|
|
private int numOfExecutions = 100;
|
|
|
|
|
private Timer timer;
|
|
|
|
|
private long count = 0;
|
|
|
|
|
|
|
|
|
|
@Argument(argName = "name-pattern", index = 0, required = false)
|
|
|
|
|
@Description("ObjectName pattern, see javax.management.ObjectName for more detail.")
|
|
|
|
|
public void setNamePattern(String name) {
|
|
|
|
|
this.name = name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Argument(argName = "attribute-pattern", index = 1, required = false)
|
|
|
|
|
@Description("Attribute name pattern.")
|
|
|
|
|
public void setAttributePattern(String attribute) {
|
|
|
|
|
this.attribute = attribute;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Option(shortName = "i", longName = "interval")
|
|
|
|
|
@Description("The interval (in ms) between two executions.")
|
|
|
|
|
public void setInterval(long interval) {
|
|
|
|
|
this.interval = interval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Option(shortName = "E", longName = "regex", flag = true)
|
|
|
|
|
@Description("Enable regular expression to match attribute name (wildcard matching by default).")
|
|
|
|
|
public void setRegEx(boolean regEx) {
|
|
|
|
|
isRegEx = regEx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Option(shortName = "m", longName = "metadata", flag = false)
|
|
|
|
|
@Description("Show metadata of mbean.")
|
|
|
|
|
public void setMetaData(boolean metaData) {
|
|
|
|
|
this.metaData = metaData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Option(shortName = "n", longName = "number-of-execution")
|
|
|
|
|
@Description("The number of times this command will be executed.")
|
|
|
|
|
public void setNumOfExecutions(int numOfExecutions) {
|
|
|
|
|
this.numOfExecutions = numOfExecutions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String getName() {
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean isRegEx() {
|
|
|
|
|
return isRegEx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean isMetaData() {
|
|
|
|
|
return metaData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public long getInterval() {
|
|
|
|
|
return interval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int getNumOfExecutions() {
|
|
|
|
|
return numOfExecutions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void process(CommandProcess process) {
|
|
|
|
|
if (StringUtils.isEmpty(getName())) {
|
|
|
|
|
listMBean(process);
|
|
|
|
|
} else if (isMetaData()) {
|
|
|
|
|
listMetaData(process);
|
|
|
|
|
} else {
|
|
|
|
|
listAttribute(process);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void listMBean(CommandProcess process) {
|
|
|
|
|
Set<ObjectName> objectNames = queryObjectNames();
|
|
|
|
|
for (ObjectName objectName : objectNames) {
|
|
|
|
|
process.write(objectName.toString());
|
|
|
|
|
process.write("\n");
|
|
|
|
|
}
|
|
|
|
|
process.end();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void listAttribute(final CommandProcess process) {
|
|
|
|
|
Session session = process.session();
|
|
|
|
|
timer = new Timer("Timer-for-arthas-mbean-" + session.getSessionId(), true);
|
|
|
|
|
|
|
|
|
|
// ctrl-C support
|
|
|
|
|
process.interruptHandler(new MBeanInterruptHandler(process, timer));
|
|
|
|
|
|
|
|
|
|
// 通过handle回调,在suspend和end时停止timer,resume时重启timer
|
|
|
|
|
Handler<Void> stopHandler = new Handler<Void>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void handle(Void event) {
|
|
|
|
|
stop();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Handler<Void> restartHandler = new Handler<Void>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void handle(Void event) {
|
|
|
|
|
restart(process);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
process.suspendHandler(stopHandler);
|
|
|
|
|
process.resumeHandler(restartHandler);
|
|
|
|
|
process.endHandler(stopHandler);
|
|
|
|
|
// q exit support
|
|
|
|
|
process.stdinHandler(new QExitHandler(process));
|
|
|
|
|
|
|
|
|
|
// start the timer
|
|
|
|
|
if (getInterval() > 0) {
|
|
|
|
|
timer.scheduleAtFixedRate(new MBeanTimerTask(process), 0, getInterval());
|
|
|
|
|
} else {
|
|
|
|
|
timer.schedule(new MBeanTimerTask(process), 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public synchronized void stop() {
|
|
|
|
|
if (timer != null) {
|
|
|
|
|
timer.cancel();
|
|
|
|
|
timer.purge();
|
|
|
|
|
timer = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public synchronized void restart(CommandProcess process) {
|
|
|
|
|
if (timer == null) {
|
|
|
|
|
Session session = process.session();
|
|
|
|
|
timer = new Timer("Timer-for-arthas-mbean-" + session.getSessionId(), true);
|
|
|
|
|
timer.scheduleAtFixedRate(new MBeanTimerTask(process), 0, getInterval());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void listMetaData(CommandProcess process) {
|
|
|
|
|
Set<ObjectName> objectNames = queryObjectNames();
|
|
|
|
|
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
|
|
|
|
|
try {
|
|
|
|
|
TableElement table = createTable();
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
process.write(RenderUtil.render(table, process.width()));
|
|
|
|
|
} catch (Throwable e) {
|
|
|
|
|
logger.warn("listMetaData error", e);
|
|
|
|
|
} finally {
|
|
|
|
|
process.end();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void complete(Completion completion) {
|
|
|
|
|
int argumentIndex = CompletionUtils.detectArgumentIndex(completion);
|
|
|
|
|
if (argumentIndex == 1) {
|
|
|
|
|
if (!completeBeanName(completion)) {
|
|
|
|
|
super.complete(completion);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
} else if (argumentIndex == 2) {
|
|
|
|
|
if (!completeAttributeName(completion)) {
|
|
|
|
|
super.complete(completion);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
super.complete(completion);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean completeBeanName(Completion completion) {
|
|
|
|
|
List<CliToken> tokens = completion.lineTokens();
|
|
|
|
|
String lastToken = TokenUtils.getLast(tokens).value();
|
|
|
|
|
|
|
|
|
|
if (StringUtils.isBlank(lastToken)) {
|
|
|
|
|
lastToken = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lastToken.startsWith("-") || lastToken.startsWith("--")) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Set<ObjectName> objectNames = queryObjectNames();
|
|
|
|
|
Set<String> names = new HashSet<String>();
|
|
|
|
|
|
|
|
|
|
if (objectNames == null) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
for (ObjectName objectName : objectNames) {
|
|
|
|
|
String name = objectName.toString();
|
|
|
|
|
if (name.startsWith(lastToken)) {
|
|
|
|
|
int index = name.indexOf('.', lastToken.length());
|
|
|
|
|
if (index > 0) {
|
|
|
|
|
names.add(name.substring(0, index + 1));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
index = name.indexOf(':', lastToken.length());
|
|
|
|
|
if (index > 0) {
|
|
|
|
|
names.add(name.substring(0, index + 1));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
names.add(name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
String next = names.iterator().next();
|
|
|
|
|
if (names.size() == 1 && (next.endsWith(".") || next.endsWith(":"))) {
|
|
|
|
|
completion.complete(next.substring(lastToken.length()), false);
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return CompletionUtils.complete(completion, names);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean completeAttributeName(Completion completion) {
|
|
|
|
|
List<CliToken> tokens = completion.lineTokens();
|
|
|
|
|
String lastToken = TokenUtils.getLast(tokens).value();
|
|
|
|
|
|
|
|
|
|
if (StringUtils.isBlank(lastToken)) {
|
|
|
|
|
lastToken = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
|
|
|
|
|
String beanName = TokenUtils.retrievePreviousArg(tokens, lastToken);
|
|
|
|
|
Set<ObjectName> objectNames = null;
|
|
|
|
|
try {
|
|
|
|
|
objectNames = platformMBeanServer.queryNames(new ObjectName(beanName), null);
|
|
|
|
|
} catch (MalformedObjectNameException e) {
|
|
|
|
|
logger.warn("queryNames error", e);
|
|
|
|
|
}
|
|
|
|
|
if (objectNames == null || objectNames.size() == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
MBeanInfo mBeanInfo = platformMBeanServer.getMBeanInfo(objectNames.iterator().next());
|
|
|
|
|
List<String> attributeNames = new ArrayList<String>();
|
|
|
|
|
MBeanAttributeInfo[] attributes = mBeanInfo.getAttributes();
|
|
|
|
|
for (MBeanAttributeInfo attribute : attributes) {
|
|
|
|
|
if (StringUtils.isBlank(lastToken)) {
|
|
|
|
|
attributeNames.add(attribute.getName());
|
|
|
|
|
} else if (attribute.getName().startsWith(lastToken)) {
|
|
|
|
|
attributeNames.add(attribute.getName());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return CompletionUtils.complete(completion, attributeNames);
|
|
|
|
|
} catch (Throwable e) {
|
|
|
|
|
logger.warn("getMBeanInfo error", e);
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Set<ObjectName> queryObjectNames() {
|
|
|
|
|
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
|
|
|
|
|
Set<ObjectName> objectNames = new HashSet<ObjectName>();
|
|
|
|
|
try {
|
|
|
|
|
if (StringUtils.isEmpty(name)) {
|
|
|
|
|
name = "*:*";
|
|
|
|
|
}
|
|
|
|
|
objectNames = platformMBeanServer.queryNames(new ObjectName(name), null);
|
|
|
|
|
} catch (MalformedObjectNameException e) {
|
|
|
|
|
logger.warn("queryObjectNames error", e);
|
|
|
|
|
}
|
|
|
|
|
return objectNames;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Matcher<String> getAttributeMatcher() {
|
|
|
|
|
if (StringUtils.isEmpty(attribute)) {
|
|
|
|
|
attribute = isRegEx ? ".*" : "*";
|
|
|
|
|
}
|
|
|
|
|
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 {
|
|
|
|
|
|
|
|
|
|
private volatile Timer timer;
|
|
|
|
|
|
|
|
|
|
public MBeanInterruptHandler(CommandProcess process, Timer timer) {
|
|
|
|
|
super(process);
|
|
|
|
|
this.timer = timer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void handle(Void event) {
|
|
|
|
|
timer.cancel();
|
|
|
|
|
super.handle(event);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class MBeanTimerTask extends TimerTask {
|
|
|
|
|
|
|
|
|
|
private CommandProcess process;
|
|
|
|
|
|
|
|
|
|
public MBeanTimerTask(CommandProcess process) {
|
|
|
|
|
this.process = process;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
if (count >= getNumOfExecutions()) {
|
|
|
|
|
// stop the timer
|
|
|
|
|
timer.cancel();
|
|
|
|
|
timer.purge();
|
|
|
|
|
process.write("Process ends after " + getNumOfExecutions() + " time(s).\n");
|
|
|
|
|
process.end();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
|
|
|
|
|
Set<ObjectName> objectNames = queryObjectNames();
|
|
|
|
|
TableElement table = createTable();
|
|
|
|
|
for (ObjectName objectName : objectNames) {
|
|
|
|
|
MBeanInfo mBeanInfo = platformMBeanServer.getMBeanInfo(objectName);
|
|
|
|
|
MBeanAttributeInfo[] attributes = mBeanInfo.getAttributes();
|
|
|
|
|
for (MBeanAttributeInfo attribute : attributes) {
|
|
|
|
|
String attributeName = attribute.getName();
|
|
|
|
|
if (!getAttributeMatcher().matching(attributeName)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
String value;
|
|
|
|
|
if (!attribute.isReadable()) {
|
|
|
|
|
value = RenderUtil.render(new LabelElement("Unavailable").style(Decoration.bold_off.fg(Color.red)));
|
|
|
|
|
} else {
|
|
|
|
|
Object attributeObj = platformMBeanServer.getAttribute(objectName, attributeName);
|
|
|
|
|
value = String.valueOf(attributeObj);
|
|
|
|
|
}
|
|
|
|
|
table.row(attributeName, value);
|
|
|
|
|
}
|
|
|
|
|
process.write(RenderUtil.render(table, process.width()));
|
|
|
|
|
process.write("\n");
|
|
|
|
|
}
|
|
|
|
|
} catch (Throwable e) {
|
|
|
|
|
logger.warn("mbean error", e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
count++;
|
|
|
|
|
process.times().incrementAndGet();
|
|
|
|
|
|
|
|
|
|
if (getInterval() <= 0) {
|
|
|
|
|
stop();
|
|
|
|
|
process.end();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|