License: Attribution-NonCommercial-ShareAlike 4.0 International
本文出自 Suzf Blog。 如未注明,均为 SUZF.NET 原创。
转载请注明:http://suzf.net/post/854
本文主要讲述的是: 如何使用 Flask + Mysql + Highcharts 构建一个简单的监控系统 以监控系统内存为例的简易 Demo,文档参考 运维之路 的教程。 整体思路是:
- 收集数据
- 存储数据
- 展示数据
建库建表
mysql> select database(); +------------+ | database() | +------------+ | highcharts | +------------+ 1 row in set (0.00 sec) mysql> show create table stat; +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | stat | CREATE TABLE `stat` ( `id` int(20) unsigned NOT NULL AUTO_INCREMENT, `host` varchar(60) DEFAULT NULL, `mem_free` int(11) DEFAULT NULL, `mem_usage` int(11) DEFAULT NULL, `mem_total` int(11) DEFAULT NULL, `load_avg` varchar(23) DEFAULT NULL, `time` bigint(11) DEFAULT NULL, PRIMARY KEY (`id`), ) ENGINE=InnoDB AUTO_INCREMENT=132 DEFAULT CHARSET=utf8 | +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
首先我们来看一下 目录结构
$tree . . ├── flask_web_agent.py ├── flask_web.py ├── static │ └── js │ ├── exporting.js │ ├── highstock.js │ └── jquery-1.8.3.min.js └── templates └── index.html 3 directories, 6 files
唠叨直接略过,直接上代码 当然这需要有一些 Python Flask html js 的基础 Agent
#/usr/bin/env python # -*- encoding=utf-8 -*- import time import json import socket import urllib, urllib2 import inspect class moon: 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_f: item = load_f.read().split()[:3] return ','.join(item) def getMemTotal(self): with open('/proc/meminfo') as mem_f: item = int(mem_f.readline().split()[1]) return item / 1024 def getMemUsage(self): with open('/proc/meminfo') as mem_f: item = int(mem_f.readline().split()[1]) - int(mem_f.readline().split()[1]) return item / 1024 def getMemFree(self): with open('/proc/meminfo') as mem_f: mem_f.readline() item = int(mem_f.readline().split()[1]) return item / 1024 def runAllGet(self): '''Auto get method to build dict''' 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 = moon() data = m.runAllGet() try: # req = urllib2.Request("http://172.16.3.100:5000", json.dumps(data), {'Content-Type': 'application/json'}) # f = urllib2.urlopen(req) url = 'http://172.16.3.100:5000' req = urllib2.Request(url) req.add_header("Content-Type","application/json") f = urllib2.urlopen(req, json.dumps(data)) response = f.read() print response f.close() except urllib2.HTTPError,e: print e.code print e.read() time.sleep(60)
Server
#!/usr/bin/env python # -*- encoding: utf-8 -*- import json import MySQLdb as mysql from flask import Flask, request, render_template, g from flask.ext.script import Manager ''' Create my app ''' app = Flask(__name__) manager = Manager(app) def connect_db(): ''' Connect to database ''' conn = mysql.connect(user="Robin", passwd="", db="highcharts", host="127.0.0.1", charset="utf8") return conn @app.before_request def before_request(): ''' Make sure we connect the db before each connect''' g.db = connect_db() @app.after_request def after_request(response): g.db.close() return response @app.route("/", methods=["GET", "POST"]) def hello(): query = "" cur = g.db.cursor() if request.method == "POST": data = request.json try: query = "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'])) cur.execute(query) cur.close() g.db.commit() except mysql.Error, e: print "Mysql Error %d: %s" % (e.args[0], e.args[1]) return "Saved data successed." else: return render_template("index.html") @app.route("/data/<item>", methods=["GET"]) def getdata(item): cur = g.db.cursor() query = "SELECT `time`,%s FROM `stat`" % item cur.execute(query) ones = [[i[0] * 1000, i[1]] for i in cur.fetchall()] cur.close() return "%s(%s);" % (request.args.get('callback'), json.dumps(ones)) if __name__ == "__main__": # app.run(host="0.0.0.0", port=666, debug=True) manager.run()
Highcharts 相关源码 可以直接从官网下载: Highcharts 相关Demo 点击这里 获取 使用highstock 绘图 ,具体模板页面内容如下:
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <!-- <meta http-equiv="refresh" content="20">--> <title>Flask demo - suzf.net</title> <script src='/static/js/jquery-1.8.3.min.js'></script> <script src='/static/js/highstock.js'></script> <script src='/static/js/exporting.js'></script> </head> <body> <div id="container" style="height: 500px; width: 700px; margin: 0 auto;"> <script type="text/javascript"> $(function () { var seriesOptions = [], seriesCounter = 0, names = ['MEM_FREE', 'MEM_USAGE', 'MEM_TOTAL']; /** * Create the chart when all data is loaded * @returns {undefined} */ function createChart() { $('#container').highcharts('StockChart', { rangeSelector: { selected: 4 }, title: { text: 'Mem info', x: -20 }, yAxis: { labels: { formatter: function () { return (this.value > 0 ? ' + ' : '') + this.value + '%'; } }, plotLines: [{ value: 0, width: 2, color: 'silver' }] }, plotOptions: { series: { compare: 'percent' } }, credits:{ enabled:true, text:'suzf.net', href:'http://suzf.net', style: { cursor: 'pointer', color: 'green', fontSize: '10px' } }, tooltip: { pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>', valueDecimals: 2 }, series: seriesOptions }); } $.each(names, function (i, name) { $.getJSON('http://172.16.3.100:5000/data/' + name.toLowerCase() + '?callback=?', function (data) { seriesOptions[i] = { name: name, data: data }; // As we're loading the data asynchronously, we don't know what order it will arrive. So // we keep a counter and create the chart when all the data is loaded. seriesCounter += 1; if (seriesCounter === names.length) { createChart(); } }); }); }); </script> </div> </body> </html>
所有工作准备就绪,执行程序 开始测试:
python flask_web.py runserver -h 0.0.0.0 & python flask_web_agent.py &