转载:https://blog.csdn.net/neven7/article/details/53909256

1.背景

做性能测试时,统计性能数据分为被压系统的数据和被压系统所在机器的数据,被压系统所在机器的数据主要包括CPU利用率、内存使用率、网络IO、磁盘IO和负载load;nGrinder默认只收集CPU, Memory, Received Byte/s, Sent Byte Per Secode/s,同时支持自定义数据收集,之前介绍过相关内容:nGrinder对监控机器收集自定义数据及源码分析

展示自定义数据需定时的写文件,比较麻烦;本文将介绍如何改动源码,直接展示CPU利用率、内存使用率、网络IO、磁盘IO和负载load这5类数据。

2.实现

nGrinder是通过sigar api统计机器性能数据,sigar项目主页:https://support.hyperic.com/display/SIGAR/Home, sigar api :http://cpansearch.perl.org/src/DOUGM/hyperic-sigar-1.6.3-src/docs/javadoc/org/hyperic/sigar/package-summary.html

2-1.新增数据类型

ngrinder-core中package:org.ngrinder.monitor.share.domain下SystemInfo类定义了收集的数据类型,新增load、read、write和memUsedPercentage数据字段:

/**
* modify by hugang
*/
public class SystemInfo extends MonitorInfo implements Serializable { private static final long serialVersionUID = -2995334644975166549L; /**
* Header field of monitor status fields.
*/
// 新增load、磁盘IO和内存使用率
public static final String HEADER = "ip,system,collectTime,freeMemory,"
+ "totalMemory,cpuUsedPercentage,receivedPerSec,sentPerSec,load,read,write,memUsedPercentage"; public boolean isParsed() {
return true;
} /**
* Enum for the system type, linux or windows.
*/
public enum System {
LINUX, WINDOW
} private System system; // 网络IO
protected BandWidth bandWidth; private long totalCpuValue; private long idleCpuValue; private long freeMemory; private long totalMemory; private float cpuUsedPercentage; // load
private double load; // 磁盘读
private long read; // 磁盘写
private long write; // 内存使用率
private double memUsedPercentage; ...
set()、get()方法 public void parse(CompositeData cd) {
// 新增
this.load = getDouble(cd, "load");
this.write = getLong(cd, "write");
this.read = getLong(cd, "read");
this.memUsedPercentage = getDouble(cd, "memUsedPercentage");
} public String toRecordString() {
StringBuilder sb = new StringBuilder();
sb.append(ip).append(",").append(system).append(",");
sb.append(DateUtils.getCollectTimeInLong(new Date(getCollectTime()))).append(",").append(freeMemory).append(","); sb.append(totalMemory).append(",").append(cpuUsedPercentage);
if (bandWidth != null) {
sb.append(",").append(bandWidth.getReceivedPerSec()).append(",").append(bandWidth.getSentPerSec());
}
// 新类型load、read、write、memUsedPercentage数据拼接
sb.append(",").append(load).append(",").append(read).append(",").append(write).append(",").append(memUsedPercentage);
if (customValues != null) {
sb.append(",").append(customValues);
}
return sb.toString();
} public static class NullSystemInfo extends SystemInfo {
private static final NullSystemInfo instance = new NullSystemInfo(); public static SystemInfo getNullSystemInfo() {
return instance;
} /**
* Return the empty record string.
*
* @return null filled record string.
* @see #toRecordString()
*/
@Override
public String toRecordString() {
StringBuilder sb = new StringBuilder();
sb.append("null").append(",").append("null").append(",");
sb.append("null").append(",").append("null").append(",");
sb.append("null").append(",").append("null");
if (bandWidth != null) {
sb.append(",").append("null").append(",").append("null");
}
// 拼接新类型数据为"null"
sb.append(",").append("null").append(",").append("null").append(",").append("null");
if (customValues != null) {
int valueCount = StringUtils.countMatches(customValues, ",") + 1;
for (int i = 0; i < valueCount; i++) {
sb.append(",").append("null");
}
}
return sb.toString();
} public boolean isParsed() {
return false;
}
} }

