diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/MonitorModel.java b/core/src/main/java/com/taobao/arthas/core/command/model/MonitorModel.java new file mode 100644 index 000000000..d59202b47 --- /dev/null +++ b/core/src/main/java/com/taobao/arthas/core/command/model/MonitorModel.java @@ -0,0 +1,33 @@ +package com.taobao.arthas.core.command.model; + +import com.taobao.arthas.core.command.monitor200.MonitorData; + +import java.util.List; + +/** + * @author gongdewei 2020/4/28 + */ +public class MonitorModel extends ResultModel { + + private List monitorDataList; + + public MonitorModel() { + } + + public MonitorModel(List monitorDataList) { + this.monitorDataList = monitorDataList; + } + + @Override + public String getType() { + return "monitor"; + } + + public List getMonitorDataList() { + return monitorDataList; + } + + public void setMonitorDataList(List monitorDataList) { + this.monitorDataList = monitorDataList; + } +} 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 eea9f8640..010b9efb2 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,24 +1,15 @@ package com.taobao.arthas.core.command.monitor200; import com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter; +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.ThreadLocalWatch; -import com.taobao.text.Decoration; -import com.taobao.text.ui.TableElement; -import com.taobao.text.util.RenderUtil; - -import java.text.DecimalFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; import static com.taobao.arthas.core.util.ArthasCheckUtils.isEquals; -import static com.taobao.text.ui.Element.label; /** * 输出的内容格式为:
@@ -70,7 +61,7 @@ class MonitorAdviceListener extends ReflectAdviceListenerAdapter { // 输出定时任务 private Timer timer; // 监控数据 - private ConcurrentHashMap> monitorData = new ConcurrentHashMap>(); + private ConcurrentHashMap> monitorData = new ConcurrentHashMap>(); private final ThreadLocalWatch threadLocalWatch = new ThreadLocalWatch(); private MonitorCommand command; private CommandProcess process; @@ -120,15 +111,15 @@ class MonitorAdviceListener extends ReflectAdviceListenerAdapter { final Key key = new Key(clazz.getName(), method.getName()); while (true) { - AtomicReference value = monitorData.get(key); + AtomicReference value = monitorData.get(key); if (null == value) { - monitorData.putIfAbsent(key, new AtomicReference(new Data())); + monitorData.putIfAbsent(key, new AtomicReference(new MonitorData())); continue; } while (true) { - Data oData = value.get(); - Data nData = new Data(); + MonitorData oData = value.get(); + MonitorData nData = new MonitorData(); nData.setCost(oData.getCost() + cost); if (isThrowing) { nData.setFailed(oData.getFailed() + 1); @@ -147,11 +138,11 @@ class MonitorAdviceListener extends ReflectAdviceListenerAdapter { } private class MonitorTimer extends TimerTask { - private Map> monitorData; + private Map> monitorData; private CommandProcess process; private int limit; - MonitorTimer(Map> monitorData, CommandProcess process, int limit) { + MonitorTimer(Map> monitorData, CommandProcess process, int limit) { this.monitorData = monitorData; this.process = process; this.limit = limit; @@ -169,53 +160,26 @@ class MonitorAdviceListener extends ReflectAdviceListenerAdapter { return; } - TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1); - table.row(true, label("timestamp").style(Decoration.bold.bold()), - label("class").style(Decoration.bold.bold()), - label("method").style(Decoration.bold.bold()), - label("total").style(Decoration.bold.bold()), - label("success").style(Decoration.bold.bold()), - label("fail").style(Decoration.bold.bold()), - label("avg-rt(ms)").style(Decoration.bold.bold()), - label("fail-rate").style(Decoration.bold.bold())); + List monitorDataList = new ArrayList(monitorData.size()); + for (Map.Entry> entry : monitorData.entrySet()) { + final AtomicReference value = entry.getValue(); - for (Map.Entry> entry : monitorData.entrySet()) { - final AtomicReference value = entry.getValue(); - - Data data; + MonitorData data; while (true) { data = value.get(); - if (value.compareAndSet(data, new Data())) { + //swap monitor data to new instance + if (value.compareAndSet(data, new MonitorData())) { break; } } if (null != data) { - - final DecimalFormat df = new DecimalFormat("0.00"); - - table.row( - new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), - entry.getKey().getClassName(), - entry.getKey().getMethodName(), - "" + data.getTotal(), - "" + data.getSuccess(), - "" + data.getFailed(), - df.format(div(data.getCost(), data.getTotal())), - df.format(100.0d * div(data.getFailed(), data.getTotal())) + "%" - ); - + data.setClassName(entry.getKey().getClassName()); + data.setMethodName(entry.getKey().getMethodName()); + monitorDataList.add(data); } } - - process.write(RenderUtil.render(table, process.width()) + "\n"); - } - - private double div(double a, double b) { - if (b == 0) { - return 0; - } - return a / b; + process.appendResult(new MonitorModel(monitorDataList)); } } @@ -259,47 +223,4 @@ class MonitorAdviceListener extends ReflectAdviceListenerAdapter { } - /** - * 数据监控用的value - * - * @author vlinux - */ - private static class Data { - private int total; - private int success; - private int failed; - private double cost; - - public int getTotal() { - return total; - } - - public void setTotal(int total) { - this.total = total; - } - - public int getSuccess() { - return success; - } - - public void setSuccess(int success) { - this.success = success; - } - - public int getFailed() { - return failed; - } - - public void setFailed(int failed) { - this.failed = failed; - } - - public double getCost() { - return cost; - } - - public void setCost(double cost) { - this.cost = cost; - } - } } diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorData.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorData.java new file mode 100644 index 000000000..9646dcfd7 --- /dev/null +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/MonitorData.java @@ -0,0 +1,63 @@ +package com.taobao.arthas.core.command.monitor200; + +/** + * 数据监控用的value for MonitorCommand + * + * @author vlinux + */ +public class MonitorData { + private String className; + private String methodName; + private int total; + private int success; + private int failed; + private double cost; + + 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 int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public int getSuccess() { + return success; + } + + public void setSuccess(int success) { + this.success = success; + } + + public int getFailed() { + return failed; + } + + public void setFailed(int failed) { + this.failed = failed; + } + + public double getCost() { + return cost; + } + + public void setCost(double cost) { + this.cost = cost; + } +} diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/MonitorView.java b/core/src/main/java/com/taobao/arthas/core/command/view/MonitorView.java new file mode 100644 index 000000000..c31743dbb --- /dev/null +++ b/core/src/main/java/com/taobao/arthas/core/command/view/MonitorView.java @@ -0,0 +1,57 @@ +package com.taobao.arthas.core.command.view; + +import com.taobao.arthas.core.command.model.MonitorModel; +import com.taobao.arthas.core.command.monitor200.MonitorData; +import com.taobao.arthas.core.shell.command.CommandProcess; +import com.taobao.text.Decoration; +import com.taobao.text.ui.TableElement; +import com.taobao.text.util.RenderUtil; + +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import static com.taobao.text.ui.Element.label; + +/** + * @author gongdewei 2020/4/28 + */ +public class MonitorView extends ResultView { + @Override + public void draw(CommandProcess process, MonitorModel result) { + TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1); + table.row(true, label("timestamp").style(Decoration.bold.bold()), + label("class").style(Decoration.bold.bold()), + label("method").style(Decoration.bold.bold()), + label("total").style(Decoration.bold.bold()), + label("success").style(Decoration.bold.bold()), + label("fail").style(Decoration.bold.bold()), + label("avg-rt(ms)").style(Decoration.bold.bold()), + label("fail-rate").style(Decoration.bold.bold())); + + final DecimalFormat df = new DecimalFormat("0.00"); + + for (MonitorData data : result.getMonitorDataList()) { + table.row( + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), + data.getClassName(), + data.getMethodName(), + "" + data.getTotal(), + "" + data.getSuccess(), + "" + data.getFailed(), + df.format(div(data.getCost(), data.getTotal())), + df.format(100.0d * div(data.getFailed(), data.getTotal())) + "%" + ); + } + + process.write(RenderUtil.render(table, process.width()) + "\n"); + + } + + private double div(double a, double b) { + if (b == 0) { + return 0; + } + return a / b; + } +} diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/ResultViewResolver.java b/core/src/main/java/com/taobao/arthas/core/command/view/ResultViewResolver.java index 043532386..febcd97de 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/view/ResultViewResolver.java +++ b/core/src/main/java/com/taobao/arthas/core/command/view/ResultViewResolver.java @@ -64,6 +64,7 @@ public class ResultViewResolver { registerView(new PerfCounterModel(), new PerfCounterView()); registerView(new ProfilerModel(), new ProfilerView()); registerView(new TimeTunnelModel(), new TimeTunnelView()); + registerView(new MonitorModel(), new MonitorView()); } catch (Throwable e) { logger.error("register result view failed", e); }