使用highcharts实现实时监控曲线图

   最近一段时间由于服务器响应有些异常,所以花了半天做了一个简单实时监控页面。如下图




基本原理如下:

1、使用Filter拦截请求,采集服务器响应数据。
若是要收集响应状态码注意构造新的HttpServletResponse

package com.cmgame.ecms.statistic

import javax.servlet.http.HttpServletResponseWrapper
import javax.servlet.http.HttpServletResponse

/**
 * 功能描述
 * @author huzl
 * @version 0.0.1, 12-7-30 下午3:11
 */
class StatusExposingServletResponse extends HttpServletResponseWrapper {
    private Integer status = SC_OK;;

    public Integer getStatus() {
        return status
    }

    def StatusExposingServletResponse(HttpServletResponse response) {
        super(response);
    }

    @Override
    void sendError(int sc, String msg) {
        super.sendError(sc, msg)
        status = sc;
    }

    @Override
    void sendError(int sc) {
        super.sendError(sc)
        status = sc;
    }

    @Override
    void sendRedirect(String location) {
        super.sendRedirect(location)
        status = SC_MOVED_TEMPORARILY;
    }

    @Override
    void setStatus(int sc) {
        super.setStatus(sc)
        status = sc;
    }

    @Override
    void setStatus(int sc, String sm) {
        super.setStatus(sc, sm)
        status = sc;
    }

}

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain){
        long startTime = System.currentTimeMillis();
        StatusExposingServletResponse response = new StatusExposingServletResponse(servletResponse);
        Throwable exception = null;
        try {
            filterChain.doFilter(servletRequest,response)
        } catch (Throwable e) {
            exception = e;
            throw e;
        }finally{
            statisticResult.completeRequest(servletRequest,response,exception,startTime);
        }
    }

若只统计错误状态码则区分Response Code是否大于400,小于400的都是正确响应

如200(OK),206(断点续传),301(永久重定向),302(临时重定向),304(内容未变),大于等于400的状态都是错误响应,计算响应速度区间和平均响应时间的代码我就不贴了

2、定时程序或线程把数据入库或保存到内存中。尽量不要使用java内嵌数据库如hsqldb,H2等,因为这些内存数据库运行时会把所有数据加到内存中,不太适合保存数据采集结果

3、使用Highcharts绘制监控页面
可以参照官网例子 http://www.highcharts.com/demo/dynamic-update
var charts = new Array();
        var serverCount = 6;
        var lastTimes = new Array();
        var max = ${params.int("max")?:120};
        $(document).ready(function() {
            Highcharts.setOptions({
                global: {
                    useUTC: false
                }
            });


            for (var i = 0; i < serverCount; i++) {
                charts[i] = new Highcharts.Chart({
                    chart: {
                        renderTo: 'container' + i,
                        type: 'spline',
                        events: {
                            load: function() {

                                // set up the updating of the chart each second
                                var series = this.series;
                                var serverIndex = i;
                                lastTimes[serverIndex] = 0;
                                var loadData = function() {
                                                                        $.getJSON("http://${request.serverName}:${request.serverPort}${request.contextPath}/toolkits/queryStatistics.gsp", {"lasTime":lastTimes[serverIndex],"proxy":true,"index":serverIndex,"max":max}, function(data) {
                                        for (var k = 0; k < series.length; k++) {
                                            for (var j = 0; j < data[k].length; j++) {
                                                var point = data[k][j];
                                                var isShift = series[k].data.length >= max;
                                                console.log("series " + k + ".data.length=" + series[k].data.length);
                                                var lastTime = 0;
                                                if (series[k].data.length > 0)
                                                    lastTime = series[k].data[series[k].data.length - 1].x;
                                                if (point[0] > lastTime)
                                                    series[k].addPoint([point[0],point[1]], true, isShift);
                                                lastTimes[serverIndex] = point[0];
                                            }
                                        }
                                    })
                                };

                                loadData();
                                setInterval(loadData, 60000);
                            }
                        }
                    },
                    title: {
                        text: '访问量实时监控'
                    },
                    xAxis: [
                        {
                            type: 'datetime',
                            tickPixelInterval: 120
                        }
                    ],
                    yAxis: [
                        {
                            title: {
                                text: '总请求/分钟',
                                style: {
                                    color: '#3E576F'
                                }
                            }
                        },
                        {
                            title: {
                                text: '平均响应时间',
                                style: {
                                    color: '#00AA00'
                                }
                            },opposite:true
                        }
                    ],
                    plotOptions: {
                        spline: {
                            marker:{
                                enabled: false,
                                states: {
                                    hover: {
                                        enabled: true,
                                        symbol: 'circle',
                                        radius: 5,
                                        lineWidth: 1
                                    }
                                }
                            }
                        }
                    },
                    tooltip: {
                        formatter: function() {
                            return '<b>' + this.series.name + '</b><br/>' +
                                    Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' +
                                    Highcharts.numberFormat(this.y, 2);
                        }
                    },
                    legend: {
                        enabled: true
                    },
                    exporting: {
                        enabled: false
                    },
                    series: [
                        {
                            name: '总请求数',
                            data: []
                        },
                        {
                            name: '错误请求数',
                            data: []
                        },
                        {
                            name: '平均响应时间',
                            yAxis:1,
                            data: []
                        }
                    ]
                });
            }

        })

需要注意的是:
1、在series的load事件中使用ajax定时加载数据,需要控制当前chart中的Point数据量,
   series.addPoint(point, true, isShift);
   当series中Point数量超过指定值,设定isShift为true,就可以移除第一个Point,防止浏览器内存占用太大无响应
2、ajax请求时只请求最新采集数据,所以每次加载采集数据后把最后时间保留下来,ajax请求时把当前chart中最后时间带上,获取最新数据

如果每秒采集一下数据并保存到数据库,可以扩充一下功能实现BI的数据挖掘和各维度的钻取该也不能。但由于是浏览器使用svg技术绘制曲线,采集的点太多时初次显示还是比较慢。

猜你喜欢

转载自bloodwolf-china.iteye.com/blog/1617804
今日推荐