这里以监控内存使用率为例,写的一个简单demo性程序,具体操作根据51reboot提供的教程写如下。
一、建库建表
创建falcon数据库:
1
2
|
mysql> create database falcon character set utf8; Query OK, 1 row affected (0.00 sec) |
创建内存监控使用的表stat,表结构如下:
1
2
3
4
5
6
7
8
9
10
11
|
CREATE TABLE `stat` ( `id` int (11) unsigned NOT NULL AUTO_INCREMENT, `host` varchar (256) DEFAULT NULL , `mem_free` int (11) DEFAULT NULL , `mem_usage` int (11) DEFAULT NULL , `mem_total` int (11) DEFAULT NULL , `load_avg` varchar (128) DEFAULT NULL , ` time ` bigint (11) DEFAULT NULL , PRIMARY KEY (`id`), KEY `host` (`host`(255)) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8; |
二、flask web端设置
首先我们设计一个web服务,实现如下功能:
完成监控页面展示
接受POST提交上来的数据
提供json数据GET接口
具体框架结构图如下:
目录结构如下:
1
2
3
4
|
web ├── flask_web.py └── templates └── mon.html |
flask_web代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
import MySQLdb as mysql import json from flask import Flask, request, render_template app = Flask(__name__) db = mysql.connect(user = "361way" , passwd = "123456" , \ db = "falcon" , charset = "utf8" ) db.autocommit( True ) c = db.cursor() @app .route( "/" , methods = [ "GET" , "POST" ]) def hello(): sql = "" if request.method = = "POST" : data = request.json try : 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' ])) ret = c.execute(sql) except mysql.IntegrityError: pass return "OK" else : return render_template( "mon.html" ) @app .route( "/data" , methods = [ "GET" ]) def getdata(): c.execute( "SELECT `time`,`mem_usage` FROM `stat`" ) ones = [[i[ 0 ] * 1000 , i[ 1 ]] for i in c.fetchall()] return "%s(%s);" % (request.args.get( 'callback' ), json.dumps(ones)) if __name__ = = "__main__" : app.run(host = "0.0.0.0" , port = 8888 , debug = True ) |
这里使用的汇图JS为highcharts、highstock ,具体模板页面内容如下:
1
|
[root@91it templates] # cat mon.html |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
<title>memory monitor</title> <!DOCTYPE HTML> <html> <head> <meta http-equiv= "Content-Type" content= "text/html; charset=utf-8" > <title>Highstock Example</title> <!-- <script type= "text/javascript" src= "{{ url_for('static', filename='jquery.min.js') }}" ></script> --> <script type= "text/javascript" src= "http://ajax.useso.com/ajax/libs/jquery/1.8.2/jquery.min.js" ></script> <style type= "text/css" > ${demo.css} </style> <script type= "text/javascript" > $( function () { $.getJSON( '/data?callback=?' , function (data) { // Create the chart $( '#container' ).highcharts( 'StockChart' , { rangeSelector: { inputEnabled: $( '#container' ).width() > 480, selected: 1 }, title: { text: 'memory monitor' }, series: [{ name: 'memory monitor' , data: data, type: 'spline' , tooltip: { valueDecimals: 2 } }] }); }); }); </script> </head> <body> <!-- <script src= "{{ url_for('static', filename='highstock.js') }}" ></script> --> <script src= "http://cdnjs.cloudflare.com/ajax/libs/highstock/2.0.4/highstock.js" ></script> <!-- <script src= "{{ url_for('static', filename='exporting.js') }}" ></script> --> <script src= "http://code.highcharts.com/modules/exporting.js" ></script> <div id= "container" style= "height: 400px" ></div> </body> </html> |
注:这里的JS代码都直接使用互联网上的代码,如果主机无法连接互联网的,可以将上面的三段代取取下来,在templates 的同级目录创建static 目录,将下载下来的三个文件放到该目录,删除模板中三处引用javascript处的代码,使用当前注释的三段。
三、agent被监控端设置
web展示页面完成了,运行起来:python flask_web.py 监听在8888端口上。我们需要做一个agent来采集数据,并通过post方法请求flask_web页面,将数据上传写入数据库。这里以监控内存为例,具体监控代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
#!/usr/bin/env python #coding=utf-8 import inspect import time import urllib, urllib2 import json import socket class mon: def __init__( self ): self .data = {} def getTime( self ): return str ( int (time.time()) + 8 * 3600 ) def getHost( self ): return socket.gethostname() def getLoadAvg( self ): with open ( '/proc/loadavg' ) as load_open: a = load_open.read().split()[: 3 ] return ',' .join(a) def getMemTotal( self ): with open ( '/proc/meminfo' ) as mem_open: a = int (mem_open.readline().split()[ 1 ]) return a / 1024 def getMemUsage( self , noBufferCache = True ): if noBufferCache: with open ( '/proc/meminfo' ) as mem_open: T = int (mem_open.readline().split()[ 1 ]) F = int (mem_open.readline().split()[ 1 ]) B = int (mem_open.readline().split()[ 1 ]) C = int (mem_open.readline().split()[ 1 ]) return (T - F - B - C) / 1024 else : with open ( '/proc/meminfo' ) as mem_open: a = int (mem_open.readline().split()[ 1 ]) - int (mem_open.readline().split()[ 1 ]) return a / 1024 def getMemFree( self , noBufferCache = True ): if noBufferCache: with open ( '/proc/meminfo' ) as mem_open: T = int (mem_open.readline().split()[ 1 ]) F = int (mem_open.readline().split()[ 1 ]) B = int (mem_open.readline().split()[ 1 ]) C = int (mem_open.readline().split()[ 1 ]) return (F + B + C) / 1024 else : with open ( '/proc/meminfo' ) as mem_open: mem_open.readline() a = int (mem_open.readline().split()[ 1 ]) return a / 1024 def runAllGet( self ): #自动获取mon类里的所有getXXX方法,用XXX作为key,getXXX()的返回值作为value,构造字典 for fun in inspect.getmembers( self , predicate = inspect.ismethod): if fun[ 0 ][: 3 ] = = 'get' : self .data[fun[ 0 ][ 3 :]] = fun[ 1 ]() return self .data if __name__ = = "__main__" : while True : m = mon() data = m.runAllGet() print data req = urllib2.Request( "http://test.361way.com:8888" , json.dumps(data), { 'Content-Type' : 'application/json' }) f = urllib2.urlopen(req) response = f.read() print response f.close() time.sleep( 60 ) |
nohup python moniItems.py >/dev/null 2>&1 & 在被监控主机上运行,如果出于实验目的,想尽快的看到展示效果,可以将time.sleep(60) 改为time.sleep(2) ,这样每2秒就会取一次数据写入数据库。
访问 http://test.361way.com:8888 就可以看到我们的监控数据了:效果图如下
highcharts支持将按时间拖动,也支持按指定时间段查看。并且查看到的图片可以直接保存为png、jpg或pdf、csv等格式查看。