市面上有很多开源的监控系统:Cacti、nagios、zabbix。感觉都不符合我的需求,为什么不自己做一个呢
用Python两个小时徒手撸了一个简易的监控系统,给大家分享一下,希望能对大家有所启发
首先数据库建表
建立一个数据库“falcon”,建表语句如下:
1 CREATE 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;
首先我们设计一个web服务,实现如下功能:
- 完成监控页面展示
- 接受POST提交上来的数据
- 提供json数据GET接口
目录结构如下:
web
├── flask_web.py
└── templates
└── mon.html
flask_web.py
1 import MySQLdb as mysql
2 import json
3 from flask import Flask, request, render_template
4 app = Flask(__name__)
5 db = mysql.connect(user="root", passwd="*******", \
6 db="falcon", charset="utf8")
7 db.autocommit(True)
8 c = db.cursor()
9
10 @app.route("/", methods=["GET", "POST"])
11 def hello():
12 sql = ""
13 if request.method == "POST":
14 data = request.json
15 try:
16 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']))
17 ret = c.execute(sql)
18 except mysql.IntegrityError:
19 pass
20 return "OK"
21 else:
22 return render_template("mon.html")
23
24 @app.route("/data", methods=["GET"])
25 def getdata():
26 c.execute("SELECT `time`,`mem_usage` FROM `stat`")
27 ones = [[i[0]*1000, i[1]] for i in c.fetchall()]
28 return "%s(%s);" % (request.args.get('callback'), json.dumps(ones))
29
30
31 if __name__ == "__main__":
32 app.run(host="0.0.0.0", port=8888, debug=True)
这个template页面是我抄的highstock的示例,mon.html
简单起见我们只展示mem_usage信息到页面上
1 <title>51reboot.com</title>
2 <!DOCTYPE HTML>
3 <html>
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Highstock Example</title>
7
8 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
9 <style type="text/css">
10 ${demo.css}
11 </style>
12 <script type="text/javascript">
13 $(function () {
14 $.getJSON('/data?callback=?', function (data) {
15
16 // Create the chart
17 $('#container').highcharts('StockChart', {
18
19 rangeSelector: {
20 inputEnabled: $('#container').width() > 480,
21 selected: 1
22 },
23
24 title: {
25 text: 'yyf-china.com'
26 },
27
28 series: [{
29 name: 'yyf-china.com',
30 data: data,
31 type: 'spline',
32 tooltip: {
33 valueDecimals: 2
34 }
35 }]
36 });
37 });
38 });
39 </script>
40 </head>
41 <body>
42 <script src="http://cdnjs.cloudflare.com/ajax/libs/highstock/2.0.4/highstock.js"></script>
43 <script src="http://code.highcharts.com/modules/exporting.js"></script>
44
45
46 <div id="container" style="height: 400px"></div>
47 </body>
48 </html>
web展示页面完成了,运行起来:
python flask_web.py 监听在8888端口上
我们需要做一个agent来采集数据,并上传数据库
moniItems.py
1 #!/usr/bin/env python
2 import inspect
3 import time
4 import urllib, urllib2
5 import json
6 import socket
7
8 class mon:
9 def __init__(self):
10 self.data = {}
11
12 def getTime(self):
13 return str(int(time.time()) + 8 * 3600)
14
15 def getHost(self):
16 return socket.gethostname()
17
18 def getLoadAvg(self):
19 with open('/proc/loadavg') as load_open:
20 a = load_open.read().split()[:3]
21 return ','.join(a)
22
23 def getMemTotal(self):
24 with open('/proc/meminfo') as mem_open:
25 a = int(mem_open.readline().split()[1])
26 return a / 1024
27
28 def getMemUsage(self, noBufferCache=True):
29 if noBufferCache:
30 with open('/proc/meminfo') as mem_open:
31 T = int(mem_open.readline().split()[1])
32 F = int(mem_open.readline().split()[1])
33 B = int(mem_open.readline().split()[1])
34 C = int(mem_open.readline().split()[1])
35 return (T-F-B-C)/1024
36 else:
37 with open('/proc/meminfo') as mem_open:
38 a = int(mem_open.readline().split()[1]) - int(mem_open.readline().split()[1])
39 return a / 1024
40
41 def getMemFree(self, noBufferCache=True):
42 if noBufferCache:
43 with open('/proc/meminfo') as mem_open:
44 T = int(mem_open.readline().split()[1])
45 F = int(mem_open.readline().split()[1])
46 B = int(mem_open.readline().split()[1])
47 C = int(mem_open.readline().split()[1])
48 return (F+B+C)/1024
49 else:
50 with open('/proc/meminfo') as mem_open:
51 mem_open.readline()
52 a = int(mem_open.readline().split()[1])
53 return a / 1024
54
55 def runAllGet(self):
56 #自动获取mon类里的所有getXXX方法,用XXX作为key,getXXX()的返回值作为value,构造字典
57 for fun in inspect.getmembers(self, predicate=inspect.ismethod):
58 if fun[0][:3] == 'get':
59 self.data[fun[0][3:]] = fun[1]()
60 return self.data
61
62 if __name__ == "__main__":
63 while True:
64 m = mon()
65 data = m.runAllGet()
66 print data
67 req = urllib2.Request("http://yyf-china.com:8888", json.dumps(data), {'Content-Type': 'application/json'})
68 f = urllib2.urlopen(req)
69 response = f.read()
70 print response
71 f.close()
72 time.sleep(60)
nohup python moniItems.py >/dev/null 2>&1 & 运行起来
访问 http://yyf-china.com:8888 就可以看到我们的监控数据的效果图