2-2.收集新增数据

ngrinder-core中package:org.ngrinder.monitor.collector下SystemDataCollector类中execute()方法实现了系统数据的收集:

/**
* modify by hugang
*/
public synchronized SystemInfo execute() {
SystemInfo systemInfo = new SystemInfo();
systemInfo.setCollectTime(System.currentTimeMillis());
try {
BandWidth networkUsage = getNetworkUsage();
BandWidth bandWidth = networkUsage.adjust(prev.getBandWidth());
systemInfo.setBandWidth(bandWidth);
// getCombined()代表 Sum of User + Sys + Nice + Wait
systemInfo.setCPUUsedPercentage((float) sigar.getCpuPerc().getCombined() * 100);
Cpu cpu = sigar.getCpu();
systemInfo.setTotalCpuValue(cpu.getTotal());
systemInfo.setIdleCpuValue(cpu.getIdle());
Mem mem = sigar.getMem();
systemInfo.setTotalMemory(mem.getTotal() / 1024L);
systemInfo.setFreeMemory(mem.getActualFree() / 1024L); // 新增load、磁盘IO和内存使用率
// The system load averages for the past 1, 5, and 15 minutes.
double load = 0;
long read = 0l;
long write = 0l; load = sigar.getLoadAverage()[0]; //LOGGER.info("monitor system load:{}", load); // 所有的文件系统
FileSystem[] fileSystems = sigar.getFileSystemList();
// 获取本地文件系统
List<String> localDevNames = new ArrayList<String>();
for(FileSystem fileSystem : fileSystems) {
if(fileSystem.getType() == FileSystem.TYPE_LOCAL_DISK) {
localDevNames.add(fileSystem.getDevName());
}
} for(String localDevName : localDevNames) {
read += sigar.getDiskUsage(localDevName).getReadBytes();
write += sigar.getDiskUsage(localDevName).getWriteBytes();
} //LOGGER.info("monitor system read:{}, write:{}", read, write); systemInfo.setLoad(load);
systemInfo.setRead(read / 1024L);
systemInfo.setWrite(write / 1024L);
systemInfo.setMemUsedPercentage(mem.getUsedPercent()); systemInfo.setSystem(OperatingSystem.IS_WIN32 ? SystemInfo.System.WINDOW : SystemInfo.System.LINUX);
systemInfo.setCustomValues(getCustomMonitorData());
} catch (Throwable e) {
LOGGER.error("Error while getting system perf data:{}", e.getMessage());
LOGGER.debug("Error trace is ", e);
}
prev = systemInfo;
return systemInfo;
}

2-3.前端monitor模板

ngrinder-controller下src/main/webapp/WEB-INF/ftl/perftest/detail_report/monitor.ftl定义了系统数据的可视化,修改如下:

