这里以监控内存使用率为例,写的一个简单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等格式查看。