zoukankan      html  css  js  c++  java
  • Graphite实战

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

    1. StatsD学习:http://blog.csdn.net/puncha/article/details/9083061
    2. 在Ubuntu Server 12.04 x64下安装Graphite: http://blog.csdn.net/puncha/article/details/9092765
    3. StatsD与Graphite联合作战:http://blog.csdn.net/puncha/article/details/9112293
    4. 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来访问了。




  • 相关阅读:
    ZAB 和 Paxos 算法的联系与区别?
    Spring支持的ORM?
    解释对象/关系映射集成模块?
    哪种依赖注入方式你建议使用,构造器注入,还是 Setter方法注入?
    我们能自己写一个容器类,然后使用 for-each 循环码?
    Struts2的Action中获取request对象的几种方式?
    Chroot 特性?
    String是最基本的数据类型吗?
    @Autowired 注解?
    比较HQL、Criteria、Native-SQL这三者做查询的区别,以及应该如何进行选择?
  • 原文地址:https://www.cnblogs.com/puncha/p/3876901.html
Copyright © 2011-2022 走看看