<#setting number_format="computer">
<#import "../../common/spring.ftl" as spring/>
<div class="page-header page-header">
<h4>Monitor</h4>
</div>
<h6 id="cpu_usage_chart_header">CPU利用率(User + Sys + Nice + Wait),建议值:小于75%</h6>
<div class="chart" id="cpu_usage_chart"></div>
<h6 id="mem_usage_chart_header">Memory使用率,建议值:小于80%</h6>
<div class="chart" id="mem_usage_chart"></div>
<h6 id="received_byte_per_sec_chart_header">Received Byte Per Second</h6>
<div class="chart" id="received_byte_per_sec_chart"></div>
<h6 id="sent_byte_per_sec_chart_header">Sent Byte Per Second</h6>
<div class="chart" id="sent_byte_per_sec_chart"></div> <h6 id="custom_monitor_chart_1_header">Load-average(one-minute)</h6>
<div class="chart" id="custom_monitor_chart_1"></div>
<h6 id="custom_monitor_chart_2_header">Physical Disk readBytes(total number of physical disk reads)</h6>
<div class="chart" id="custom_monitor_chart_2"></div>
<h6 id="custom_monitor_chart_3_header">Physical Disk writesBytes(total number of physical disk writes)</h6>
<div class="chart" id="custom_monitor_chart_3"></div> <script>
//@ sourceURL=/perftest/detail_report/monitor
function getMonitorDataAndDraw(testId, targetIP) {
var ajaxObj = new AjaxObj("/perftest/api/" + testId + "/monitor");
ajaxObj.params = {
targetIP: targetIP,
imgWidth: parseInt($("#cpu_usage_chart").width())
};
ajaxObj.success = function (data) {
var interval = data.chartInterval; // modify by hugang
// data.customData1为load, data.customData2为磁盘读, data.customData3为磁盘写
drawChart('cpu_usage_chart', [data.cpu], formatPercentage, interval);
// 调整为内存使用率
drawChart('mem_usage_chart', [data.customData4], formatPercentage, interval);
// load
drawChart("custom_monitor_chart_1", [data.customData1], formatDouble, interval);
drawChart("received_byte_per_sec_chart", [data.received], formatNetwork, interval);
drawChart("sent_byte_per_sec_chart", [data.sent], formatNetwork, interval);
// 磁盘读
drawChart("custom_monitor_chart_2", [data.customData2], formatMemory, interval);
// 磁盘写
drawChart("custom_monitor_chart_3", [data.customData3], formatMemory, interval); createChartExportButton("<@spring.message "perfTest.report.exportImg.button"/>", "<@spring.message "perfTest.report.exportImg.title"/>");
};
ajaxObj.call();
}
function drawChart(id, data, yFormat, interval) {
return new Chart(id, data, interval, {yAxisFormatter: yFormat}).plot();
} function drawOptionalChart(id, data, interval, labels) {
var result = drawChart(id, data, interval, labels);
if (result.isEmpty()) {
$("#" + id).hide();
$("#" + id + "_header").hide();
}
}
getMonitorDataAndDraw(${id}, "${targetIP}"); </script>

3.结果展示

对工程进行打包:

hugangdeMacBook-Pro:CPC hugang$ mvn clean -Dmaven.test.skip=true package

部署新war包,服务正常启动后;需重新下载监控包,因为依赖的ngrinder-core.jar包有改动,重新启动监控服务后,执行性能测试任务。

系统监控数据文件:/root/.ngrinder/perftest/0_999/${任务id}/report下 monitor_system_${ip}.data新增load、read、write和memUsedPercentage。

前端展示:

