From 353d8501f3b69c975b3b7fc931ebe5051ed218ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=BF=97=E6=AF=85?= Date: Sun, 28 Apr 2019 14:24:23 +0800 Subject: [PATCH] improve timetunnel command(#631) --- .../command/monitor200/TimeTunnelCommand.java | 62 ++++++++++--------- .../core/shell/command/CommandProcess.java | 13 ++-- .../core/shell/system/impl/ProcessImpl.java | 5 ++ 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelCommand.java index 16950d2ac..7ec3ef8d7 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelCommand.java @@ -20,6 +20,7 @@ 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.cli.annotations.Argument; +import com.taobao.middleware.logger.Logger; import com.taobao.text.ui.TableElement; import com.taobao.text.util.RenderUtil; @@ -78,6 +79,7 @@ public class TimeTunnelCommand extends EnhancerCommand { private int numberOfLimit = 100; private int replayTimes = 1; private long replayInterval = 1000L; + private static final Logger logger = LogUtil.getArthasLogger(); @Argument(index = 0, argName = "class-pattern", required = false) @Description("Path and classname of Pattern Matching") @@ -362,7 +364,7 @@ public class TimeTunnelCommand extends EnhancerCommand { affect.rCnt(1); } catch (ExpressException e) { - LogUtil.getArthasLogger().warn("tt failed.", e); + logger.warn("tt failed.", e); process.write(e.getMessage() + ", visit " + LogUtil.LOGGER_FILE + " for more detail\n"); } finally { process.write(affect.toString()).write("\n"); @@ -436,39 +438,40 @@ public class TimeTunnelCommand extends EnhancerCommand { process.end(); } - // 重放指定记录 + /** + * 重放指定记录 + */ private void processPlay(CommandProcess process) { - RowAffect affect = new RowAffect(); + TimeFragment tf = timeFragmentMap.get(index); + if (null == tf) { + process.write(format("Time fragment[%d] does not exist.", index) + "\n"); + process.end(); + return; + } + Advice advice = tf.getAdvice(); + String className = advice.getClazz().getName(); + String methodName = advice.getMethod().getName(); + String objectAddress = advice.getTarget() == null ? "NULL" : "0x" + toHexString(advice.getTarget().hashCode()); + ArthasMethod method = advice.getMethod(); + boolean accessible = advice.getMethod().isAccessible(); try { - TimeFragment tf = timeFragmentMap.get(index); - if (null == tf) { - process.write(format("Time fragment[%d] does not exist.", index) + "\n"); - process.write(affect + "\n"); - process.end(); - return; + if (!accessible) { + method.setAccessible(true); } - - Advice advice = tf.getAdvice(); - String className = advice.getClazz().getName(); - String methodName = advice.getMethod().getName(); - String objectAddress = advice.getTarget() == null ? "NULL" : "0x" + toHexString(advice.getTarget().hashCode()); - - - - ArthasMethod method = advice.getMethod(); - method.setAccessible(true); - boolean accessible = advice.getMethod().isAccessible(); for (int i = 0; i < getReplayTimes(); i++) { -// wait for the next execution if (i > 0) { - try { - Thread.sleep(getReplayInterval()); - } catch (InterruptedException e) { - e.printStackTrace(); + //wait for the next execution + Thread.sleep(getReplayInterval()); + if (!process.isRunning()) { + return; } } long beginTime = System.nanoTime(); TableElement table = TimeTunnelTable.createDefaultTable(); + if (i != 0) { + // empty line separator + process.write("\n"); + } TimeTunnelTable.drawPlayHeader(className, methodName, objectAddress, index, table); TimeTunnelTable.drawParameters(advice, table, isNeedExpand(), expand); @@ -480,14 +483,13 @@ public class TimeTunnelCommand extends EnhancerCommand { TimeTunnelTable.drawPlayException(table, t, isNeedExpand(), expand); } process.write(RenderUtil.render(table, process.width())) - .write(format("Time fragment[%d] successfully replayed.", index)) + .write(format("Time fragment[%d] successfully replayed %d times.", index, i+1)) .write("\n"); - affect.rCnt(1); - process.write(affect.toString()).write("\n"); } - method.setAccessible(accessible); - + } catch (Throwable t) { + logger.warn("tt replay failed.", t); } finally { + method.setAccessible(accessible); process.end(); } } diff --git a/core/src/main/java/com/taobao/arthas/core/shell/command/CommandProcess.java b/core/src/main/java/com/taobao/arthas/core/shell/command/CommandProcess.java index ad315592e..6f85ca0b4 100644 --- a/core/src/main/java/com/taobao/arthas/core/shell/command/CommandProcess.java +++ b/core/src/main/java/com/taobao/arthas/core/shell/command/CommandProcess.java @@ -121,9 +121,9 @@ public interface CommandProcess extends Tty { /** * Register listener - * + * * @param lock the lock for enhance class - * @param listener + * @param listener */ void register(int lock, AdviceListener listener); @@ -134,7 +134,7 @@ public interface CommandProcess extends Tty { /** * Execution times - * + * * @return execution times */ AtomicInteger times(); @@ -151,7 +151,7 @@ public interface CommandProcess extends Tty { /** * echo tips - * + * * @param tips process tips */ void echoTips(String tips); @@ -162,4 +162,9 @@ public interface CommandProcess extends Tty { * @return */ String cacheLocation(); + + /** + * Whether the process is running + */ + boolean isRunning(); } diff --git a/core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java b/core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java index 6134e1234..379aa6ee9 100644 --- a/core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java +++ b/core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java @@ -557,6 +557,11 @@ public class ProcessImpl implements Process { public void end(int statusCode) { terminate(statusCode, null); } + + @Override + public boolean isRunning() { + return processStatus == ExecStatus.RUNNING; + } } static class ProcessOutput {