nGrinder二次开发之监控机器性能数据
转载: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二次开发之监控机器性能数据的更多相关文章
- 使用Jyhon脚本和PMI模块监控WAS性能数据
使用Jyhon脚本和PMI模块监控WAS性能数据的优点有: 1.可以使用非交互的方式远程获取数据 2.不需要图形化模块支持 3.对各种was版本的兼容性较高 4.使用方便,官方自带 缺点也有很多: 1 ...
- Python监控进程性能数据并画图保存为PDF文档
引言 利用psutil模块(https://pypi.python.org/pypi/psutil/),可以很方便的监控系统的CPU.内存.磁盘IO.网络带宽等性能參数,下面是否代码为监控某个特定程序 ...
- ENVI二次开发模式下的Landsat数据读取
从usgs网站或者马里兰大学下载TM或Landsat原始数据,数据可能包括9个tif数据,两个txt文件和一个gtf文件.示例结构如下: ENVI下可以直接打开*_MTL.txt文件打开,打开后波段列 ...
- ODI KM二次开发手册
ODI KM二次开发手册 分类: ODI(16) 目录(?)[+] 1 引言 1.1 编写目的 本手册面向的读者对象为具备数据集成业务知识及对ODI操作了解的开发人员,作为其完成基于ODI基础上K ...
- [开源地址] 放弃Flink,.NET5.0开发CSharpFlink,简要设计、部署及二次开发说明。
github地址:https://github.com/wxzz/CSharpFlinkgitee地址:https://gitee.com/wxzz/CSharpFlink 1 概述及背景 我们有一个 ...
- 性能测试工具 nGrinder 项目剖析及二次开发
转:https://testerhome.com/topics/4225 0.背景 组内需要一款轻量级的性能测试工具,之前考虑过LR(太笨重,单实例,当然它的地位是不容置疑的),阿里云的PTS(htt ...
- nGrinder对监控机器收集自定义数据及源码分析
转载:https://blog.csdn.net/neven7/article/details/50782451 0.背景 性能测试工具nGrinder支持在无需修改源码的情况下,对目标服务器收集自定 ...
- nagios二次开发(四)---nagios监控原理和nagios架构简介
nagios监控原理 下面根据上面摘自网络的原理图对nagios的监控原理进行一下简单的说明: 1.nagios通过nsca进行被动监控.那么什么是被动监控呢?被动监测:就是指由被监测的服务器主动上传 ...
- zabbix nagios 类nagios 之 不以性能为前提的开发和监控都是瞎扯淡
从最初的nagios到现在强大的zabbix 3.0,我想说,不以性能为前提的开发和监控都是瞎扯淡? 首先我对这两款监控软件的认识: zabbix,很多企业都在用,给人的感觉是很炫,不过我个人觉得虽然 ...
随机推荐
- 单纯用JS做的分页插件
最近公司需要用到分页插件,由于市面上大多都是jQuery的分页插件,而且项目中有自己的工具类,所以说我在工具类中又添加了不依赖jQuery的分页插件,而且分页插件来说对DOM的操作也不是很多,就是用J ...
- 图形管线之旅 Part3
原文:<A trip through the Graphics Pipeline 2011> 翻译:往昔之剑 转载请注明出处 此时,我们一路上通过多个驱动层和命令处理器将draw ...
- HTTP 415错误 Unsupported Content-Type
报如下错误: { "badMediaType": { "message": "Unsupported Content-Type", &quo ...
- SpringBoot学习(六)
1.pom 文件 <?xml version="1.0" encoding="utf-8"?> <dependencies> <d ...
- 深入理解javascript作用域系列第三篇
前面的话 一般认为,javascript代码在执行时是由上到下一行一行执行的.但实际上这并不完全正确,主要是因为声明提升的存在.本文是深入理解javascript作用域系列第三篇——声明提升(hois ...
- Highcharts实现走势图
Highcharts 是一个用纯JavaScript编写的一个图表库, 能够很简单便捷的在web网站或是web应用程序添加有交互性的图表,并且免费提供给个人学习.个人网站和非商业用途使用.HighCh ...
- 常用排序算法的Python实现
冒泡排序 算法思想: 对于一组需要排序的数据,对于相邻的两个数进行比较,使较大(或者较小)的数一直向后推,经过多层排序之后,使整个序列是有序的. 算法实现: def bubble_sort(L): l ...
- Hibernate hql(hibernate query language)基础查询
在开发过程中,数据库的操作我们其实更多的用到的是查询功能,今天开始学习hql的查询. 1.加入必要的工具 2.Hibernate配备的一种非常强大的查询语言,这种查询语言看上去很像sql.但是不要被语 ...
- Loj10086 Easy SSSP
试题描述 输入数据给出一个有 N 个节点,M 条边的带权有向图.要求你写一个程序,判断这个有向图中是否存在负权回路.如果从一个点沿着某条路径出发,又回到了自己,而且所经过的边上的权和小于 0,就说 ...
- Nginx服务器的启动控制
写在前面的话:读书破万卷,编码如有神--------------------------------------------------------------------主要内容包括: nginx服 ...