转载: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. 单纯用JS做的分页插件

    最近公司需要用到分页插件,由于市面上大多都是jQuery的分页插件,而且项目中有自己的工具类,所以说我在工具类中又添加了不依赖jQuery的分页插件,而且分页插件来说对DOM的操作也不是很多,就是用J ...

  2. 图形管线之旅 Part3

    原文:<A trip through the Graphics Pipeline 2011> 翻译:往昔之剑   转载请注明出处   此时,我们一路上通过多个驱动层和命令处理器将draw ...

  3. HTTP 415错误 Unsupported Content-Type

    报如下错误: { "badMediaType": { "message": "Unsupported Content-Type", &quo ...

  4. SpringBoot学习(六)

    1.pom 文件 <?xml version="1.0" encoding="utf-8"?> <dependencies> <d ...

  5. 深入理解javascript作用域系列第三篇

    前面的话 一般认为,javascript代码在执行时是由上到下一行一行执行的.但实际上这并不完全正确,主要是因为声明提升的存在.本文是深入理解javascript作用域系列第三篇——声明提升(hois ...

  6. Highcharts实现走势图

    Highcharts 是一个用纯JavaScript编写的一个图表库, 能够很简单便捷的在web网站或是web应用程序添加有交互性的图表,并且免费提供给个人学习.个人网站和非商业用途使用.HighCh ...

  7. 常用排序算法的Python实现

    冒泡排序 算法思想: 对于一组需要排序的数据,对于相邻的两个数进行比较,使较大(或者较小)的数一直向后推,经过多层排序之后,使整个序列是有序的. 算法实现: def bubble_sort(L): l ...

  8. Hibernate hql(hibernate query language)基础查询

    在开发过程中,数据库的操作我们其实更多的用到的是查询功能,今天开始学习hql的查询. 1.加入必要的工具 2.Hibernate配备的一种非常强大的查询语言,这种查询语言看上去很像sql.但是不要被语 ...

  9. Loj10086 Easy SSSP

      试题描述 输入数据给出一个有 N 个节点,M 条边的带权有向图.要求你写一个程序,判断这个有向图中是否存在负权回路.如果从一个点沿着某条路径出发,又回到了自己,而且所经过的边上的权和小于 0,就说 ...

  10. Nginx服务器的启动控制

    写在前面的话:读书破万卷,编码如有神--------------------------------------------------------------------主要内容包括: nginx服 ...