總的而言,分三部分:
1.監控器(monitor.py
): 每秒獲取系統的四個cpu的使用率,存入數據庫。
2.路由器(app.py
): 響應頁面的ajax,獲取最新的一條或多條數據。
3.頁面(index.html
): 發出ajax請求,更新echarts圖表
一、監控器
使用了psutil庫,對系統進行監控。
import psutil
import sqlite3
import time
'''
說明:四個cpu使用率,顯然是臨時數據,所以最好用內存數據庫,如Redis等
但是這里強行使用sqlite3,不管了,哪個叫他是內置的呢?!
'''
db_name = 'mydb.db'
def create_db():
# 連接
conn = sqlite3.connect(db_name)
c = conn.cursor()
# 創建表
c.execute('''DROP TABLE IF EXISTS cpu''') # 刪除舊表,如果存在(因為這是臨時數據)
c.execute('''CREATE TABLE cpu (id INTEGER PRIMARY KEY AUTOINCREMENT, insert_time text,cpu1 float, cpu2 float, cpu3 float, cpu4 float)''')
# 關閉
conn.close()
def save_to_db(data):
'''參數data格式:['00:01',3.5, 5.9, 0.7, 29.6]'''
# 建立連接
conn = sqlite3.connect(db_name)
c = conn.cursor()
# 插入數據
c.execute('INSERT INTO cpu(insert_time,cpu1,cpu2,cpu3,cpu4) VALUES (?,?,?,?,?)', data)
# 提交!!!
conn.commit()
# 關閉連接
conn.close()
# 創建表
create_db()
# 通過循環,對系統進行監控
while True:
# 獲取系統cpu使用率(每隔1秒)
cpus = psutil.cpu_percent(interval=1, percpu=True)
# 獲取系統時間(只取分:秒)
t = time.strftime('%M:%S', time.localtime())
# 保存到數據庫
save_to_db((t, *cpus))
二、路由器
import sqlite3
from flask import Flask, request, render_template, jsonify
app = Flask(__name__)
def get_db():
db = sqlite3.connect('mydb.db')
db.row_factory = sqlite3.Row
return db
def query_db(query, args=(), one=False):
db = get_db()
cur = db.execute(query, args)
db.commit()
rv = cur.fetchall()
db.close()
return (rv[0] if rv else None) if one else rv
@app.route("/", methods=["GET"])
def index():
return render_template("index.html")
@app.route("/cpu", methods=["POST"])
def cpu():
if request.method == "POST":
res = query_db("SELECT * FROM cpu WHERE id>=(?)", args=(int(request.form['id'])+1,)) #返回1+個數據
return jsonify(insert_time = [x[1] for x in res],
cpu1 = [x[2] for x in res],
cpu2 = [x[3] for x in res],
cpu3 = [x[4] for x in res],
cpu4 = [x[5] for x in res]) # 返回json格式
if __name__ == "__main__":
app.run(debug=True)
三、頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ECharts3 Ajax</title>
<script src="{{ url_for('static', filename='jquery-3.1.1.js') }}"></script>
<script src="{{ url_for('static', filename='echarts.js') }}"></script>
</head>
<body>
<!--為ECharts准備一個具備大小(寬高)的Dom-->
<div id="main" style="height:500px;border:1px solid #ccc;padding:10px;"></div>
<script type="text/javascript">
//--- 折柱 ---
var myChart = echarts.init(document.getElementById('main'));
myChart.setOption({
title: {
text: '服務器系統監控'
},
tooltip: {},
legend: {
data:['cpu1','cpu2','cpu3','cpu4']
},
xAxis: {
data: []
},
yAxis: {},
series: [{
name: 'cpu1',
type: 'line',
data: []
},{
name: 'cpu2',
type: 'line',
data: []
},{
name: 'cpu3',
type: 'line',
data: []
},{
name: 'cpu4',
type: 'line',
data: []
}]
});
// 六個全局變量:插入時間、cpu1、cpu2、cpu3、cpu4、 哨兵(用於POST)
var insert_time = ["","","","","","","","","",""],
cpu1 = [0,0,0,0,0,0,0,0,0,0],
cpu2 = [0,0,0,0,0,0,0,0,0,0],
cpu3 = [0,0,0,0,0,0,0,0,0,0],
cpu4 = [0,0,0,0,0,0,0,0,0,0],
lastID = 0; // 哨兵,記錄上次數據表中的最后id +1(下次查詢只要>=lastID)
//准備好統一的 callback 函數
var update_mychart = function (data) { //data是json格式的response對象
myChart.hideLoading(); // 隱藏加載動畫
dataLength = data.insert_time.length; //取回的數據長度
lastID += dataLength; //哨兵,相應增加。
// 切片是能統一的關鍵!!
insert_time = insert_time.slice(dataLength).concat(data.insert_time); // 數組,先切片、再拼接
cpu1 = cpu1.slice(dataLength).concat(data.cpu1.map(parseFloat)); //注意map方法
cpu2 = cpu2.slice(dataLength).concat(data.cpu2.map(parseFloat));
cpu3 = cpu3.slice(dataLength).concat(data.cpu3.map(parseFloat));
cpu4 = cpu4.slice(dataLength).concat(data.cpu4.map(parseFloat));
// 填入數據
myChart.setOption({
xAxis: {
data: insert_time
},
series: [{
name: 'cpu1', // 根據名字對應到相應的系列
data: cpu1
},{
name: 'cpu2',
data: cpu2
},{
name: 'cpu3',
data: cpu3
},{
name: 'cpu4',
data: cpu4
}]
});
if (dataLength == 0){clearInterval(timeTicket);} //如果取回的數據長度為0,停止ajax
}
myChart.showLoading(); // 首次顯示加載動畫
// 異步加載數據 (首次,get,顯示6個數據)
$.get('/cpu').done(update_mychart);
// 異步更新數據 (以后,定時post,取回1個數據)
var timeTicket = setInterval(function () {
$.post('/cpu',{id: lastID}).done(update_mychart);
}, 3000);
</script>
</body>
</html>