mirror of
https://github.com/alibaba/arthas.git
synced 2026-10-21 05:19:50 +00:00
transform command: monitor
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
+19
-98
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user