diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorAdviceListener.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorAdviceListener.java index bbcc7c6d..0b661356 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorAdviceListener.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorAdviceListener.java @@ -1,9 +1,14 @@ 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.command.express.ExpressException; import com.taobao.arthas.core.command.model.MonitorModel; import com.taobao.arthas.core.shell.command.CommandProcess; import com.taobao.arthas.core.advisor.ArthasMethod; +import com.taobao.arthas.core.util.StringUtils; import com.taobao.arthas.core.util.ThreadLocalWatch; import java.util.ArrayList; @@ -65,9 +70,16 @@ import static com.taobao.arthas.core.util.ArthasCheckUtils.isEquals; class MonitorAdviceListener extends AdviceListenerAdapter { // 输出定时任务 private Timer timer; + private static final Logger logger = LoggerFactory.getLogger(MonitorAdviceListener.class); // 监控数据 private ConcurrentHashMap> monitorData = new ConcurrentHashMap>(); private final ThreadLocalWatch threadLocalWatch = new ThreadLocalWatch(); + private final ThreadLocal conditionResult = new ThreadLocal() { + @Override + protected Boolean initialValue() { + return true; + } + }; private MonitorCommand command; private CommandProcess process; @@ -98,22 +110,47 @@ class MonitorAdviceListener extends AdviceListenerAdapter { public void before(ClassLoader loader, Class clazz, ArthasMethod method, Object target, Object[] args) throws Throwable { threadLocalWatch.start(); + if (!StringUtils.isEmpty(this.command.getConditionExpress()) && command.isBefore()) { + Advice advice = Advice.newForBefore(loader, clazz, method, target, args); + long cost = threadLocalWatch.cost(); + this.conditionResult.set(isConditionMet(this.command.getConditionExpress(), advice, cost)); + //重新计算执行方法的耗时(排除执行condition-express耗时) + threadLocalWatch.start(); + } } @Override public void afterReturning(ClassLoader loader, Class clazz, ArthasMethod method, Object target, Object[] args, Object returnObject) throws Throwable { - finishing(clazz, method, false); + finishing(clazz, method, false, Advice.newForAfterRetuning(loader, clazz, method, target, args, returnObject)); } @Override public void afterThrowing(ClassLoader loader, Class clazz, ArthasMethod method, Object target, Object[] args, Throwable throwable) { - finishing(clazz, method, true); + finishing(clazz, method, true, Advice.newForAfterThrowing(loader, clazz, method, target, args, throwable)); } - private void finishing(Class clazz, ArthasMethod method, boolean isThrowing) { + private void finishing(Class clazz, ArthasMethod method, boolean isThrowing, Advice advice) { double cost = threadLocalWatch.costInMillis(); + + if (command.isBefore()) { + if (!this.conditionResult.get()) { + return; + } + } else { + try { + //不满足condition-express的不纳入统计 + if (!isConditionMet(this.command.getConditionExpress(), advice, cost)) { + return; + } + } catch (ExpressException e) { + //condition-express执行错误的不纳入统计 + logger.warn("monitor execute condition-express failed.", e); + return; + } + } + final Key key = new Key(clazz.getName(), method.getName()); while (true) { diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorCommand.java index 0b4a0eed..2184a4d0 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorCommand.java @@ -23,15 +23,19 @@ import com.taobao.middleware.cli.annotations.Summary; @Description("\nExamples:\n" + " monitor org.apache.commons.lang.StringUtils isBlank\n" + " monitor org.apache.commons.lang.StringUtils isBlank -c 5\n" + + " monitor org.apache.commons.lang.StringUtils isBlank params[0]!=null\n" + + " monitor -b org.apache.commons.lang.StringUtils isBlank params[0]!=null\n" + " monitor -E org\\.apache\\.commons\\.lang\\.StringUtils isBlank\n" + Constants.WIKI + Constants.WIKI_HOME + "monitor") public class MonitorCommand extends EnhancerCommand { private String classPattern; private String methodPattern; + private String conditionExpress; private int cycle = 60; private boolean isRegEx = false; private int numberOfLimit = 100; + private boolean isBefore = false; @Argument(argName = "class-pattern", index = 0) @Description("Path and classname of Pattern Matching") @@ -45,6 +49,12 @@ public class MonitorCommand extends EnhancerCommand { this.methodPattern = methodPattern; } + @Argument(argName = "condition-express", index = 2, required = false) + @Description(Constants.CONDITION_EXPRESS) + public void setConditionExpress(String conditionExpress) { + this.conditionExpress = conditionExpress; + } + @Option(shortName = "c", longName = "cycle") @Description("The monitor interval (in seconds), 60 seconds by default") public void setCycle(int cycle) { @@ -63,6 +73,12 @@ public class MonitorCommand extends EnhancerCommand { this.numberOfLimit = numberOfLimit; } + @Option(shortName = "b", longName = "before", flag = true) + @Description("Evaluate the condition-express before method invoke") + public void setBefore(boolean before) { + isBefore = before; + } + public String getClassPattern() { return classPattern; } @@ -71,6 +87,10 @@ public class MonitorCommand extends EnhancerCommand { return methodPattern; } + public String getConditionExpress() { + return conditionExpress; + } + public int getCycle() { return cycle; } @@ -83,6 +103,10 @@ public class MonitorCommand extends EnhancerCommand { return numberOfLimit; } + public boolean isBefore() { + return isBefore; + } + @Override protected Matcher getClassNameMatcher() { if (classNameMatcher == null) { diff --git a/site/src/site/sphinx/en/monitor.md b/site/src/site/sphinx/en/monitor.md index ce9fcf45..40aaf1c8 100644 --- a/site/src/site/sphinx/en/monitor.md +++ b/site/src/site/sphinx/en/monitor.md @@ -5,7 +5,7 @@ monitor > Monitor method invocation. -Monitor invocation for the method matched with `class-pattern` and `method-pattern`. +Monitor invocation for the method matched with `class-pattern` and `method-pattern` and filter by `condition-expression`. `monitor` is not a command returning immediately. @@ -34,8 +34,10 @@ Parameter `[c:]` stands for cycles of statistics. Its value is an integer value |---:|:---| |*class-pattern*|pattern for the class name| |*method-pattern*|pattern for the method name| +|*condition-expression*|condition expression for filtering method calls| |`[E]`|turn on regex matching while the default is wildcard matching| |`[c:]`|cycle of statistics, the default value: `120`s| +|`[b]`|evaluate the condition-expression before method invoke| ### Usage @@ -67,3 +69,58 @@ Affect(class-cnt:1 , method-cnt:1) cost in 94 ms. ----------------------------------------------------------------------------------------------- 2018-12-03 19:07:03 demo.MathGame primeFactors 2 2 0 3182.72 0.00% ``` + +#### Evaluate condition-express to filter method (after method call) + +```bash +monitor -c 5 demo.MathGame primeFactors "params[0] <= 2" +Press Q or Ctrl+C to abort. +Affect(class count: 1 , method count: 1) cost in 19 ms, listenerId: 5 + timestamp class method total success fail avg-rt(ms) fail-rate +----------------------------------------------------------------------------------------------- + 2020-09-02 09:42:36 demo.MathGame primeFactors 5 3 2 0.09 40.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:41 demo.MathGame primeFactors 5 2 3 0.11 60.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:46 demo.MathGame primeFactors 5 1 4 0.06 80.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:51 demo.MathGame primeFactors 5 1 4 0.12 80.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:56 demo.MathGame primeFactors 5 3 2 0.15 40.00% +``` + +#### Evaluate condition-express to filter method (before method call) + +```bash +monitor -b -c 5 com.test.testes.MathGame primeFactors "params[0] <= 2" +Press Q or Ctrl+C to abort. +Affect(class count: 1 , method count: 1) cost in 21 ms, listenerId: 4 + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:41:57 demo.MathGame primeFactors 1 0 1 0.10 100.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:02 demo.MathGame primeFactors 3 0 3 0.06 100.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:07 demo.MathGame primeFactors 2 0 2 0.06 100.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:12 demo.MathGame primeFactors 1 0 1 0.05 100.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:17 demo.MathGame primeFactors 2 0 2 0.10 100.00% +``` + diff --git a/site/src/site/sphinx/monitor.md b/site/src/site/sphinx/monitor.md index 87bd06c6..e86f8d81 100644 --- a/site/src/site/sphinx/monitor.md +++ b/site/src/site/sphinx/monitor.md @@ -5,7 +5,7 @@ monitor > 方法执行监控 -对匹配 `class-pattern`/`method-pattern`的类、方法的调用进行监控。 +对匹配 `class-pattern`/`method-pattern`/`condition-express`的类、方法的调用进行监控。 `monitor` 命令是一个非实时返回命令. @@ -34,8 +34,10 @@ monitor |---:|:---| |*class-pattern*|类名表达式匹配| |*method-pattern*|方法名表达式匹配| +|*condition-express*|条件表达式| |[E]|开启正则表达式匹配,默认为通配符匹配| |`[c:]`|统计周期,默认值为120秒| +|[b]|在**方法调用之前**计算condition-express| ### 使用参考 @@ -67,3 +69,59 @@ Affect(class-cnt:1 , method-cnt:1) cost in 94 ms. ----------------------------------------------------------------------------------------------- 2018-12-03 19:07:03 demo.MathGame primeFactors 2 2 0 3182.72 0.00% ``` + +#### 计算条件表达式过滤统计结果(方法执行完毕之后) + +```bash +monitor -c 5 demo.MathGame primeFactors "params[0] <= 2" +Press Q or Ctrl+C to abort. +Affect(class count: 1 , method count: 1) cost in 19 ms, listenerId: 5 + timestamp class method total success fail avg-rt(ms) fail-rate +----------------------------------------------------------------------------------------------- + 2020-09-02 09:42:36 demo.MathGame primeFactors 5 3 2 0.09 40.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:41 demo.MathGame primeFactors 5 2 3 0.11 60.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:46 demo.MathGame primeFactors 5 1 4 0.06 80.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:51 demo.MathGame primeFactors 5 1 4 0.12 80.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:56 demo.MathGame primeFactors 5 3 2 0.15 40.00% +``` + +#### 计算条件表达式过滤统计结果(方法执行完毕之前) + + +```bash +monitor -b -c 5 com.test.testes.MathGame primeFactors "params[0] <= 2" +Press Q or Ctrl+C to abort. +Affect(class count: 1 , method count: 1) cost in 21 ms, listenerId: 4 + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:41:57 demo.MathGame primeFactors 1 0 1 0.10 100.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:02 demo.MathGame primeFactors 3 0 3 0.06 100.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:07 demo.MathGame primeFactors 2 0 2 0.06 100.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:12 demo.MathGame primeFactors 1 0 1 0.05 100.00% + + timestamp class method total success fail avg-rt(ms) fail-rate +---------------------------------------------------------------------------------------------- + 2020-09-02 09:42:17 demo.MathGame primeFactors 2 0 2 0.10 100.00% +``` +