这里以监控内存使用率为例,写的一个简单demo性程序,具体操作根据51reboot提供的教程写如下。

一、建库建表

创建falcon数据库:

1mysql> create database falcon character set utf8;
2Query OK, 1 row affected (0.00 sec)

创建内存监控使用的表stat,表结构如下:

 1CREATE TABLE `stat` (
 2  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 3  `host` varchar(256) DEFAULT NULL,
 4  `mem_free` int(11) DEFAULT NULL,
 5  `mem_usage` int(11) DEFAULT NULL,
 6  `mem_total` int(11) DEFAULT NULL,
 7  `load_avg` varchar(128) DEFAULT NULL,
 8  `time` bigint(11) DEFAULT NULL,
 9  PRIMARY KEY (`id`),
10  KEY `host` (`host`(255))
11) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

二、flask web端设置

首先我们设计一个web服务,实现如下功能:

  • 完成监控页面展示
  • 接受POST提交上来的数据
  • 提供json数据GET接口

具体框架结构图如下:

flask-monitor

目录结构如下:

1web
2├── flask_web.py
3└── templates
4    └── mon.html

flask_web代码如下:

 1import MySQLdb as mysql
 2import json
 3from flask import Flask, request, render_template
 4app = Flask(__name__)
 5db = mysql.connect(user="361way", passwd="123456", \
 6        db="falcon", charset="utf8")
 7db.autocommit(True)
 8c = db.cursor()
 9@app.route("/", methods=["GET", "POST"])
10def hello():
11    sql = ""
12    if request.method == "POST":
13        data = request.json
14        try:
15            sql = "INSERT INTO `stat` (`host`,`mem_free`,`mem_usage`,`mem_total`,`load_avg`,`time`) VALUES('%s', '%d', '%d', '%d', '%s', '%d')" % (data['Host'], data['MemFree'], data['MemUsage'], data['MemTotal'], data['LoadAvg'], int(data['Time']))
16            ret = c.execute(sql)
17        except mysql.IntegrityError:
18            pass
19        return "OK"
20    else:
21        return render_template("mon.html")
22@app.route("/data", methods=["GET"])
23def getdata():
24    c.execute("SELECT `time`,`mem_usage` FROM `stat`")
25    ones = [[i[0]*1000, i[1]] for i in c.fetchall()]
26    return "%s(%s);" % (request.args.get('callback'), json.dumps(ones))
27if __name__ == "__main__":
28    app.run(host="0.0.0.0", port=8888, debug=True)

这里使用的汇图JS为highcharts、highstock ,具体模板页面内容如下:

 1[root@91it templates]# cat mon.html
 2<title>memory monitor</title>
 3
 4<html>
 5    <head>
 6        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 7        <title>Highstock Example</title>
 8        <!-- <script type="text/javascript" src="{{ url_for('static', filename='jquery.min.js') }}"></script> -->
 9        <script type="text/javascript" src="http://ajax.useso.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
10        <style type="text/css">
11${demo.css}
12        </style>
13        <script type="text/javascript">
14$(function () {
15    $.getJSON('/data?callback=?', function (data) {
16        // Create the chart
17        $('#container').highcharts('StockChart', {
18            rangeSelector: {
19                inputEnabled: $('#container').width() > 480,
20                selected: 1
21            },
22            title: {
23                text: 'memory monitor'
24            },
25            series: [{
26                name: 'memory monitor',
27                data: data,
28                type: 'spline',
29                tooltip: {
30                    valueDecimals: 2
31                }
32            }]
33        });
34    });
35});
36        </script>
37    </head>
38    <body>
39<!-- <script src="{{ url_for('static', filename='highstock.js') }}"></script> -->
40<script src="http://cdnjs.cloudflare.com/ajax/libs/highstock/2.0.4/highstock.js"></script>
41<!-- <script src="{{ url_for('static', filename='exporting.js') }}"></script> -->
42<script src="http://code.highcharts.com/modules/exporting.js"></script>
43<div id="container" style="height: 400px"></div>
44    </body>
45</html>

注:这里的JS代码都直接使用互联网上的代码,如果主机无法连接互联网的,可以将上面的三段代取取下来,在templates 的同级目录创建static 目录,将下载下来的三个文件放到该目录,删除模板中三处引用javascript处的代码,使用当前注释的三段。

三、agent被监控端设置

web展示页面完成了,运行起来:python flask_web.py 监听在8888端口上。我们需要做一个agent来采集数据,并通过post方法请求flask_web页面,将数据上传写入数据库。这里以监控内存为例,具体监控代码如下:

 1#!/usr/bin/env python
 2#coding=utf-8
 3import inspect
 4import time
 5import urllib, urllib2
 6import json
 7import socket
 8class mon:
 9    def __init__(self):
10        self.data = {}
11    def getTime(self):
12        return str(int(time.time()) + 8 * 3600)
13    def getHost(self):
14        return socket.gethostname()
15    def getLoadAvg(self):
16        with open('/proc/loadavg') as load_open:
17            a = load_open.read().split()[:3]
18            return ','.join(a)
19    def getMemTotal(self):
20        with open('/proc/meminfo') as mem_open:
21            a = int(mem_open.readline().split()[1])
22            return a / 1024
23    def getMemUsage(self, noBufferCache=True):
24        if noBufferCache:
25            with open('/proc/meminfo') as mem_open:
26                T = int(mem_open.readline().split()[1])
27                F = int(mem_open.readline().split()[1])
28                B = int(mem_open.readline().split()[1])
29                C = int(mem_open.readline().split()[1])
30                return (T-F-B-C)/1024
31        else:
32            with open('/proc/meminfo') as mem_open:
33                a = int(mem_open.readline().split()[1]) - int(mem_open.readline().split()[1])
34                return a / 1024
35    def getMemFree(self, noBufferCache=True):
36        if noBufferCache:
37            with open('/proc/meminfo') as mem_open:
38                T = int(mem_open.readline().split()[1])
39                F = int(mem_open.readline().split()[1])
40                B = int(mem_open.readline().split()[1])
41                C = int(mem_open.readline().split()[1])
42                return (F+B+C)/1024
43        else:
44            with open('/proc/meminfo') as mem_open:
45                mem_open.readline()
46                a = int(mem_open.readline().split()[1])
47                return a / 1024
48    def runAllGet(self):
49        #自动获取mon类里的所有getXXX方法,用XXX作为key,getXXX()的返回值作为value,构造字典
50        for fun in inspect.getmembers(self, predicate=inspect.ismethod):
51            if fun[0][:3] == 'get':
52                self.data[fun[0][3:]] = fun[1]()
53        return self.data
54if __name__ == "__main__":
55    while True:
56        m = mon()
57        data = m.runAllGet()
58        print data
59        req = urllib2.Request("http://test.361way.com:8888", json.dumps(data), {'Content-Type': 'application/json'})
60        f = urllib2.urlopen(req)
61        response = f.read()
62        print response
63        f.close()
64        time.sleep(60)

nohup python moniItems.py >/dev/null 2>&1 &在被监控主机上运行,如果出于实验目的,想尽快的看到展示效果,可以将time.sleep(60) 改为time.sleep(2) ,这样每2秒就会取一次数据写入数据库。

访问 http://test.361way.com:8888 就可以看到我们的监控数据了:效果图如下

flask-highcharts

highcharts支持将按时间拖动,也支持按指定时间段查看。并且查看到的图片可以直接保存为png、jpg或pdf、csv等格式查看。