mirror of
https://gitee.com/arthas/arthas.git
synced 2024-12-02 12:17:45 +08:00
support trace/watch with exist listenerId. #1207
This commit is contained in:
parent
b7414f899d
commit
4a673a79e3
@ -6,6 +6,8 @@ package com.taobao.arthas.core.advisor;
|
||||
*/
|
||||
public interface AdviceListener {
|
||||
|
||||
long id();
|
||||
|
||||
/**
|
||||
* 监听器创建<br/>
|
||||
* 监听器被注册时触发
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.taobao.arthas.core.advisor;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import com.taobao.arthas.core.command.express.ExpressException;
|
||||
import com.taobao.arthas.core.command.express.ExpressFactory;
|
||||
import com.taobao.arthas.core.shell.command.CommandProcess;
|
||||
@ -14,7 +16,14 @@ import com.taobao.arthas.core.util.StringUtils;
|
||||
*
|
||||
*/
|
||||
public abstract class AdviceListenerAdapter implements AdviceListener, ProcessAware {
|
||||
private static final AtomicLong ID_GENERATOR = new AtomicLong(0);
|
||||
private Process process;
|
||||
private long id = ID_GENERATOR.addAndGet(1);
|
||||
|
||||
@Override
|
||||
public long id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create() {
|
||||
|
@ -19,8 +19,8 @@ public class AdviceWeaver {
|
||||
private static final Logger logger = LoggerFactory.getLogger(AdviceWeaver.class);
|
||||
|
||||
// 通知监听器集合
|
||||
private final static Map<Integer/*ADVICE_ID*/, AdviceListener> advices
|
||||
= new ConcurrentHashMap<Integer, AdviceListener>();
|
||||
private final static Map<Long/*ADVICE_ID*/, AdviceListener> advices
|
||||
= new ConcurrentHashMap<Long, AdviceListener>();
|
||||
|
||||
/**
|
||||
* 注册监听器
|
||||
@ -28,13 +28,13 @@ public class AdviceWeaver {
|
||||
* @param adviceId 通知ID
|
||||
* @param listener 通知监听器
|
||||
*/
|
||||
public static void reg(int adviceId, AdviceListener listener) {
|
||||
public static void reg(AdviceListener listener) {
|
||||
|
||||
// 触发监听器创建
|
||||
listener.create();
|
||||
|
||||
// 注册监听器
|
||||
advices.put(adviceId, listener);
|
||||
advices.put(listener.id(), listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -42,28 +42,28 @@ public class AdviceWeaver {
|
||||
*
|
||||
* @param adviceId 通知ID
|
||||
*/
|
||||
public static void unReg(int adviceId) {
|
||||
|
||||
// 注销监听器
|
||||
final AdviceListener listener = advices.remove(adviceId);
|
||||
|
||||
// 触发监听器销毁
|
||||
public static void unReg(AdviceListener listener) {
|
||||
if (null != listener) {
|
||||
// 注销监听器
|
||||
advices.remove(listener.id());
|
||||
|
||||
// 触发监听器销毁
|
||||
listener.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static AdviceListener listener(long id) {
|
||||
return advices.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复监听
|
||||
*
|
||||
* @param adviceId 通知ID
|
||||
* @param listener 通知监听器
|
||||
*/
|
||||
public static void resume(int adviceId, AdviceListener listener) {
|
||||
public static void resume(AdviceListener listener) {
|
||||
// 注册监听器
|
||||
advices.put(adviceId, listener);
|
||||
advices.put(listener.id(), listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,7 +71,7 @@ public class AdviceWeaver {
|
||||
*
|
||||
* @param adviceId 通知ID
|
||||
*/
|
||||
public static AdviceListener suspend(int adviceId) {
|
||||
public static AdviceListener suspend(long adviceId) {
|
||||
// 注销监听器
|
||||
return advices.remove(adviceId);
|
||||
}
|
||||
|
@ -94,7 +94,8 @@ public class Enhancer implements ClassFileTransformer {
|
||||
this.skipJDKTrace = skipJDKTrace;
|
||||
this.classNameMatcher = classNameMatcher;
|
||||
this.methodNameMatcher = methodNameMatcher;
|
||||
this.affect = new EnhancerAffect();;
|
||||
this.affect = new EnhancerAffect();
|
||||
affect.setListenerId(listener.id());
|
||||
}
|
||||
|
||||
public static class SpyInterceptor {
|
||||
|
@ -8,6 +8,7 @@ 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.shell.cli.Completion;
|
||||
@ -21,6 +22,8 @@ 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.middleware.cli.annotations.Description;
|
||||
import com.taobao.middleware.cli.annotations.Option;
|
||||
|
||||
/**
|
||||
* @author beiwei30 on 29/11/2016.
|
||||
@ -35,6 +38,14 @@ public abstract class EnhancerCommand extends AnnotatedCommand {
|
||||
protected Matcher classNameMatcher;
|
||||
protected Matcher methodNameMatcher;
|
||||
|
||||
protected long listenerId;
|
||||
|
||||
@Option(longName = "listenerId")
|
||||
@Description("The special listenerId")
|
||||
public void setListenerId(long listenerId) {
|
||||
this.listenerId = listenerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 类名匹配
|
||||
*
|
||||
@ -56,6 +67,15 @@ public abstract class EnhancerCommand extends AnnotatedCommand {
|
||||
*/
|
||||
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
|
||||
@ -99,7 +119,7 @@ public abstract class EnhancerCommand extends AnnotatedCommand {
|
||||
int lock = session.getLock();
|
||||
try {
|
||||
Instrumentation inst = session.getInstrumentation();
|
||||
AdviceListener listener = getAdviceListener(process);
|
||||
AdviceListener listener = getAdviceListenerWithId(process);
|
||||
if (listener == null) {
|
||||
warn(process, "advice listener is null");
|
||||
return;
|
||||
@ -111,7 +131,7 @@ public abstract class EnhancerCommand extends AnnotatedCommand {
|
||||
|
||||
Enhancer enhancer = new Enhancer(listener, listener instanceof InvokeTraceable, skipJDKTrace, getClassNameMatcher(), getMethodNameMatcher());
|
||||
// 注册通知监听器
|
||||
process.register(lock, listener, enhancer);
|
||||
process.register(listener, enhancer);
|
||||
EnhancerAffect effect = enhancer.enhance(inst);
|
||||
|
||||
if (effect.cCnt() == 0 || effect.mCnt() == 0) {
|
||||
|
@ -42,7 +42,7 @@ public class WatchCommand extends EnhancerCommand {
|
||||
private Integer sizeLimit = 10 * 1024 * 1024;
|
||||
private boolean isRegEx = false;
|
||||
private int numberOfLimit = 100;
|
||||
|
||||
|
||||
@Argument(index = 0, argName = "class-pattern")
|
||||
@Description("The full qualified class name you want to watch")
|
||||
public void setClassPattern(String classPattern) {
|
||||
|
@ -123,10 +123,9 @@ public interface CommandProcess extends Tty {
|
||||
/**
|
||||
* Register listener
|
||||
*
|
||||
* @param lock the lock for enhance class
|
||||
* @param listener
|
||||
*/
|
||||
void register(int lock, AdviceListener listener, ClassFileTransformer transformer);
|
||||
void register(AdviceListener listener, ClassFileTransformer transformer);
|
||||
|
||||
/**
|
||||
* Unregister listener
|
||||
|
@ -384,9 +384,8 @@ public class ProcessImpl implements Process {
|
||||
private final List<String> args2;
|
||||
private final Tty tty;
|
||||
private final CommandLine commandLine;
|
||||
private int enhanceLock = -1;
|
||||
private AtomicInteger times = new AtomicInteger();
|
||||
private AdviceListener suspendedListener = null;
|
||||
private AdviceListener listener = null;
|
||||
private ClassFileTransformer transformer;
|
||||
|
||||
public CommandProcessImpl(Process process, List<String> args2, Tty tty, CommandLine commandLine) {
|
||||
@ -528,13 +527,15 @@ public class ProcessImpl implements Process {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(int enhanceLock, AdviceListener listener, ClassFileTransformer transformer) {
|
||||
this.enhanceLock = enhanceLock;
|
||||
|
||||
public void register(AdviceListener listener, ClassFileTransformer transformer) {
|
||||
if (listener instanceof ProcessAware) {
|
||||
((ProcessAware) listener).setProcess(this.process);
|
||||
ProcessAware processAware = (ProcessAware) listener;
|
||||
// listener 有可能是其它 command 创建的
|
||||
if(processAware.getProcess() == null) {
|
||||
processAware.setProcess(this.process);
|
||||
}
|
||||
}
|
||||
AdviceWeaver.reg(enhanceLock, listener);
|
||||
AdviceWeaver.reg(listener);
|
||||
|
||||
this.transformer = transformer;
|
||||
}
|
||||
@ -545,22 +546,29 @@ public class ProcessImpl implements Process {
|
||||
ArthasBootstrap.getInstance().getTransformerManager().removeTransformer(transformer);
|
||||
}
|
||||
|
||||
AdviceWeaver.unReg(enhanceLock);
|
||||
if (listener instanceof ProcessAware) {
|
||||
// listener有可能其它 command 创建的,所以不能unRge
|
||||
if (this.process.equals(((ProcessAware) listener).getProcess())) {
|
||||
AdviceWeaver.unReg(listener);
|
||||
}
|
||||
} else {
|
||||
AdviceWeaver.unReg(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resume() {
|
||||
if (this.enhanceLock >= 0 && suspendedListener != null) {
|
||||
AdviceWeaver.resume(enhanceLock, suspendedListener);
|
||||
suspendedListener = null;
|
||||
}
|
||||
// if (suspendedListener != null) {
|
||||
// AdviceWeaver.resume(suspendedListener);
|
||||
// suspendedListener = null;
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suspend() {
|
||||
if (this.enhanceLock >= 0) {
|
||||
suspendedListener = AdviceWeaver.suspend(enhanceLock);
|
||||
}
|
||||
// if (this.enhanceLock >= 0) {
|
||||
// suspendedListener = AdviceWeaver.suspend(enhanceLock);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -22,6 +22,7 @@ public final class EnhancerAffect extends Affect {
|
||||
private final AtomicInteger cCnt = new AtomicInteger();
|
||||
private final AtomicInteger mCnt = new AtomicInteger();
|
||||
private ClassFileTransformer transformer;
|
||||
private long listenerId;
|
||||
/**
|
||||
* dumpClass的文件存放集合
|
||||
*/
|
||||
@ -92,6 +93,14 @@ public final class EnhancerAffect extends Affect {
|
||||
this.transformer = transformer;
|
||||
}
|
||||
|
||||
public long getListenerId() {
|
||||
return listenerId;
|
||||
}
|
||||
|
||||
public void setListenerId(long listenerId) {
|
||||
this.listenerId = listenerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder infoSB = new StringBuilder();
|
||||
@ -108,10 +117,11 @@ public final class EnhancerAffect extends Affect {
|
||||
infoSB.append("[Affect method: ").append(method).append("]\n");
|
||||
}
|
||||
}
|
||||
infoSB.append(format("Affect(class count:%d , method count:%d) cost in %s ms.",
|
||||
infoSB.append(format("Affect(class count: %d , method count: %d) cost in %s ms, listenerId: %d",
|
||||
cCnt(),
|
||||
mCnt(),
|
||||
cost()));
|
||||
cost(),
|
||||
listenerId));
|
||||
return infoSB.toString();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user