zoukankan      html  css  js  c++  java
  • 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。

    前端展示:

  • 相关阅读:
    微信开发教程 Yank.WeiXin.Robot
    HtmlAgilityPack教程
    PHP获取文件的绝对路径
    关于mysql联合索引
    IE无法获得cookie,ie不支持cookie的解决办法,火狐支持
    最详细的cookie和浏览隐私之间的关系
    JavaScipt选取文档元素的方法
    javascript正则表达式
    JS实现操作成功定时回到主页效果
    js实现表格信息的删除和添加
  • 原文地址:https://www.cnblogs.com/ceshi2016/p/8668776.html
Copyright © 2011-2022 走看看