GRAPHITE实战

2022-04-21 00:00:00 统计 访问 页面 次数 每隔

这4个文章是一个系列的,关于如何配置 StatsD,Graphite以及如何使用两者来显示访问信息:


在上次把StatsD和Graphite搭建完工后,今天就开始深入研究Graphite怎么用了。Graphite默认绑定在80端口,所以直接用浏览器访问就行,左侧是所有的bucket:

假如你要配置的话,可以访问http://<graphite server>/admin/。后的/不能漏!这个是配置界面可以增加删除用户(需要superuser权限,在第二篇博文里面有讲如何创建superuser的),界面是有够丑的:

这个界面的实用性一般,我比较喜欢使用Dashboard界面(点击Dashboard就可以进入):

Dashboard可以保存点击Dashboard-》Save就可以了,点击Finder可以让你加载你保存的Dashboard。


好,下面是我要统计的信息

1) 用户账号信息,我想知道到底有谁来访问过我的网站,本身statsd不是用来统计这个的,但是为了简单起见,有一个人来访问,我就把他的域账号作为bucket名字,然后increment。

2) 页面的访问计数和页面的渲染时间,这个我使用了timing功能,timing的sum就是10s内页面渲染的总时间,这个没啥用,但是其他两个属性很有用count(用来统计页面访问次数)、upper(用来统计页面渲染大值)。

3) 状态码,这个用来统计出错的次数(404,500)这些。


开始写代码,statsd-client默认提供了一个expressJs的中间件,但是不太符合我的要求,所以我照着他,重写了一个:

var should = require("should");

// For each requested URL (exclude the static resources), we will statistics
// 1) Counter: cer.status_codes.*
// 2) Timing: timers.cer.pages.*
exports.statsdMiddleware = function (statsdClient) {

    return function (req, res, next) {

        should.exists(res.locals);
        should.exists(req.method);
        var startTime = new Date();

        // Shadow end request
        var end = res.end;
        res.end = function () {
            end.apply(res, arguments);

            // Statistics the status code, especailly for 500, 404
            statsdClient.increment('status_codes.' + res.statusCode);

            var timeElapse = new Date() - startTime;

            if (req.route && req.route.path) {
                var path = req.route.path;
                if (Object.prototype.toString.call(path) === '[object RegExp]') {
                    path = path.source;
                }

                if (path === "/") {
                    path = "root";
                }

                if (req.query.productId) {
                    path += '_' + req.query.productId;
                }

                // Statistics the page hit count and time to render the page
                var key = 'pages.' + req.method.toLowerCase() + '_' + path.replace(/:/g, "").replace(/\//, "").replace(/\//g, "_");
                statsdClient.timing(key, timeElapse);

                // Statistics user accounts
                var user = req.headers["x-iisnode-auth_user"];
                if (user) {
                    console.log(user);
                    statsdClient.increment("users." + user.replace(/\\/g, '_'));
                }
            }
        };
        next();
    };
}


原作者构思很巧妙,把res.end函数替换掉,这样就可以在每次完成HTTP request的时候,进行统计了。我这里的思路是,假如有req.route.path这个属性(这个可以过滤掉一些静态资源的访问),我就格式化一下key,然后发送给statsD。同时也增加2个计数器,一个是status_codes.*,一个是users.*。这个就完成了,还要做的一件事就是把中间件加入到expressJs里面:

var express = require('express')
  , http = require('http')
  , path = require('path')
  , util = require('util')
  , middlewares = require('./middlewares');

var app = express();
var SDC = new require('statsd-client');
var sdc = new SDC({ host: 'localhost', port: 8125, debug: false }).getChildClient('cer');

app.configure(function () {
    app.set('env', 'production');
    app.set('port', process.env.PORT || 80);
    app.set('views', __dirname + '/views');
    app.set('view engine', 'ejs');
    app.use(middlewares.statsdMiddleware(sdc));
    app.use(express.favicon());
    app.use(express.logger('dev'));
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(app.router);
    app.use(express.static(path.join(__dirname, 'public')));
    app.use(express.errorHandler());
});


这么简单,一切就OK了!接下来的事情就是在Dashboard里面做几个统计:

1. 统计1天内所有页面的访问次数:sumSeries(summarize(*.timers.cer.pages.*.count,"1d"))

2. 查看304状态每隔10秒的出现次数(statsD每隔10秒发送一次):stats_counts.cer.status_codes.304

3. 查看所有用户每隔10秒的访问次数:stats_counts.cer.users.*

4. 查看某一个页面每隔10秒的访问总量:*.timers.cer.pages.get_cer_weeklyCrashCount.count

5. 查看某一个页面每隔10秒的大渲染时间: *.timers.cer.pages.*.upper


然后保存这个dashboard为CER_SITE之后,每次就可以通过http://10.31.143.230/dashboard/#CER_SITE来访问了。

相关文章