本人第一次写blog,努力中。
言归正传。这篇博客完成的工作是在网页上以图表的方式,显示cpu、内存、流量等资源信息。先上一副效果图:
使用工具与环境:
web架构:基于python的django
画图工具:基于js的画图工具 highcharts 链接http://www.highcharts.com/
页面的基本显示由html代码负责,没啥可说的。html代码如下:
<!DOCTYPE html>
<htmllang="en">
<head>
<title>计算机资源视图</title>
<metahttp-equiv="Content-Type"content="text/html; charset=utf-8">
<linkrel="stylesheet"type="text/css"href="/media/css/basic.css"/>
<scripttype="text/javascript"src="/media/js/jquery-1.4.2.min.js"></script>
<scripttype="text/javascript"src="/media/jschart/highcharts.js"></script>
<scripttype="text/javascript"src="/media/jschart/modules/exporting.js"></script>
<scripttype="text/javascript"src="/media/mjs/physical.js"></script>
</head>
<body>
<!-- #charts -->
<charts>
<divclass="charts">
<divclass="chartshead"><span>主控节点 资源视图</span></div>
<divid="cpu"></div>
<divid="mem"></div>
<divid="rx"></div>
<divid="tx"></div>
<brstyle="clear:both"/>
</div>
</charts>
</body>
</html>
画图主要是使用js代码,使用ajax机制定时异步获得数据,然后在图上添加数据点。每5秒添加一个新点。js代码如下:
var chart_cpu;
var chart_mem;
var chart_rx;
var chart_tx;
var maxmem;
var mem;
var pre_cpu = 0
var pre_cpu_total = 0
var pre_rb = 0
var pre_tb = 0
var flag = 1
var timeout = 5000
//var para = window.location.search;
//更新
function requestData() {
var stime = new Date();
$.ajax({
//async: false,
url:'/ajax/jsonmgt',
success: function(point) {
// add 4 points
var x = (new Date()).getTime() + 8*3600*1000; // 当前时间
var out = eval("(" + point + ")")
//var out = eval( point )
maxmem = out[0]
mem = out[1]
cpu_use = out[2]
cpu_total = out[3]
rb = out[4]
tb = out[5]
memrate = mem/maxmem * 100
//cpu
d_cpu = cpu_use - pre_cpu
d_cpu_total = cpu_total - pre_cpu_total
pre_cpu = cpu_use
pre_cpu_total = cpu_total
cpurate = d_cpu/d_cpu_total *100
if(cpurate == 100)
cpurate = 99.9
//rb tb
d_rb = rb - pre_rb
d_tb = tb - pre_tb
pre_rb = rb
pre_tb = tb
rkb = d_rb/1024
tkb = d_tb/1024
if(flag == 1){
rkb = 0
tkb = 0
cpurate = 0
memrate = 0
flag =0
}
//add points
chart_cpu.series[0].addPoint([x,cpurate], true, true);
chart_mem.series[0].addPoint([x,memrate], true, true);
chart_rx.series[0].addPoint([x,rkb], true, true);
chart_tx.series[0].addPoint([x,tkb], true, true);
var etime = new Date();
d_date=etime.getTime()-stime.getTime();
setTimeout(requestData, timeout - d_date);
},
cache: false
});
}
//cpu
$(document).ready(function(){
chart_cpu = new Highcharts.Chart({
chart: {
renderTo: 'cpu', //图表放置的容器,DIV
defaultSeriesType: 'spline', //图表类型为曲线图
backgroundColor:'#DFFDFD',
events: {
//load: requestData
}
},
title: {
text: 'CPU负载'//图表标题
},
xAxis: { //设置X轴
title: { text: '时间' },
type: 'datetime', //X轴为日期时间类型
tickPixelInterval: 150 //X轴标签间隔
},
yAxis: { //设置Y轴
title: { text: 'CPU使用率' },
labels: {
formatter: function() {
returnthis.value +'%';
}
},
max: 100, //Y轴最大值
min: 0 //Y轴最小值
},
tooltip: {//当鼠标悬置数据点时的提示框
formatter: function() { //格式化提示信息
return Highcharts.dateFormat('%H:%M:%S', this.x) +' '+
Highcharts.numberFormat(this.y, 2)+'%';
}
},
legend: {
enabled: false//设置图例不可见
},
exporting: {
enabled: false//设置导出按钮不可用
},
series: [{
data: (function() { //设置默认数据,
var data = [],
time = (new Date()).getTime() + 8*3600*1000,
i;
for (i = -19; i < 0; i++) {
data.push({
x: time + i * timeout,
y: 0 * 100
});
}
return data;
})()
}]
});
});
//mem
$(function() {
chart_mem = new Highcharts.Chart({
chart: {
renderTo: 'mem', //图表放置的容器,DIV
defaultSeriesType: 'spline', //图表类型为曲线图
backgroundColor:'#DFFDFD',
events: {
}
},
title: {
text: '内存负载'//图表标题
},
xAxis: { //设置X轴
title: { text: '时间' },
type: 'datetime', //X轴为日期时间类型
tickPixelInterval: 150 //X轴标签间隔
},
yAxis: { //设置Y轴
title: { text: '内存使用记录' },
labels: {
formatter: function() {
returnthis.value + '%';
}
},
max: 100, //Y轴最大值
min: 0 //Y轴最小值
},
tooltip: {//当鼠标悬置数据点时的提示框
formatter: function() { //格式化提示信息
return Highcharts.dateFormat('%H:%M:%S', this.x) +' '+
Highcharts.numberFormat(this.y, 2) + '%' + ' ' +
Highcharts.numberFormat(mem,0) + 'MB';
}
},
legend: {
enabled: false//设置图例不可见
},
exporting: {
enabled: false//设置导出按钮不可用
},
series: [{
data: (function() { //设置默认数据,
var data = [],
time = (new Date()).getTime()+8*3600*1000,
i;
for (i = -19; i < 0; i++) {
data.push({
x: time + i * timeout,
y: 0
});
}
return data;
})()
}]
});
});
//rx
$(function() {
chart_rx = new Highcharts.Chart({
chart: {
renderTo: 'rx', //图表放置的容器,DIV
defaultSeriesType: 'spline', //图表类型为曲线图
backgroundColor:'#DFFDFD', //背景颜色
events: {
}
},
title: {
text: '网络接收流量'//图表标题
},
xAxis: { //设置X轴
title: { text: '时间' },
type: 'datetime', //X轴为日期时间类型
tickPixelInterval: 150 //X轴标签间隔
},
yAxis: { //设置Y轴
title: { text: '接收网络流量' },
labels: {
formatter: function() {
returnthis.value +'kb/s';
}
},
//max: 200, //Y轴最大值
min: 0 //Y轴最小值
},
tooltip: {//当鼠标悬置数据点时的提示框
formatter: function() { //格式化提示信息
return Highcharts.dateFormat('%H:%M:%S', this.x) +' '+
Highcharts.numberFormat(this.y, 2)+'kb/s';
}
},
legend: {
enabled: false//设置图例不可见
},
exporting: {
enabled: false//设置导出按钮不可用
},
series: [{
data: (function() { //设置默认数据,
var data = [],
time = (new Date()).getTime() + 8*3600*1000,
i;
for (i = -19; i < 0; i++) {
data.push({
x: time + i * timeout,
y: 0
});
}
return data;
})()
}]
});
});
//tx
$(function() {
chart_tx = new Highcharts.Chart({
chart: {
renderTo: 'tx', //图表放置的容器,DIV
defaultSeriesType: 'spline', //图表类型为曲线图
backgroundColor:'#DFFDFD',
events: {
load: requestData
}
},
title: {
text: '网络发送流量'//图表标题
},
xAxis: { //设置X轴
title: { text: '时间' },
type: 'datetime', //X轴为日期时间类型
tickPixelInterval: 150 //X轴标签间隔
},
yAxis: { //设置Y轴
title: { text: '发送网络流量' },
labels: {
formatter: function() {
returnthis.value +'kb/s';
}
},
//max: 200, //Y轴最大值
min: 0 //Y轴最小值
},
tooltip: {//当鼠标悬置数据点时的提示框
formatter: function() { //格式化提示信息
return Highcharts.dateFormat('%H:%M:%S', this.x) +' '+
Highcharts.numberFormat(this.y, 2)+'kb/s';
}
},
legend: {
enabled: false//设置图例不可见
},
exporting: {
enabled: false//设置导出按钮不可用
},
series: [{
data: (function() { //设置默认数据,
var data = [],
time = (new Date()).getTime() + 8*3600*1000,
i;
for (i = -19; i < 0; i++) {
data.push({
x: time + i * timeout,
y: 0
});
}
return data;
})()
}]
});
})
使用ajax,就需要有数据源定期提供数据。使用c语言写一个程序(取名mgtinfo.c)抓取瞬时的cpu、内存、流量。代码如下:
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
typedefstruct//定义一个cpu occupy的结构体
{
char name[20]; //定义一个char类型的数组名name有20个元素
long user; //定义一个无符号的int类型的user
long nice; //定义一个无符号的int类型的nice
long system;//定义一个无符号的int类型的system
long idle; //定义一个无符号的int类型的idle
}CPU_OCCUPY;
typedefstruct//定义一个mem occupy的结构体
{
char name[20]; //定义一个char类型的数组名name有20个元素
long total;
//char name2[20];
char unit[20];
long free;
long buffers;
long cached;
}MEM_OCCUPY;
typedefstruct//定义一个cpu occupy的结构体
{
char name[20]; //定义一个char类型的数组名name有20个元素
long rb, rpkt, r_err, r_drop, r_fifo, r_frame, r_compr, r_mcast;
long tb, tpkt, t_err, t_drop, t_fifo, t_coll, t_carrier, t_compr;
}NET_OCCUPY;
int get_memoccupy (MEM_OCCUPY *mem) //对无类型get函数含有一个形参结构体类弄的指针O
{
FILE *fd;
int n;
char buf[256];
MEM_OCCUPY *m;
m=mem;
long MemFree, Buffers, Cached;
fd = fopen ("/proc/meminfo", "r");
fgets (buf, sizeof(buf), fd);
sscanf (buf, "%s %ld %s", &m->name, &m->total, &m->unit);
fgets (buf, sizeof(buf), fd);
sscanf (buf, "%s %ld %s", m->name, &m->free, m->unit);
fgets (buf, sizeof(buf), fd);
sscanf (buf, "%s %ld %s", m->name, &m->buffers, m->unit);
fgets (buf, sizeof(buf), fd);
sscanf (buf, "%s %ld %s", m->name, &m->cached, m->unit);
fclose(fd); //关闭文件fd
return 0;
}
int get_cpuoccupy (CPU_OCCUPY *cpust) //对无类型get函数含有一个形参结构体类弄的指针O
{
FILE *fd;
int n;
char buf[256];
CPU_OCCUPY *cpu_occupy;
cpu_occupy=cpust;
if ((fd = fopen ("/proc/stat", "r")) != NULL){
while (fgets (buf, sizeof(buf), fd)){
if( *buf == 'c' && *(buf + 1) == 'p') break;
}
fclose (fd);
}
else
printf("read file failed\n");
sscanf (buf, "cpu %ld %ld %ld %ld", &cpu_occupy->user, &cpu_occupy->nice,&cpu_occupy->system, &cpu_occupy->idle);
//printf("%ld\n", cpu_occupy->user);
return 0;
}
int get_netoccupy (NET_OCCUPY *net) //对无类型get函数含有一个形参结构体类弄的指针O
{
FILE *fd;
char buf[256];
NET_OCCUPY *net_occupy;
net_occupy = net;
//long MemFree, Buffers, Cached;
fd = fopen ("/proc/net/dev", "r");
fgets (buf, sizeof(buf), fd);
fgets (buf, sizeof(buf), fd);
fgets (buf, sizeof(buf), fd);
fgets (buf, sizeof(buf), fd);
//printf("%s",buf);
sscanf (buf, "%s %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld", &net_occupy->name, &net_occupy->rb ,&net_occupy->rpkt, &net_occupy->r_err, &net_occupy->r_drop, &net_occupy->r_fifo ,&net_occupy->r_frame, &net_occupy->r_compr, &net_occupy->r_mcast, &net_occupy->tb, &net_occupy->tpkt);
fclose(fd); //关闭文件fd
return 0;
}
int cal_cpuoccupy (CPU_OCCUPY *o, CPU_OCCUPY *n)
{
unsigned long od, nd;
unsigned long id, sd;
int cpu_use = 0;
od = (unsigned long) (o->user + o->nice + o->system +o->idle);//第一次(用户+优先级+系统+空闲)的时间再赋给od
nd = (unsigned long) (n->user + n->nice + n->system +n->idle);//第二次(用户+优先级+系统+空闲)的时间再赋给od
id = (unsigned long) (n->user - o->user); //用户第一次和第二次的时间之差再赋给id
sd = (unsigned long) (n->system - o->system);//系统第一次和第二次的时间之差再赋给sd
if((nd-od) != 0)
cpu_use = (int)((sd+id)*10000)/(nd-od); //((用户+系统)乖100)除(第一次和第二次的时间差)再赋给g_cpu_used
else cpu_use = 0;
return cpu_use;
}
int main()
{
CPU_OCCUPY cpu_stat;
MEM_OCCUPY mem_stat;
NET_OCCUPY net_stat;
long cpu_use, cpu_total;
//获取内存
get_memoccupy ((MEM_OCCUPY *)&mem_stat);
//第一次获取cpu使用情况
get_cpuoccupy((CPU_OCCUPY *)&cpu_stat);
cpu_use = cpu_stat.user + cpu_stat.nice + cpu_stat.system;
cpu_total=cpu_stat.user + cpu_stat.nice + cpu_stat.system + cpu_stat.idle;
//printf("%ld,%ld,%ld,%ld\n",cpu_stat.user,cpu_stat.nice,cpu_stat.system,cpu_stat.idle);
get_netoccupy((NET_OCCUPY *)&net_stat);
printf("%ld,%ld,%ld,%ld,%ld,%ld\n",mem_stat.total/1024,(mem_stat.total-mem_stat.free-mem_stat.buffers-mem_stat.cached)/1024,cpu_use,cpu_total,net_stat.rb,net_stat.tb);
return 0;
}
在django中,需要写一个函数jsonmgt,作为ajax请求的响应。每次执行,jsonmgt调用mgtinfo.c,获得瞬时cpu、内存、流量后,以json数据形式返回给页面。页面再用上面贴的js代码添加数据点绘图。
# time data
def jsonmgt( request ):
print"calulate data"
cmd="cmd/./mgtinfo"
output = os.popen(cmd,'r')
ret = output.read()
info = ret.split(',')
maxmem = string.atof(info[0])
mem = string.atof(info[1])
cpu_use = string.atof(info[2])
cpu_total = string.atof(info[3])
rb = string.atof(info[4])
tb = string.atof(info[5])
output.close()
data = [maxmem,mem,cpu_use,cpu_total,rb,tb]
data = simplejson.dumps( data, cls = QuerySetEncoder )
return HttpResponse( data )
# django ajax
class QuerySetEncoder( simplejson.JSONEncoder ):
"""
Encoding QuerySet into JSON format.
"""
def default( self, object ):
try:
return serializers.serialize( "python", object,ensure_ascii = False )
except:
return simplejson.JSONEncoder.default( self, object )