Commit 5d7c4150 authored by shengnan hu's avatar shengnan hu
Browse files

init

parents
Pipeline #4720 failed with stage
in 31 seconds
package com.taobao.arthas.core.command.model;
import java.lang.management.ThreadInfo;
import java.util.List;
import java.util.Map;
/**
* Model of 'thread' command
*
* @author gongdewei 2020/4/26
*/
public class ThreadModel extends ResultModel {
//single thread: thread 12
private ThreadInfo threadInfo;
//thread -b
private BlockingLockInfo blockingLockInfo;
//thread -n 5
private List<BusyThreadInfo> busyThreads;
//thread stats
private List<ThreadVO> threadStats;
private Map<Thread.State, Integer> threadStateCount;
private boolean all;
public ThreadModel() {
}
public ThreadModel(ThreadInfo threadInfo) {
this.threadInfo = threadInfo;
}
public ThreadModel(BlockingLockInfo blockingLockInfo) {
this.blockingLockInfo = blockingLockInfo;
}
public ThreadModel(List<BusyThreadInfo> busyThreads) {
this.busyThreads = busyThreads;
}
public ThreadModel(List<ThreadVO> threadStats, Map<Thread.State, Integer> threadStateCount, boolean all) {
this.threadStats = threadStats;
this.threadStateCount = threadStateCount;
this.all = all;
}
@Override
public String getType() {
return "thread";
}
public ThreadInfo getThreadInfo() {
return threadInfo;
}
public void setThreadInfo(ThreadInfo threadInfo) {
this.threadInfo = threadInfo;
}
public BlockingLockInfo getBlockingLockInfo() {
return blockingLockInfo;
}
public void setBlockingLockInfo(BlockingLockInfo blockingLockInfo) {
this.blockingLockInfo = blockingLockInfo;
}
public List<BusyThreadInfo> getBusyThreads() {
return busyThreads;
}
public void setBusyThreads(List<BusyThreadInfo> busyThreads) {
this.busyThreads = busyThreads;
}
public List<ThreadVO> getThreadStats() {
return threadStats;
}
public void setThreadStats(List<ThreadVO> threadStats) {
this.threadStats = threadStats;
}
public Map<Thread.State, Integer> getThreadStateCount() {
return threadStateCount;
}
public void setThreadStateCount(Map<Thread.State, Integer> threadStateCount) {
this.threadStateCount = threadStateCount;
}
public boolean isAll() {
return all;
}
public void setAll(boolean all) {
this.all = all;
}
}
package com.taobao.arthas.core.command.model;
import java.util.Date;
/**
* Thread root node of TraceCommand
* @author gongdewei 2020/4/29
*/
public class ThreadNode extends TraceNode {
private String threadName;
private long threadId;
private boolean daemon;
private int priority;
private String classloader;
private Date timestamp;
private String traceId;
private String rpcId;
public ThreadNode() {
super("thread");
timestamp = new Date();
}
public ThreadNode(String threadName, long threadId, boolean daemon, int priority, String classloader) {
super("thread");
this.threadName = threadName;
this.threadId = threadId;
this.daemon = daemon;
this.priority = priority;
this.classloader = classloader;
timestamp = new Date();
}
public String getThreadName() {
return threadName;
}
public void setThreadName(String threadName) {
this.threadName = threadName;
}
public long getThreadId() {
return threadId;
}
public void setThreadId(long threadId) {
this.threadId = threadId;
}
public boolean isDaemon() {
return daemon;
}
public void setDaemon(boolean daemon) {
this.daemon = daemon;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public String getClassloader() {
return classloader;
}
public void setClassloader(String classloader) {
this.classloader = classloader;
}
public Date getTimestamp() {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public String getTraceId() {
return traceId;
}
public void setTraceId(String traceId) {
this.traceId = traceId;
}
public String getRpcId() {
return rpcId;
}
public void setRpcId(String rpcId) {
this.rpcId = rpcId;
}
}
package com.taobao.arthas.core.command.model;
import java.lang.Thread.State;
/**
* Thread VO of 'dashboard' and 'thread' command
*
* @author gongdewei 2020/4/22
*/
public class ThreadVO {
private long id;
private String name;
private String group;
private int priority;
private State state;
private double cpu;
private long deltaTime;
private long time;
private boolean interrupted;
private boolean daemon;
public ThreadVO() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public double getCpu() {
return cpu;
}
public void setCpu(double cpu) {
this.cpu = cpu;
}
public long getDeltaTime() {
return deltaTime;
}
public void setDeltaTime(long deltaTime) {
this.deltaTime = deltaTime;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public boolean isInterrupted() {
return interrupted;
}
public void setInterrupted(boolean interrupted) {
this.interrupted = interrupted;
}
public boolean isDaemon() {
return daemon;
}
public void setDaemon(boolean daemon) {
this.daemon = daemon;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ThreadVO threadVO = (ThreadVO) o;
if (id != threadVO.id) return false;
return name != null ? name.equals(threadVO.name) : threadVO.name == null;
}
@Override
public int hashCode() {
int result = (int) (id ^ (id >>> 32));
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
}
package com.taobao.arthas.core.command.model;
/**
* Throw exception info node of TraceCommand
* @author gongdewei 2020/7/21
*/
public class ThrowNode extends TraceNode {
private String exception;
private String message;
private int lineNumber;
public ThrowNode() {
super("throw");
}
public String getException() {
return exception;
}
public void setException(String exception) {
this.exception = exception;
}
public int getLineNumber() {
return lineNumber;
}
public void setLineNumber(int lineNumber) {
this.lineNumber = lineNumber;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
package com.taobao.arthas.core.command.model;
import java.util.Date;
/**
* VO for TimeFragment
* @author gongdewei 2020/4/27
*/
public class TimeFragmentVO {
private Integer index;
private Date timestamp;
private double cost;
private boolean isReturn;
private boolean isThrow;
private String object;
private String className;
private String methodName;
private ObjectVO[] params;
private ObjectVO returnObj;
private ObjectVO throwExp;
public TimeFragmentVO() {
}
public Integer getIndex() {
return index;
}
public TimeFragmentVO setIndex(Integer index) {
this.index = index;
return this;
}
public Date getTimestamp() {
return timestamp;
}
public TimeFragmentVO setTimestamp(Date timestamp) {
this.timestamp = timestamp;
return this;
}
public double getCost() {
return cost;
}
public TimeFragmentVO setCost(double cost) {
this.cost = cost;
return this;
}
public boolean isReturn() {
return isReturn;
}
public TimeFragmentVO setReturn(boolean aReturn) {
isReturn = aReturn;
return this;
}
public boolean isThrow() {
return isThrow;
}
public TimeFragmentVO setThrow(boolean aThrow) {
isThrow = aThrow;
return this;
}
public String getObject() {
return object;
}
public TimeFragmentVO setObject(String object) {
this.object = object;
return this;
}
public String getClassName() {
return className;
}
public TimeFragmentVO setClassName(String className) {
this.className = className;
return this;
}
public String getMethodName() {
return methodName;
}
public TimeFragmentVO setMethodName(String methodName) {
this.methodName = methodName;
return this;
}
public ObjectVO[] getParams() {
return params;
}
public TimeFragmentVO setParams(ObjectVO[] params) {
this.params = params;
return this;
}
public ObjectVO getReturnObj() {
return returnObj;
}
public TimeFragmentVO setReturnObj(ObjectVO returnObj) {
this.returnObj = returnObj;
return this;
}
public ObjectVO getThrowExp() {
return throwExp;
}
public TimeFragmentVO setThrowExp(ObjectVO throwExp) {
this.throwExp = throwExp;
return this;
}
}
package com.taobao.arthas.core.command.model;
import java.util.List;
import java.util.Map;
/**
* Data model of TimeTunnelCommand
* @author gongdewei 2020/4/27
*/
public class TimeTunnelModel extends ResultModel {
//查看列表
private List<TimeFragmentVO> timeFragmentList;
//是否为第一次输出(需要加表头)
private Boolean isFirst;
//查看单条记录
private TimeFragmentVO timeFragment;
//重放执行的结果
private TimeFragmentVO replayResult;
//重放执行的次数
private Integer replayNo;
private ObjectVO watchValue;
//search: tt -s {} -w {}
private Map<Integer, ObjectVO> watchResults;
private Integer expand;
private Integer sizeLimit;
@Override
public String getType() {
return "tt";
}
public List<TimeFragmentVO> getTimeFragmentList() {
return timeFragmentList;
}
public TimeTunnelModel setTimeFragmentList(List<TimeFragmentVO> timeFragmentList) {
this.timeFragmentList = timeFragmentList;
return this;
}
public TimeFragmentVO getTimeFragment() {
return timeFragment;
}
public TimeTunnelModel setTimeFragment(TimeFragmentVO timeFragment) {
this.timeFragment = timeFragment;
return this;
}
public Integer getExpand() {
return expand;
}
public TimeTunnelModel setExpand(Integer expand) {
this.expand = expand;
return this;
}
public Integer getSizeLimit() {
return sizeLimit;
}
public TimeTunnelModel setSizeLimit(Integer sizeLimit) {
this.sizeLimit = sizeLimit;
return this;
}
public ObjectVO getWatchValue() {
return watchValue;
}
public TimeTunnelModel setWatchValue(ObjectVO watchValue) {
this.watchValue = watchValue;
return this;
}
public Map<Integer, ObjectVO> getWatchResults() {
return watchResults;
}
public TimeTunnelModel setWatchResults(Map<Integer, ObjectVO> watchResults) {
this.watchResults = watchResults;
return this;
}
public TimeFragmentVO getReplayResult() {
return replayResult;
}
public TimeTunnelModel setReplayResult(TimeFragmentVO replayResult) {
this.replayResult = replayResult;
return this;
}
public Integer getReplayNo() {
return replayNo;
}
public TimeTunnelModel setReplayNo(Integer replayNo) {
this.replayNo = replayNo;
return this;
}
public Boolean getFirst() {
return isFirst;
}
public TimeTunnelModel setFirst(Boolean first) {
isFirst = first;
return this;
}
}
package com.taobao.arthas.core.command.model;
import java.util.List;
/**
* Tomcat info of 'dashboard' command
*
* @author gongdewei 2020/4/23
*/
public class TomcatInfoVO {
private List<ConnectorStats> connectorStats;
private List<ThreadPool> threadPools;
public TomcatInfoVO() {
}
public List<ConnectorStats> getConnectorStats() {
return connectorStats;
}
public void setConnectorStats(List<ConnectorStats> connectorStats) {
this.connectorStats = connectorStats;
}
public List<ThreadPool> getThreadPools() {
return threadPools;
}
public void setThreadPools(List<ThreadPool> threadPools) {
this.threadPools = threadPools;
}
public static class ConnectorStats {
private String name;
private double qps;
private double rt;
private double error;
private long received;
private long sent;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getQps() {
return qps;
}
public void setQps(double qps) {
this.qps = qps;
}
public double getRt() {
return rt;
}
public void setRt(double rt) {
this.rt = rt;
}
public double getError() {
return error;
}
public void setError(double error) {
this.error = error;
}
public long getReceived() {
return received;
}
public void setReceived(long received) {
this.received = received;
}
public long getSent() {
return sent;
}
public void setSent(long sent) {
this.sent = sent;
}
}
public static class ThreadPool {
private String name;
private long busy;
private long total;
public ThreadPool() {
}
public ThreadPool(String name, long busy, long total) {
this.name = name;
this.busy = busy;
this.total = total;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getBusy() {
return busy;
}
public void setBusy(long busy) {
this.busy = busy;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
}
}
package com.taobao.arthas.core.command.model;
/**
* Data model of TraceCommand
* @author gongdewei 2020/4/29
*/
public class TraceModel extends ResultModel {
private TraceNode root;
private int nodeCount;
public TraceModel() {
}
public TraceModel(TraceNode root, int nodeCount) {
this.root = root;
this.nodeCount = nodeCount;
}
@Override
public String getType() {
return "trace";
}
public TraceNode getRoot() {
return root;
}
public void setRoot(TraceNode root) {
this.root = root;
}
public int getNodeCount() {
return nodeCount;
}
public void setNodeCount(int nodeCount) {
this.nodeCount = nodeCount;
}
}
package com.taobao.arthas.core.command.model;
import java.util.ArrayList;
import java.util.List;
/**
* Abstract Node of TraceCommand
* @author gongdewei 2020/4/28
*/
public abstract class TraceNode {
protected TraceNode parent;
protected List<TraceNode> children;
/**
* node type: method,
*/
private String type;
/**
* 备注
*/
private String mark;
/**
* TODO marks数量的作用?是否可以去掉
*/
private int marks = 0;
public TraceNode(String type) {
this.type = type;
}
public void addChild(TraceNode child) {
if (children == null) {
children = new ArrayList<TraceNode>();
}
this.children.add(child);
child.setParent(this);
}
public void setMark(String mark) {
this.mark = mark;
marks++;
}
public String getMark() {
return mark;
}
public Integer marks() {
return marks;
}
public void begin() {
}
public void end() {
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public TraceNode parent() {
return parent;
}
public void setParent(TraceNode parent) {
this.parent = parent;
}
public List<TraceNode> getChildren() {
return children;
}
}
package com.taobao.arthas.core.command.model;
import com.taobao.arthas.core.util.StringUtils;
import java.util.List;
/**
* Tree model of TraceCommand
* @author gongdewei 2020/4/28
*/
public class TraceTree {
private TraceNode root;
private TraceNode current;
private int nodeCount = 0;
public TraceTree(ThreadNode root) {
this.root = root;
this.current = root;
}
/**
* Begin a new method call
* @param className className of method
* @param methodName method name of the call
* @param lineNumber line number of invoke point
* @param isInvoking Whether to invoke this method in other classes
*/
public void begin(String className, String methodName, int lineNumber, boolean isInvoking) {
TraceNode child = findChild(current, className, methodName, lineNumber);
if (child == null) {
child = new MethodNode(className, methodName, lineNumber, isInvoking);
current.addChild(child);
}
child.begin();
current = child;
nodeCount += 1;
}
private TraceNode findChild(TraceNode node, String className, String methodName, int lineNumber) {
List<TraceNode> childList = node.getChildren();
if (childList != null) {
//less memory than foreach/iterator
for (int i = 0; i < childList.size(); i++) {
TraceNode child = childList.get(i);
if (matchNode(child, className, methodName, lineNumber)) {
return child;
}
}
}
return null;
}
private boolean matchNode(TraceNode node, String className, String methodName, int lineNumber) {
if (node instanceof MethodNode) {
MethodNode methodNode = (MethodNode) node;
if (lineNumber != methodNode.getLineNumber()) return false;
if (className != null ? !className.equals(methodNode.getClassName()) : methodNode.getClassName() != null) return false;
return methodName != null ? methodName.equals(methodNode.getMethodName()) : methodNode.getMethodName() == null;
}
return false;
}
public void end() {
current.end();
if (current.parent() != null) {
//TODO 为什么会到达这里? 调用end次数比begin多?
current = current.parent();
}
}
public void end(Throwable throwable, int lineNumber) {
ThrowNode throwNode = new ThrowNode();
throwNode.setException(throwable.getClass().getName());
throwNode.setMessage(throwable.getMessage());
throwNode.setLineNumber(lineNumber);
current.addChild(throwNode);
this.end(true);
}
public void end(boolean isThrow) {
if (isThrow) {
current.setMark("throws Exception");
if (current instanceof MethodNode) {
MethodNode methodNode = (MethodNode) current;
methodNode.setThrow(true);
}
}
this.end();
}
/**
* 修整树结点
*/
public void trim() {
this.normalizeClassName(root);
}
/**
* 转换标准类名,放在trace结束后统一转换,减少重复操作
* @param node
*/
private void normalizeClassName(TraceNode node) {
if (node instanceof MethodNode) {
MethodNode methodNode = (MethodNode) node;
String nodeClassName = methodNode.getClassName();
String normalizeClassName = StringUtils.normalizeClassName(nodeClassName);
methodNode.setClassName(normalizeClassName);
}
List<TraceNode> children = node.getChildren();
if (children != null) {
//less memory fragment than foreach
for (int i = 0; i < children.size(); i++) {
TraceNode child = children.get(i);
normalizeClassName(child);
}
}
}
public TraceNode getRoot() {
return root;
}
public TraceNode current() {
return current;
}
public int getNodeCount() {
return nodeCount;
}
}
package com.taobao.arthas.core.command.model;
import com.sun.management.VMOption;
import java.util.List;
/**
* @author gongdewei 2020/4/15
*/
public class VMOptionModel extends ResultModel {
private List<VMOption> vmOptions;
private ChangeResultVO changeResult;
public VMOptionModel() {
}
public VMOptionModel(List<VMOption> vmOptions) {
this.vmOptions = vmOptions;
}
public VMOptionModel(ChangeResultVO changeResult) {
this.changeResult = changeResult;
}
@Override
public String getType() {
return "vmoption";
}
public List<VMOption> getVmOptions() {
return vmOptions;
}
public void setVmOptions(List<VMOption> vmOptions) {
this.vmOptions = vmOptions;
}
public ChangeResultVO getChangeResult() {
return changeResult;
}
public void setChangeResult(ChangeResultVO changeResult) {
this.changeResult = changeResult;
}
}
package com.taobao.arthas.core.command.model;
public class VersionModel extends ResultModel {
private String version;
@Override
public String getType() {
return "version";
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}
package com.taobao.arthas.core.command.model;
import java.util.Collection;
/**
*
* @author hengyunabc 2022-04-24
*
*/
public class VmToolModel extends ResultModel {
private ObjectVO value;
private Collection<ClassLoaderVO> matchedClassLoaders;
private String classLoaderClass;
@Override
public String getType() {
return "vmtool";
}
public ObjectVO getValue() {
return value;
}
public VmToolModel setValue(ObjectVO value) {
this.value = value;
return this;
}
public String getClassLoaderClass() {
return classLoaderClass;
}
public VmToolModel setClassLoaderClass(String classLoaderClass) {
this.classLoaderClass = classLoaderClass;
return this;
}
public Collection<ClassLoaderVO> getMatchedClassLoaders() {
return matchedClassLoaders;
}
public VmToolModel setMatchedClassLoaders(Collection<ClassLoaderVO> matchedClassLoaders) {
this.matchedClassLoaders = matchedClassLoaders;
return this;
}
}
package com.taobao.arthas.core.command.model;
import java.util.Date;
/**
* Watch command result model
*
* @author gongdewei 2020/03/26
*/
public class WatchModel extends ResultModel {
private Date ts;
private double cost;
private ObjectVO value;
private Integer sizeLimit;
private String className;
private String methodName;
private String accessPoint;
public WatchModel() {
}
@Override
public String getType() {
return "watch";
}
public Date getTs() {
return ts;
}
public void setTs(Date ts) {
this.ts = ts;
}
public double getCost() {
return cost;
}
public ObjectVO getValue() {
return value;
}
public void setCost(double cost) {
this.cost = cost;
}
public void setValue(ObjectVO value) {
this.value = value;
}
public void setSizeLimit(Integer sizeLimit) {
this.sizeLimit = sizeLimit;
}
public Integer getSizeLimit() {
return sizeLimit;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public String getAccessPoint() {
return accessPoint;
}
public void setAccessPoint(String accessPoint) {
this.accessPoint = accessPoint;
}
}
package com.taobao.arthas.core.command.model;
/**
* @author gongdewei 2020/4/20
*/
public class WelcomeModel extends ResultModel {
private String pid;
private String time;
private String version;
private String wiki;
private String tutorials;
private String mainClass;
public WelcomeModel() {
}
@Override
public String getType() {
return "welcome";
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getWiki() {
return wiki;
}
public void setWiki(String wiki) {
this.wiki = wiki;
}
public String getTutorials() {
return tutorials;
}
public void setTutorials(String tutorials) {
this.tutorials = tutorials;
}
public String getMainClass() {
return mainClass;
}
public void setMainClass(String mainClass) {
this.mainClass = mainClass;
}
}
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.Advice;
import com.taobao.arthas.core.advisor.AdviceListenerAdapter;
import com.taobao.arthas.core.advisor.ArthasMethod;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.LogUtil;
import com.taobao.arthas.core.util.ThreadLocalWatch;
/**
* @author ralf0131 2017-01-06 16:02.
*/
public class AbstractTraceAdviceListener extends AdviceListenerAdapter {
private static final Logger logger = LoggerFactory.getLogger(AbstractTraceAdviceListener.class);
protected final ThreadLocalWatch threadLocalWatch = new ThreadLocalWatch();
protected TraceCommand command;
protected CommandProcess process;
protected final ThreadLocal<TraceEntity> threadBoundEntity = new ThreadLocal<TraceEntity>();
/**
* Constructor
*/
public AbstractTraceAdviceListener(TraceCommand command, CommandProcess process) {
this.command = command;
this.process = process;
}
protected TraceEntity threadLocalTraceEntity(ClassLoader loader) {
TraceEntity traceEntity = threadBoundEntity.get();
if (traceEntity == null) {
traceEntity = new TraceEntity(loader);
threadBoundEntity.set(traceEntity);
}
return traceEntity;
}
@Override
public void destroy() {
threadBoundEntity.remove();
}
@Override
public void before(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args)
throws Throwable {
TraceEntity traceEntity = threadLocalTraceEntity(loader);
traceEntity.tree.begin(clazz.getName(), method.getName(), -1, false);
traceEntity.deep++;
// 开始计算本次方法调用耗时
threadLocalWatch.start();
}
@Override
public void afterReturning(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args,
Object returnObject) throws Throwable {
threadLocalTraceEntity(loader).tree.end();
final Advice advice = Advice.newForAfterReturning(loader, clazz, method, target, args, returnObject);
finishing(loader, advice);
}
@Override
public void afterThrowing(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args,
Throwable throwable) throws Throwable {
int lineNumber = -1;
StackTraceElement[] stackTrace = throwable.getStackTrace();
if (stackTrace.length != 0) {
lineNumber = stackTrace[0].getLineNumber();
}
threadLocalTraceEntity(loader).tree.end(throwable, lineNumber);
final Advice advice = Advice.newForAfterThrowing(loader, clazz, method, target, args, throwable);
finishing(loader, advice);
}
public TraceCommand getCommand() {
return command;
}
private void finishing(ClassLoader loader, Advice advice) {
// 本次调用的耗时
TraceEntity traceEntity = threadLocalTraceEntity(loader);
if (traceEntity.deep >= 1) { // #1817 防止deep为负数
traceEntity.deep--;
}
if (traceEntity.deep == 0) {
double cost = threadLocalWatch.costInMillis();
try {
boolean conditionResult = isConditionMet(command.getConditionExpress(), advice, cost);
if (this.isVerbose()) {
process.write("Condition express: " + command.getConditionExpress() + " , result: " + conditionResult + "\n");
}
if (conditionResult) {
// 满足输出条件
process.times().incrementAndGet();
// TODO: concurrency issues for process.write
process.appendResult(traceEntity.getModel());
// 是否到达数量限制
if (isLimitExceeded(command.getNumberOfLimit(), process.times().get())) {
// TODO: concurrency issue to abort process
abortProcess(process, command.getNumberOfLimit());
}
}
} catch (Throwable e) {
logger.warn("trace failed.", e);
process.end(1, "trace failed, condition is: " + command.getConditionExpress() + ", " + e.getMessage()
+ ", visit " + LogUtil.loggingFile() + " for more details.");
} finally {
threadBoundEntity.remove();
}
}
}
}
package com.taobao.arthas.core.command.monitor200;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicLong;
import com.alibaba.arthas.deps.org.slf4j.Logger;
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.taobao.arthas.core.command.Constants;
import com.taobao.arthas.core.command.model.DashboardModel;
import com.taobao.arthas.core.command.model.GcInfoVO;
import com.taobao.arthas.core.command.model.RuntimeInfoVO;
import com.taobao.arthas.core.command.model.ThreadVO;
import com.taobao.arthas.core.command.model.TomcatInfoVO;
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.shell.QExitHandler;
import com.taobao.arthas.core.shell.session.Session;
import com.taobao.arthas.core.util.NetUtils;
import com.taobao.arthas.core.util.NetUtils.Response;
import com.taobao.arthas.core.util.StringUtils;
import com.taobao.arthas.core.util.ThreadUtil;
import com.taobao.arthas.core.util.metrics.SumRateCounter;
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;
/**
* @author hengyunabc 2015年11月19日 上午11:57:21
*/
@Name("dashboard")
@Summary("Overview of target jvm's thread, memory, gc, vm, tomcat info.")
@Description(Constants.EXAMPLE +
" dashboard\n" +
" dashboard -n 10\n" +
" dashboard -i 2000\n" +
Constants.WIKI + Constants.WIKI_HOME + "dashboard")
public class DashboardCommand extends AnnotatedCommand {
private static final Logger logger = LoggerFactory.getLogger(DashboardCommand.class);
private SumRateCounter tomcatRequestCounter = new SumRateCounter();
private SumRateCounter tomcatErrorCounter = new SumRateCounter();
private SumRateCounter tomcatReceivedBytesCounter = new SumRateCounter();
private SumRateCounter tomcatSentBytesCounter = new SumRateCounter();
private int numOfExecutions = Integer.MAX_VALUE;
private long interval = 5000;
private final AtomicLong count = new AtomicLong(0);
private volatile Timer timer;
@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;
}
@Option(shortName = "i", longName = "interval")
@Description("The interval (in ms) between two executions, default is 5000 ms.")
public void setInterval(long interval) {
this.interval = interval;
}
@Override
public void process(final CommandProcess process) {
Session session = process.session();
timer = new Timer("Timer-for-arthas-dashboard-" + session.getSessionId(), true);
// ctrl-C support
process.interruptHandler(new DashboardInterruptHandler(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
timer.scheduleAtFixedRate(new DashboardTimerTask(process), 0, getInterval());
}
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-dashboard-" + session.getSessionId(), true);
timer.scheduleAtFixedRate(new DashboardTimerTask(process), 0, getInterval());
}
}
public int getNumOfExecutions() {
return numOfExecutions;
}
public long getInterval() {
return interval;
}
private static void addRuntimeInfo(DashboardModel dashboardModel) {
RuntimeInfoVO runtimeInfo = new RuntimeInfoVO();
runtimeInfo.setOsName(System.getProperty("os.name"));
runtimeInfo.setOsVersion(System.getProperty("os.version"));
runtimeInfo.setJavaVersion(System.getProperty("java.version"));
runtimeInfo.setJavaHome(System.getProperty("java.home"));
runtimeInfo.setSystemLoadAverage(ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage());
runtimeInfo.setProcessors(Runtime.getRuntime().availableProcessors());
runtimeInfo.setUptime(ManagementFactory.getRuntimeMXBean().getUptime() / 1000);
runtimeInfo.setTimestamp(System.currentTimeMillis());
dashboardModel.setRuntimeInfo(runtimeInfo);
}
private static void addGcInfo(DashboardModel dashboardModel) {
List<GcInfoVO> gcInfos = new ArrayList<GcInfoVO>();
dashboardModel.setGcInfos(gcInfos);
List<GarbageCollectorMXBean> garbageCollectorMxBeans = ManagementFactory.getGarbageCollectorMXBeans();
for (GarbageCollectorMXBean gcMXBean : garbageCollectorMxBeans) {
String name = gcMXBean.getName();
gcInfos.add(new GcInfoVO(StringUtils.beautifyName(name), gcMXBean.getCollectionCount(), gcMXBean.getCollectionTime()));
}
}
private void addTomcatInfo(DashboardModel dashboardModel) {
// 如果请求tomcat信息失败,则不显示tomcat信息
if (!NetUtils.request("http://localhost:8006").isSuccess()) {
return;
}
TomcatInfoVO tomcatInfoVO = new TomcatInfoVO();
dashboardModel.setTomcatInfo(tomcatInfoVO);
String threadPoolPath = "http://localhost:8006/connector/threadpool";
String connectorStatPath = "http://localhost:8006/connector/stats";
Response connectorStatResponse = NetUtils.request(connectorStatPath);
if (connectorStatResponse.isSuccess()) {
List<TomcatInfoVO.ConnectorStats> connectorStats = new ArrayList<TomcatInfoVO.ConnectorStats>();
List<JSONObject> tomcatConnectorStats = JSON.parseArray(connectorStatResponse.getContent(), JSONObject.class);
for (JSONObject stat : tomcatConnectorStats) {
String connectorName = stat.getString("name").replace("\"", "");
long bytesReceived = stat.getLongValue("bytesReceived");
long bytesSent = stat.getLongValue("bytesSent");
long processingTime = stat.getLongValue("processingTime");
long requestCount = stat.getLongValue("requestCount");
long errorCount = stat.getLongValue("errorCount");
tomcatRequestCounter.update(requestCount);
tomcatErrorCounter.update(errorCount);
tomcatReceivedBytesCounter.update(bytesReceived);
tomcatSentBytesCounter.update(bytesSent);
double qps = tomcatRequestCounter.rate();
double rt = processingTime / (double) requestCount;
double errorRate = tomcatErrorCounter.rate();
long receivedBytesRate = Double.valueOf(tomcatReceivedBytesCounter.rate()).longValue();
long sentBytesRate = Double.valueOf(tomcatSentBytesCounter.rate()).longValue();
TomcatInfoVO.ConnectorStats connectorStat = new TomcatInfoVO.ConnectorStats();
connectorStat.setName(connectorName);
connectorStat.setQps(qps);
connectorStat.setRt(rt);
connectorStat.setError(errorRate);
connectorStat.setReceived(receivedBytesRate);
connectorStat.setSent(sentBytesRate);
connectorStats.add(connectorStat);
}
tomcatInfoVO.setConnectorStats(connectorStats);
}
Response threadPoolResponse = NetUtils.request(threadPoolPath);
if (threadPoolResponse.isSuccess()) {
List<TomcatInfoVO.ThreadPool> threadPools = new ArrayList<TomcatInfoVO.ThreadPool>();
List<JSONObject> threadPoolInfos = JSON.parseArray(threadPoolResponse.getContent(), JSONObject.class);
for (JSONObject info : threadPoolInfos) {
String name = info.getString("name").replace("\"", "");
long busy = info.getLongValue("threadBusy");
long total = info.getLongValue("threadCount");
threadPools.add(new TomcatInfoVO.ThreadPool(name, busy, total));
}
tomcatInfoVO.setThreadPools(threadPools);
}
}
private class DashboardTimerTask extends TimerTask {
private CommandProcess process;
private ThreadSampler threadSampler;
public DashboardTimerTask(CommandProcess process) {
this.process = process;
this.threadSampler = new ThreadSampler();
}
@Override
public void run() {
try {
if (count.get() >= getNumOfExecutions()) {
// stop the timer
timer.cancel();
timer.purge();
process.end(0, "Process ends after " + getNumOfExecutions() + " time(s).");
return;
}
DashboardModel dashboardModel = new DashboardModel();
//thread sample
List<ThreadVO> threads = ThreadUtil.getThreads();
dashboardModel.setThreads(threadSampler.sample(threads));
//memory
dashboardModel.setMemoryInfo(MemoryCommand.memoryInfo());
//gc
addGcInfo(dashboardModel);
//runtime
addRuntimeInfo(dashboardModel);
//tomcat
try {
addTomcatInfo(dashboardModel);
} catch (Throwable e) {
logger.error("try to read tomcat info error", e);
}
process.appendResult(dashboardModel);
count.getAndIncrement();
process.times().incrementAndGet();
} catch (Throwable e) {
String msg = "process dashboard failed: " + e.getMessage();
logger.error(msg, e);
process.end(-1, msg);
}
}
}
}
package com.taobao.arthas.core.command.monitor200;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.shell.handlers.command.CommandInterruptHandler;
import java.util.Timer;
/**
* @author ralf0131 2017-01-09 13:37.
*/
public class DashboardInterruptHandler extends CommandInterruptHandler {
private volatile Timer timer;
public DashboardInterruptHandler(CommandProcess process, Timer timer) {
super(process);
this.timer = timer;
}
@Override
public void handle(Void event) {
timer.cancel();
super.handle(event);
}
}
package com.taobao.arthas.core.command.monitor200;
import java.lang.instrument.Instrumentation;
import java.util.Collections;
import java.util.List;
import com.alibaba.arthas.deps.org.slf4j.Logger;
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
import com.taobao.arthas.core.advisor.AdviceListener;
import com.taobao.arthas.core.advisor.AdviceWeaver;
import com.taobao.arthas.core.advisor.Enhancer;
import com.taobao.arthas.core.advisor.InvokeTraceable;
import com.taobao.arthas.core.command.model.EnhancerModel;
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.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.Constants;
import com.taobao.arthas.core.util.LogUtil;
import com.taobao.arthas.core.util.affect.EnhancerAffect;
import com.taobao.arthas.core.util.matcher.Matcher;
import com.taobao.arthas.core.view.Ansi;
import com.taobao.middleware.cli.annotations.Description;
import com.taobao.middleware.cli.annotations.Option;
/**
* @author beiwei30 on 29/11/2016.
*/
public abstract class EnhancerCommand extends AnnotatedCommand {
private static final Logger logger = LoggerFactory.getLogger(EnhancerCommand.class);
protected static final List<String> EMPTY = Collections.emptyList();
public static final String[] EXPRESS_EXAMPLES = { "params", "returnObj", "throwExp", "target", "clazz", "method",
"{params,returnObj}", "params[0]" };
private String excludeClassPattern;
protected Matcher classNameMatcher;
protected Matcher classNameExcludeMatcher;
protected Matcher methodNameMatcher;
protected long listenerId;
protected boolean verbose;
@Option(longName = "exclude-class-pattern")
@Description("exclude class name pattern, use either '.' or '/' as separator")
public void setExcludeClassPattern(String excludeClassPattern) {
this.excludeClassPattern = excludeClassPattern;
}
@Option(longName = "listenerId")
@Description("The special listenerId")
public void setListenerId(long listenerId) {
this.listenerId = listenerId;
}
@Option(shortName = "v", longName = "verbose", flag = true)
@Description("Enables print verbose information, default value false.")
public void setVerbosee(boolean verbose) {
this.verbose = verbose;
}
/**
* 类名匹配
*
* @return 获取类名匹配
*/
protected abstract Matcher getClassNameMatcher();
/**
* 排除类名匹配
*/
protected abstract Matcher getClassNameExcludeMatcher();
/**
* 方法名匹配
*
* @return 获取方法名匹配
*/
protected abstract Matcher getMethodNameMatcher();
/**
* 获取监听器
*
* @return 返回监听器
*/
protected abstract AdviceListener getAdviceListener(CommandProcess process);
AdviceListener getAdviceListenerWithId(CommandProcess process) {
if (listenerId != 0) {
AdviceListener listener = AdviceWeaver.listener(listenerId);
if (listener != null) {
return listener;
}
}
return getAdviceListener(process);
}
@Override
public void process(final CommandProcess process) {
// ctrl-C support
process.interruptHandler(new CommandInterruptHandler(process));
// q exit support
process.stdinHandler(new QExitHandler(process));
// start to enhance
enhance(process);
}
@Override
public void complete(Completion completion) {
int argumentIndex = CompletionUtils.detectArgumentIndex(completion);
if (argumentIndex == 1) { // class name
if (!CompletionUtils.completeClassName(completion)) {
super.complete(completion);
}
return;
} else if (argumentIndex == 2) { // method name
if (!CompletionUtils.completeMethodName(completion)) {
super.complete(completion);
}
return;
} else if (argumentIndex == 3) { // watch express
completeArgument3(completion);
return;
}
super.complete(completion);
}
protected void enhance(CommandProcess process) {
Session session = process.session();
if (!session.tryLock()) {
String msg = "someone else is enhancing classes, pls. wait.";
process.appendResult(new EnhancerModel(null, false, msg));
process.end(-1, msg);
return;
}
EnhancerAffect effect = null;
int lock = session.getLock();
try {
Instrumentation inst = session.getInstrumentation();
AdviceListener listener = getAdviceListenerWithId(process);
if (listener == null) {
logger.error("advice listener is null");
String msg = "advice listener is null, check arthas log";
process.appendResult(new EnhancerModel(effect, false, msg));
process.end(-1, msg);
return;
}
boolean skipJDKTrace = false;
if(listener instanceof AbstractTraceAdviceListener) {
skipJDKTrace = ((AbstractTraceAdviceListener) listener).getCommand().isSkipJDKTrace();
}
Enhancer enhancer = new Enhancer(listener, listener instanceof InvokeTraceable, skipJDKTrace, getClassNameMatcher(), getClassNameExcludeMatcher(), getMethodNameMatcher());
// 注册通知监听器
process.register(listener, enhancer);
effect = enhancer.enhance(inst);
if (effect.getThrowable() != null) {
String msg = "error happens when enhancing class: "+effect.getThrowable().getMessage();
process.appendResult(new EnhancerModel(effect, false, msg));
process.end(1, msg + ", check arthas log: " + LogUtil.loggingFile());
return;
}
if (effect.cCnt() == 0 || effect.mCnt() == 0) {
// no class effected
// might be method code too large
process.appendResult(new EnhancerModel(effect, false, "No class or method is affected"));
String smCommand = Ansi.ansi().fg(Ansi.Color.GREEN).a("sm CLASS_NAME METHOD_NAME").reset().toString();
String optionsCommand = Ansi.ansi().fg(Ansi.Color.GREEN).a("options unsafe true").reset().toString();
String javaPackage = Ansi.ansi().fg(Ansi.Color.GREEN).a("java.*").reset().toString();
String resetCommand = Ansi.ansi().fg(Ansi.Color.GREEN).a("reset CLASS_NAME").reset().toString();
String logStr = Ansi.ansi().fg(Ansi.Color.GREEN).a(LogUtil.loggingFile()).reset().toString();
String issueStr = Ansi.ansi().fg(Ansi.Color.GREEN).a("https://github.com/alibaba/arthas/issues/47").reset().toString();
String msg = "No class or method is affected, try:\n"
+ "1. Execute `" + smCommand + "` to make sure the method you are tracing actually exists (it might be in your parent class).\n"
+ "2. Execute `" + optionsCommand + "`, if you want to enhance the classes under the `" + javaPackage + "` package.\n"
+ "3. Execute `" + resetCommand + "` and try again, your method body might be too large.\n"
+ "4. Match the constructor, use `<init>`, for example: `watch demo.MathGame <init>`\n"
+ "5. Check arthas log: " + logStr + "\n"
+ "6. Visit " + issueStr + " for more details.";
process.end(-1, msg);
return;
}
// 这里做个补偿,如果在enhance期间,unLock被调用了,则补偿性放弃
if (session.getLock() == lock) {
if (process.isForeground()) {
process.echoTips(Constants.Q_OR_CTRL_C_ABORT_MSG + "\n");
}
}
process.appendResult(new EnhancerModel(effect, true));
//异步执行,在AdviceListener中结束
} catch (Throwable e) {
String msg = "error happens when enhancing class: "+e.getMessage();
logger.error(msg, e);
process.appendResult(new EnhancerModel(effect, false, msg));
process.end(-1, msg);
} finally {
if (session.getLock() == lock) {
// enhance结束后解锁
process.session().unLock();
}
}
}
protected void completeArgument3(Completion completion) {
super.complete(completion);
}
public String getExcludeClassPattern() {
return excludeClassPattern;
}
}
package com.taobao.arthas.core.command.monitor200;
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.ScriptSupportCommand;
import com.taobao.arthas.core.shell.command.CommandProcess;
/**
* Groovy support has been completed dropped in Arthas 3.0 because of severer memory leak.
* @author beiwei30 on 01/12/2016.
*/
@Deprecated
public class GroovyAdviceListener extends AdviceListenerAdapter {
private ScriptSupportCommand.ScriptListener scriptListener;
private ScriptSupportCommand.Output output;
public GroovyAdviceListener(ScriptSupportCommand.ScriptListener scriptListener, CommandProcess process) {
this.scriptListener = scriptListener;
this.output = new CommandProcessAdaptor(process);
}
@Override
public void create() {
scriptListener.create(output);
}
@Override
public void destroy() {
scriptListener.destroy(output);
}
@Override
public void before(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args)
throws Throwable {
scriptListener.before(output, 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 {
scriptListener.afterReturning(output, Advice.newForAfterReturning(loader, clazz, method, target, args, returnObject));
}
@Override
public void afterThrowing(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args,
Throwable throwable) throws Throwable {
scriptListener.afterThrowing(output, Advice.newForAfterThrowing(loader, clazz, method, target, args, throwable));
}
private static class CommandProcessAdaptor implements ScriptSupportCommand.Output {
private CommandProcess process;
public CommandProcessAdaptor(CommandProcess process) {
this.process = process;
}
@Override
public ScriptSupportCommand.Output print(String string) {
process.write(string);
return this;
}
@Override
public ScriptSupportCommand.Output println(String string) {
process.write(string).write("\n");
return this;
}
@Override
public ScriptSupportCommand.Output finish() {
process.end();
return this;
}
}
}
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