transform command: monitor

This commit is contained in:
gongdewei
2020-04-28 15:38:51 +08:00
parent af2411d994
commit 56fe820605
5 changed files with 173 additions and 98 deletions
@@ -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<MonitorData> monitorDataList;
public MonitorModel() {
}
public MonitorModel(List<MonitorData> monitorDataList) {
this.monitorDataList = monitorDataList;
}
@Override
public String getType() {
return "monitor";
}
public List<MonitorData> getMonitorDataList() {
return monitorDataList;
}
public void setMonitorDataList(List<MonitorData> monitorDataList) {
this.monitorDataList = monitorDataList;
}
}
@@ -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;
/**
* 输出的内容格式为:<br/>
@@ -70,7 +61,7 @@ class MonitorAdviceListener extends ReflectAdviceListenerAdapter {
// 输出定时任务
private Timer timer;
// 监控数据
private ConcurrentHashMap<Key, AtomicReference<Data>> monitorData = new ConcurrentHashMap<Key, AtomicReference<Data>>();
private ConcurrentHashMap<Key, AtomicReference<MonitorData>> monitorData = new ConcurrentHashMap<Key, AtomicReference<MonitorData>>();
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<Data> value = monitorData.get(key);
AtomicReference<MonitorData> value = monitorData.get(key);
if (null == value) {
monitorData.putIfAbsent(key, new AtomicReference<Data>(new Data()));
monitorData.putIfAbsent(key, new AtomicReference<MonitorData>(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<Key, AtomicReference<Data>> monitorData;
private Map<Key, AtomicReference<MonitorData>> monitorData;
private CommandProcess process;
private int limit;
MonitorTimer(Map<Key, AtomicReference<Data>> monitorData, CommandProcess process, int limit) {
MonitorTimer(Map<Key, AtomicReference<MonitorData>> 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<MonitorData> monitorDataList = new ArrayList<MonitorData>(monitorData.size());
for (Map.Entry<Key, AtomicReference<MonitorData>> entry : monitorData.entrySet()) {
final AtomicReference<MonitorData> value = entry.getValue();
for (Map.Entry<Key, AtomicReference<Data>> entry : monitorData.entrySet()) {
final AtomicReference<Data> 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;
}
}
}
@@ -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;
}
}
@@ -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<MonitorModel> {
@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;
}
}
@@ -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);
}