nGrinder二次开发之监控机器性能数据的更多相关文章

  1. 使用Jyhon脚本和PMI模块监控WAS性能数据

    使用Jyhon脚本和PMI模块监控WAS性能数据的优点有: 1.可以使用非交互的方式远程获取数据 2.不需要图形化模块支持 3.对各种was版本的兼容性较高 4.使用方便,官方自带 缺点也有很多: 1 ...

  2. Python监控进程性能数据并画图保存为PDF文档

    引言 利用psutil模块(https://pypi.python.org/pypi/psutil/),可以很方便的监控系统的CPU.内存.磁盘IO.网络带宽等性能參数,下面是否代码为监控某个特定程序 ...

  3. ENVI二次开发模式下的Landsat数据读取

    从usgs网站或者马里兰大学下载TM或Landsat原始数据,数据可能包括9个tif数据,两个txt文件和一个gtf文件.示例结构如下: ENVI下可以直接打开*_MTL.txt文件打开,打开后波段列 ...

  4. ODI KM二次开发手册

    ODI KM二次开发手册   分类: ODI(16) 目录(?)[+] 1 引言 1.1 编写目的 本手册面向的读者对象为具备数据集成业务知识及对ODI操作了解的开发人员,作为其完成基于ODI基础上K ...

  5. [开源地址] 放弃Flink,.NET5.0开发CSharpFlink,简要设计、部署及二次开发说明。

    github地址:https://github.com/wxzz/CSharpFlinkgitee地址:https://gitee.com/wxzz/CSharpFlink 1 概述及背景 我们有一个 ...

  6. 性能测试工具 nGrinder 项目剖析及二次开发

    转:https://testerhome.com/topics/4225 0.背景 组内需要一款轻量级的性能测试工具,之前考虑过LR(太笨重,单实例,当然它的地位是不容置疑的),阿里云的PTS(htt ...

  7. nGrinder对监控机器收集自定义数据及源码分析

    转载:https://blog.csdn.net/neven7/article/details/50782451 0.背景 性能测试工具nGrinder支持在无需修改源码的情况下,对目标服务器收集自定 ...

  8. nagios二次开发(四)---nagios监控原理和nagios架构简介

    nagios监控原理 下面根据上面摘自网络的原理图对nagios的监控原理进行一下简单的说明: 1.nagios通过nsca进行被动监控.那么什么是被动监控呢?被动监测:就是指由被监测的服务器主动上传 ...

  9. zabbix nagios 类nagios 之 不以性能为前提的开发和监控都是瞎扯淡

    从最初的nagios到现在强大的zabbix 3.0,我想说,不以性能为前提的开发和监控都是瞎扯淡? 首先我对这两款监控软件的认识: zabbix,很多企业都在用,给人的感觉是很炫,不过我个人觉得虽然 ...

随机推荐

  1. svn代码同步脚本

    碰到一个需求,主要是2个项目需要用到同一份代码,主要是域名和配置信息不一样,而且要把svn更新的代码同步过去.本来考虑提交时用钩子同步过去,但考虑到同步过去的代码还需要测试,而且另一边代码的时效性不强 ...

  2. 【Splay 总结】

    很多年前学的splay已经忘了? BZOJ 3729 要用Splay啊哭..强制在线.. 二叉查找树 二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree ...

  3. 我的OI生涯 第一章

    第一章   一入电竞深似海 我叫WZY,是TSYZ的一名学生. 2016年7月10日,我进了一个叫做oi的坑. 那时的我不知道什么叫竞赛,不知道什么叫编程,不知道什么是c++. 就记得前一天我特意去图 ...

  4. [BZOJ5010][FJOI2017]矩阵填数(状压DP)

    5010: [Fjoi2017]矩阵填数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 90  Solved: 45[Submit][Status][ ...

  5. 【动态规划/多重背包问题】POJ2392-Space Elevator

    方法同POJ1014-Dividing,唯一不同点在于每一种block有最大限定高度a,故要以a为关键字进行排序,使得最大高度小的在前,否则最大高度小的再后可能放不上去. #include<io ...

  6. 【ArcGIS笔记】数据处理

    1.ARCGIS在导入Excel坐标点的时候出现"没有注册类"的情况怎么办? 确保你本机上装有office,并且版本要能够识别XLSX格式.2007以上. 2.导入excel时re ...

  7. myBatis 切换数据源(spring事务)理解

    1. mybatis (SqlSessionTemplate)的动态代理 a) sqlSession的结构 b)SqlSession 结构 public class SqlSessionTemplat ...

  8. React-Native调用支付宝,微信

    https://www.pingxx.com/docs/downloads Ping++ 是为移动端应用以及 PC 网页量身打造的下一代支付系统,通过一个 SDK 便可以同时支持移动端以及 PC 端网 ...

  9. Go语言设计模式实践:迭代器(Iterator)

    关于本系列 决定开个新坑. 这个系列首先是关于Go语言实践的.在项目中实际使用Go语言也有段时间了,一个体会就是不论是官方文档.图书还是网络资料,关于Go语言惯用法(idiom)的介绍都比较少,基本只 ...

  10. windows样式(style)参考

    [WTL] 窗体Style的含义比较有用的设置:(1)WS_POPUP:弹出式窗体,没有标题栏!WS_BORDER:细的黑边框WS_OVERLAPPED:一般的有标题栏的窗体,见多了.WS_CHILD ...