Graphite实战
这4个文章是一个系列的,关于如何配置 StatsD,Graphite以及如何使用两者来显示访问信息:
- StatsD学习:http://blog.csdn.net/puncha/article/details/9083061
- 在Ubuntu Server 12.04 x64下安装Graphite: http://blog.csdn.net/puncha/article/details/9092765
- StatsD与Graphite联合作战:http://blog.csdn.net/puncha/article/details/9112293
- Graphite实战:http://blog.csdn.net/puncha/article/details/9137001
在上次把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来访问了。