HTML
<script type="text/javascript" src="../static/js/jquery-1.8.0.min.js"></script>
<script src="../static/js/highcharts.js"></script>
<script language='javascript' src='../../src/lib/binaryXHR.js'></script>
<script language='javascript' src='../../src/lib/rrdFile.js'></script>
<script type="text/javascript" src="../static/js/get_cpu_mem_data.js"></script>
<script src="../static/js/highcharts.js"></script>
<script type="text/javascript" src="../static/js/cpu_memory.js"></script>
<div class="clearfix">
<div id="container" style="min-width: 550px; height: 200px; margin: 0 auto"></div>
</div>
js
binaryXHR.js
/*
* BinaryFile over XMLHttpRequest
* Part of the javascriptRRD package
* Copyright (c) 2009 Frank Wuerthwein, [email protected]
* MIT License [http://www.opensource.org/licenses/mit-license.php]
*
* Original repository: http://javascriptrrd.sourceforge.net/
*
* Based on:
* Binary Ajax 0.1.5
* Copyright (c) 2008 Jacob Seidelin, [email protected], http://blog.nihilogic.dk/
* MIT License [http://www.opensource.org/licenses/mit-license.php]
*/
// ============================================================
// Exception class
function InvalidBinaryFile(msg) {
this.message=msg;
this.name="Invalid BinaryFile";
}
// pretty print
InvalidBinaryFile.prototype.toString = function() {
return this.name + ': "' + this.message + '"';
}
// =====================================================================
// BinaryFile class
// Allows access to element inside a binary stream
function BinaryFile(strData, iDataOffset, iDataLength) {
var data = strData;
var dataOffset = iDataOffset || 0;
var dataLength = 0;
// added
var doubleMantExpHi=Math.pow(2,-28);
var doubleMantExpLo=Math.pow(2,-52);
var doubleMantExpFast=Math.pow(2,-20);
var switch_endian = false;
this.getRawData = function() {
return data;
}
if (typeof strData == "string") {
dataLength = iDataLength || data.length;
this.getByteAt = function(iOffset) {
return data.charCodeAt(iOffset + dataOffset) & 0xFF;
}
} else if (typeof strData == "unknown") {
dataLength = iDataLength || IEBinary_getLength(data);
this.getByteAt = function(iOffset) {
return IEBinary_getByteAt(data, iOffset + dataOffset);
}
} else {
throw new InvalidBinaryFile("Unsupported type " + (typeof strData));
}
this.getEndianByteAt = function(iOffset,width,delta) {
if (this.switch_endian)
return this.getByteAt(iOffset+width-delta-1);
else
return this.getByteAt(iOffset+delta);
}
this.getLength = function() {
return dataLength;
}
this.getSByteAt = function(iOffset) {
var iByte = this.getByteAt(iOffset);
if (iByte > 127)
return iByte - 256;
else
return iByte;
}
this.getShortAt = function(iOffset) {
var iShort = (this.getEndianByteAt(iOffset,2,1) << 8) + this.getEndianByteAt(iOffset,2,0)
if (iShort < 0) iShort += 65536;
return iShort;
}
this.getSShortAt = function(iOffset) {
var iUShort = this.getShortAt(iOffset);
if (iUShort > 32767)
return iUShort - 65536;
else
return iUShort;
}
this.getLongAt = function(iOffset) {
var iByte1 = this.getEndianByteAt(iOffset,4,0),
iByte2 = this.getEndianByteAt(iOffset,4,1),
iByte3 = this.getEndianByteAt(iOffset,4,2),
iByte4 = this.getEndianByteAt(iOffset,4,3);
var iLong = (((((iByte4 << 8) + iByte3) << 8) + iByte2) << 8) + iByte1;
if (iLong < 0) iLong += 4294967296;
return iLong;
}
this.getSLongAt = function(iOffset) {
var iULong = this.getLongAt(iOffset);
if (iULong > 2147483647)
return iULong - 4294967296;
else
return iULong;
}
this.getStringAt = function(iOffset, iLength) {
var aStr = [];
for (var i=iOffset,j=0;i<iOffset+iLength;i++,j++) {
aStr[j] = String.fromCharCode(this.getByteAt(i));
}
return aStr.join("");
}
// Added
this.getCStringAt = function(iOffset, iMaxLength) {
var aStr = [];
for (var i=iOffset,j=0;(i<iOffset+iMaxLength) && (this.getByteAt(i)>0);i++,j++) {
aStr[j] = String.fromCharCode(this.getByteAt(i));
}
return aStr.join("");
}
// Added
this.getDoubleAt = function(iOffset) {
var iByte1 = this.getEndianByteAt(iOffset,8,0),
iByte2 = this.getEndianByteAt(iOffset,8,1),
iByte3 = this.getEndianByteAt(iOffset,8,2),
iByte4 = this.getEndianByteAt(iOffset,8,3),
iByte5 = this.getEndianByteAt(iOffset,8,4),
iByte6 = this.getEndianByteAt(iOffset,8,5),
iByte7 = this.getEndianByteAt(iOffset,8,6),
iByte8 = this.getEndianByteAt(iOffset,8,7);
var iSign=iByte8 >> 7;
var iExpRaw=((iByte8 & 0x7F)<< 4) + (iByte7 >> 4);
var iMantHi=((((((iByte7 & 0x0F) << 8) + iByte6) << 8) + iByte5) << 8) + iByte4;
var iMantLo=((((iByte3) << 8) + iByte2) << 8) + iByte1;
if (iExpRaw==0) return 0.0;
if (iExpRaw==0x7ff) return undefined;
var iExp=(iExpRaw & 0x7FF)-1023;
var dDouble = ((iSign==1)?-1:1)*Math.pow(2,iExp)*(1.0 + iMantLo*doubleMantExpLo + iMantHi*doubleMantExpHi);
return dDouble;
}
// added
// Extracts only 4 bytes out of 8, loosing in precision (20 bit mantissa)
this.getFastDoubleAt = function(iOffset) {
var iByte5 = this.getEndianByteAt(iOffset,8,4),
iByte6 = this.getEndianByteAt(iOffset,8,5),
iByte7 = this.getEndianByteAt(iOffset,8,6),
iByte8 = this.getEndianByteAt(iOffset,8,7);
var iSign=iByte8 >> 7;
var iExpRaw=((iByte8 & 0x7F)<< 4) + (iByte7 >> 4);
var iMant=((((iByte7 & 0x0F) << 8) + iByte6) << 8) + iByte5;
if (iExpRaw==0) return 0.0;
if (iExpRaw==0x7ff) return undefined;
var iExp=(iExpRaw & 0x7FF)-1023;
var dDouble = ((iSign==1)?-1:1)*Math.pow(2,iExp)*(1.0 + iMant*doubleMantExpFast);
return dDouble;
}
this.getCharAt = function(iOffset) {
return String.fromCharCode(this.getByteAt(iOffset));
}
}
document.write(
"<script type='text/vbscript'>\r\n"
+ "Function IEBinary_getByteAt(strBinary, iOffset)\r\n"
+ " IEBinary_getByteAt = AscB(MidB(strBinary,iOffset+1,1))\r\n"
+ "End Function\r\n"
+ "Function IEBinary_getLength(strBinary)\r\n"
+ " IEBinary_getLength = LenB(strBinary)\r\n"
+ "End Function\r\n"
+ "</script>\r\n"
);
// ===============================================================
// Load a binary file from the specified URL
// Will return an object of type BinaryFile
function FetchBinaryURL(url) {
var request = new XMLHttpRequest();
request.open("GET", url,false);
try {
request.overrideMimeType('text/plain; charset=x-user-defined');
} catch (err) {
// ignore any error, just to make both FF and IE work
}
request.send(null);
var response=request.responseBody;
if (response==undefined){ // responseBody is non standard, but the only way to make it work in IE
response=request.responseText;
}
var bf=new BinaryFile(response);
return bf;
}
// ===============================================================
// Asyncronously load a binary file from the specified URL
//
// callback must be a function with one or two arguments:
// - bf = an object of type BinaryFile
// - optional argument object (used only if callback_arg not undefined)
function FetchBinaryURLAsync(url, callback, callback_arg) {
var callback_wrapper = function() {
if(this.readyState == 4) {
var response=this.responseBody;
if (response==undefined){ // responseBody is non standard, but the only way to make it work in IE
response=this.responseText;
}
var bf=new BinaryFile(response);
if (callback_arg!=null) {
callback(bf,callback_arg);
} else {
callback(bf);
}
}
}
var request = new XMLHttpRequest();
request.onreadystatechange = callback_wrapper;
request.open("GET", url,true);
try {
request.overrideMimeType('text/plain; charset=x-user-defined');
} catch (err) {
// ignore any error, just to make both FF and IE work
}
request.send(null);
return request
}
rrdFile.js
/*
* Client library for access to RRD archive files
* Part of the javascriptRRD package
* Copyright (c) 2009-2010 Frank Wuerthwein, [email protected]
* Igor Sfiligoi, [email protected]
*
* Original repository: http://javascriptrrd.sourceforge.net/
*
* MIT License [http://www.opensource.org/licenses/mit-license.php]
*
*/
/*
*
* RRDTool has been developed and is maintained by
* Tobias Oether [http://oss.oetiker.ch/rrdtool/]
*
* This software can be used to read files produced by the RRDTool
* but has been developed independently.
*
* Limitations:
*
* This version of the module assumes RRD files created on linux
* with intel architecture and supports both 32 and 64 bit CPUs.
* All integers in RRD files are suppoes to fit in 32bit values.
*
* Only versions 3 and 4 of the RRD archive are supported.
*
* Only AVERAGE,MAXIMUM,MINIMUM and LAST consolidation functions are
* supported. For all others, the behaviour is at the moment undefined.
*
*/
/*
* Dependencies:
*
* The data provided to this module require an object of a class
* that implements the following methods:
* getByteAt(idx) - Return a 8 bit unsigned integer at offset idx
* getLongAt(idx) - Return a 32 bit unsigned integer at offset idx
* getDoubleAt(idx) - Return a double float at offset idx
* getFastDoubleAt(idx) - Similar to getDoubleAt but with less precision
* getCStringAt(idx,maxsize) - Return a string of at most maxsize characters
* that was 0-terminated in the source
*
* The BinaryFile from binaryXHR.js implements this interface.
*
*/
// ============================================================
// Exception class
function InvalidRRD(msg) {
this.message=msg;
this.name="Invalid RRD";
}
// pretty print
InvalidRRD.prototype.toString = function() {
return this.name + ': "' + this.message + '"';
}
// ============================================================
// RRD DS Info class
function RRDDS(rrd_data,rrd_data_idx,my_idx) {
this.rrd_data=rrd_data;
this.rrd_data_idx=rrd_data_idx;
this.my_idx=my_idx;
}
RRDDS.prototype.getIdx = function() {
return this.my_idx;
}
RRDDS.prototype.getName = function() {
return this.rrd_data.getCStringAt(this.rrd_data_idx,20);
}
RRDDS.prototype.getType = function() {
return this.rrd_data.getCStringAt(this.rrd_data_idx+20,20);
}
RRDDS.prototype.getMin = function() {
return this.rrd_data.getDoubleAt(this.rrd_data_idx+48);
}
RRDDS.prototype.getMax = function() {
return this.rrd_data.getDoubleAt(this.rrd_data_idx+56);
}
// ============================================================
// RRD RRA Info class
function RRDRRAInfo(rrd_data,rra_def_idx,
int_align,row_cnt,pdp_step,my_idx) {
this.rrd_data=rrd_data;
this.rra_def_idx=rra_def_idx;
this.int_align=int_align;
this.row_cnt=row_cnt;
this.pdp_step=pdp_step;
this.my_idx=my_idx;
// char nam[20], uint row_cnt, uint pdp_cnt
this.rra_pdp_cnt_idx=rra_def_idx+Math.ceil(20/int_align)*int_align+int_align;
}
RRDRRAInfo.prototype.getIdx = function() {
return this.my_idx;
}
// Get number of rows
RRDRRAInfo.prototype.getNrRows = function() {
return this.row_cnt;
}
// Get number of slots used for consolidation
// Mostly for internal use
RRDRRAInfo.prototype.getPdpPerRow = function() {
return this.rrd_data.getLongAt(this.rra_pdp_cnt_idx);
}
// Get RRA step (expressed in seconds)
RRDRRAInfo.prototype.getStep = function() {
return this.pdp_step*this.getPdpPerRow();
}
// Get consolidation function name
RRDRRAInfo.prototype.getCFName = function() {
return this.rrd_data.getCStringAt(this.rra_def_idx,20);
}
// ============================================================
// RRD RRA handling class
function RRDRRA(rrd_data,rra_ptr_idx,
rra_info,
header_size,prev_row_cnts,ds_cnt) {
this.rrd_data=rrd_data;
this.rra_info=rra_info;
this.row_cnt=rra_info.row_cnt;
this.ds_cnt=ds_cnt;
var row_size=ds_cnt*8;
this.base_rrd_db_idx=header_size+prev_row_cnts*row_size;
// get imediately, since it will be needed often
this.cur_row=rrd_data.getLongAt(rra_ptr_idx);
// calculate idx relative to base_rrd_db_idx
// mostly used internally
this.calc_idx = function(row_idx,ds_idx) {
if ((row_idx>=0) && (row_idx<this.row_cnt)) {
if ((ds_idx>=0) && (ds_idx<ds_cnt)){
// it is round robin, starting from cur_row+1
var real_row_idx=row_idx+this.cur_row+1;
if (real_row_idx>=this.row_cnt) real_row_idx-=this.row_cnt;
return row_size*real_row_idx+ds_idx*8;
} else {
throw RangeError("DS idx ("+ row_idx +") out of range [0-" + ds_cnt +").");
}
} else {
throw RangeError("Row idx ("+ row_idx +") out of range [0-" + this.row_cnt +").");
}
}
}
RRDRRA.prototype.getIdx = function() {
return this.rra_info.getIdx();
}
// Get number of rows/columns
RRDRRA.prototype.getNrRows = function() {
return this.row_cnt;
}
RRDRRA.prototype.getNrDSs = function() {
return this.ds_cnt;
}
// Get RRA step (expressed in seconds)
RRDRRA.prototype.getStep = function() {
return this.rra_info.getStep();
}
// Get consolidation function name
RRDRRA.prototype.getCFName = function() {
return this.rra_info.getCFName();
}
RRDRRA.prototype.getEl = function(row_idx,ds_idx) {
return this.rrd_data.getDoubleAt(this.base_rrd_db_idx+this.calc_idx(row_idx,ds_idx));
}
// Low precision version of getEl
// Uses getFastDoubleAt
RRDRRA.prototype.getElFast = function(row_idx,ds_idx) {
return this.rrd_data.getFastDoubleAt(this.base_rrd_db_idx+this.calc_idx(row_idx,ds_idx));
}
// ============================================================
// RRD Header handling class
function RRDHeader(rrd_data) {
this.rrd_data=rrd_data;
this.validate_rrd();
this.calc_idxs();
}
// Internal, used for initialization
RRDHeader.prototype.validate_rrd = function() {
if (this.rrd_data.getLength()<1) throw new InvalidRRD("Empty file.");
if (this.rrd_data.getLength()<16) throw new InvalidRRD("File too short.");
if (this.rrd_data.getCStringAt(0,4)!=="RRD") throw new InvalidRRD("Wrong magic id.");
this.rrd_version=this.rrd_data.getCStringAt(4,5);
if ((this.rrd_version!=="0003")&&(this.rrd_version!=="0004")&&(this.rrd_version!=="0001")) {
throw new InvalidRRD("Unsupported RRD version "+this.rrd_version+".");
}
this.float_width=8;
if (this.rrd_data.getLongAt(12)==0) {
// not a double here... likely 64 bit
this.float_align=8;
if (! (this.rrd_data.getDoubleAt(16)==8.642135e+130)) {
// uhm... wrong endian?
this.rrd_data.switch_endian=true;
}
if (this.rrd_data.getDoubleAt(16)==8.642135e+130) {
// now, is it all 64bit or only float 64 bit?
if (this.rrd_data.getLongAt(28)==0) {
// true 64 bit align
this.int_align=8;
this.int_width=8;
} else {
// integers are 32bit aligned
this.int_align=4;
this.int_width=4;
}
} else {
throw new InvalidRRD("Magic float not found at 16.");
}
} else {
/// should be 32 bit alignment
if (! (this.rrd_data.getDoubleAt(12)==8.642135e+130)) {
// uhm... wrong endian?
this.rrd_data.switch_endian=true;
}
if (this.rrd_data.getDoubleAt(12)==8.642135e+130) {
this.float_align=4;
this.int_align=4;
this.int_width=4;
} else {
throw new InvalidRRD("Magic float not found at 12.");
}
}
this.unival_width=this.float_width;
this.unival_align=this.float_align;
// process the header here, since I need it for validation
// char magic[4], char version[5], double magic_float
// long ds_cnt, long rra_cnt, long pdp_step, unival par[10]
this.ds_cnt_idx=Math.ceil((4+5)/this.float_align)*this.float_align+this.float_width;
this.rra_cnt_idx=this.ds_cnt_idx+this.int_width;
this.pdp_step_idx=this.rra_cnt_idx+this.int_width;
//always get only the low 32 bits, the high 32 on 64 bit archs should always be 0
this.ds_cnt=this.rrd_data.getLongAt(this.ds_cnt_idx);
if (this.ds_cnt<1) {
throw new InvalidRRD("ds count less than 1.");
}
this.rra_cnt=this.rrd_data.getLongAt(this.rra_cnt_idx);
if (this.ds_cnt<1) {
throw new InvalidRRD("rra count less than 1.");
}
this.pdp_step=this.rrd_data.getLongAt(this.pdp_step_idx);
if (this.pdp_step<1) {
throw new InvalidRRD("pdp step less than 1.");
}
// best guess, assuming no weird align problems
this.top_header_size=Math.ceil((this.pdp_step_idx+this.int_width)/this.unival_align)*this.unival_align+10*this.unival_width;
var t=this.rrd_data.getLongAt(this.top_header_size);
if (t==0) {
throw new InvalidRRD("Could not find first DS name.");
}
}
// Internal, used for initialization
RRDHeader.prototype.calc_idxs = function() {
this.ds_def_idx=this.top_header_size;
// char ds_nam[20], char dst[20], unival par[10]
this.ds_el_size=Math.ceil((20+20)/this.unival_align)*this.unival_align+10*this.unival_width;
this.rra_def_idx=this.ds_def_idx+this.ds_el_size*this.ds_cnt;
// char cf_nam[20], uint row_cnt, uint pdp_cnt, unival par[10]
this.row_cnt_idx=Math.ceil(20/this.int_align)*this.int_align;
this.rra_def_el_size=Math.ceil((this.row_cnt_idx+2*this.int_width)/this.unival_align)*this.unival_align+10*this.unival_width;
this.live_head_idx=this.rra_def_idx+this.rra_def_el_size*this.rra_cnt;
// time_t last_up, int last_up_usec
this.live_head_size=2*this.int_width;
this.pdp_prep_idx=this.live_head_idx+this.live_head_size;
// char last_ds[30], unival scratch[10]
this.pdp_prep_el_size=Math.ceil(30/this.unival_align)*this.unival_align+10*this.unival_width;
this.cdp_prep_idx=this.pdp_prep_idx+this.pdp_prep_el_size*this.ds_cnt;
// unival scratch[10]
this.cdp_prep_el_size=10*this.unival_width;
this.rra_ptr_idx=this.cdp_prep_idx+this.cdp_prep_el_size*this.ds_cnt*this.rra_cnt;
// uint cur_row
this.rra_ptr_el_size=1*this.int_width;
this.header_size=this.rra_ptr_idx+this.rra_ptr_el_size*this.rra_cnt;
}
// Optional initialization
// Read and calculate row counts
RRDHeader.prototype.load_row_cnts = function() {
this.rra_def_row_cnts=[];
this.rra_def_row_cnt_sums=[]; // how many rows before me
for (var i=0; i<this.rra_cnt; i++) {
this.rra_def_row_cnts[i]=this.rrd_data.getLongAt(this.rra_def_idx+i*this.rra_def_el_size+this.row_cnt_idx,false);
if (i==0) {
this.rra_def_row_cnt_sums[i]=0;
} else {
this.rra_def_row_cnt_sums[i]=this.rra_def_row_cnt_sums[i-1]+this.rra_def_row_cnts[i-1];
}
}
}
// ---------------------------
// Start of user functions
RRDHeader.prototype.getMinStep = function() {
return this.pdp_step;
}
RRDHeader.prototype.getLastUpdate = function() {
return this.rrd_data.getLongAt(this.live_head_idx,false);
}
RRDHeader.prototype.getNrDSs = function() {
return this.ds_cnt;
}
RRDHeader.prototype.getDSNames = function() {
var ds_names=[]
for (var idx=0; idx<this.ds_cnt; idx++) {
var ds=this.getDSbyIdx(idx);
var ds_name=ds.getName()
ds_names.push(ds_name);
}
return ds_names;
}
RRDHeader.prototype.getDSbyIdx = function(idx) {
if ((idx>=0) && (idx<this.ds_cnt)) {
return new RRDDS(this.rrd_data,this.ds_def_idx+this.ds_el_size*idx,idx);
} else {
throw RangeError("DS idx ("+ idx +") out of range [0-" + this.ds_cnt +").");
}
}
RRDHeader.prototype.getDSbyName = function(name) {
for (var idx=0; idx<this.ds_cnt; idx++) {
var ds=this.getDSbyIdx(idx);
var ds_name=ds.getName()
if (ds_name==name)
return ds;
}
throw RangeError("DS name "+ name +" unknown.");
}
RRDHeader.prototype.getNrRRAs = function() {
return this.rra_cnt;
}
RRDHeader.prototype.getRRAInfo = function(idx) {
if ((idx>=0) && (idx<this.rra_cnt)) {
return new RRDRRAInfo(this.rrd_data,
this.rra_def_idx+idx*this.rra_def_el_size,
this.int_align,this.rra_def_row_cnts[idx],this.pdp_step,
idx);
} else {
throw RangeError("RRA idx ("+ idx +") out of range [0-" + this.rra_cnt +").");
}
}
// ============================================================
// RRDFile class
// Given a BinaryFile, gives access to the RRD archive fields
//
// Arguments:
// bf must be an object compatible with the BinaryFile interface
// file_options - currently no semantics... introduced for future expandability
function RRDFile(bf,file_options) {
this.file_options=file_options;
var rrd_data=bf
this.rrd_header=new RRDHeader(rrd_data);
this.rrd_header.load_row_cnts();
// ===================================
// Start of user functions
this.getMinStep = function() {
return this.rrd_header.getMinStep();
}
this.getLastUpdate = function() {
return this.rrd_header.getLastUpdate();
}
this.getNrDSs = function() {
return this.rrd_header.getNrDSs();
}
this.getDSNames = function() {
return this.rrd_header.getDSNames();
}
this.getDS = function(id) {
if (typeof id == "number") {
return this.rrd_header.getDSbyIdx(id);
} else {
return this.rrd_header.getDSbyName(id);
}
}
this.getNrRRAs = function() {
return this.rrd_header.getNrRRAs();
}
this.getRRAInfo = function(idx) {
return this.rrd_header.getRRAInfo(idx);
}
this.getRRA = function(idx) {
rra_info=this.rrd_header.getRRAInfo(idx);
return new RRDRRA(rrd_data,
this.rrd_header.rra_ptr_idx+idx*this.rrd_header.rra_ptr_el_size,
rra_info,
this.rrd_header.header_size,
this.rrd_header.rra_def_row_cnt_sums[idx],
this.rrd_header.ds_cnt);
}
}
get_cpu_mem_data.js
rrd_data=undefined;
var cpu_value,mem_value;
function get_cpu_mem_val(bf) {
var i_rrd_data=undefined;
if (bf.getLength()<1) {
alert("File is empty (possibly loading failed)!");
return 1;
}
try {
var i_rrd_data=new RRDFile(bf);
} catch(err) {
alert("File is not a valid RRD archive!\n"+err);
}
if (i_rrd_data!=undefined) {
rrd_data=i_rrd_data;
var rra=rrd_data.getRRA(0);
var cpu=rra.getElFast(60-1,0);
var mem=rra.getElFast(60-1,1);
if (cpu ==undefined){
cpu=0;
}
if (mem ==undefined){
mem=0;
}
cpu_value=cpu;
mem_value=mem;
//alert("cpu:"+cpu+"mem:"+mem);
}
else
{
var cpu=0;
var mem=0;
}
}
function get_cpu_mem(){
fname="../sysstatus.rrd?rand="+Math.random();
try {
FetchBinaryURLAsync(fname,get_cpu_mem_val);
var data=[{cpu_value:cpu_value,mem_value:mem_value}];
return data;
} catch (err) {
alert("Failed loading "+fname+"\n"+err);
}
}
function get_cpu_mem_vals(bf) {
var i_rrd_data=undefined;
if (bf.getLength()<1) {
alert("File is empty (possibly loading failed)!");
return 1;
}
try {
var i_rrd_data=new RRDFile(bf);
} catch(err) {
alert("File is not a valid RRD archive!\n"+err);
}
if (i_rrd_data!=undefined) {
rrd_data=i_rrd_data;
}
var rra=rrd_data.getRRA(0);
var rows=rra.getNrRows();
for (var i=0; i<rows;i++) {
var cpu=rra.getElFast(i,0);
var mem=rra.getElFast(i,1);
}
}
function get_cpu_mems(){
fname="./sysstatus.rrd";
try {
FetchBinaryURLAsync(fname,get_cpu_mem_vals);
} catch (err) {
alert("Failed loading "+fname+"\n"+err);
}
}
cpu_memory.js
$(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
var chart;
$('#container').highcharts({
credits:{enabled:false},//不显示Highcharts的链接
chart: {
type: 'spline',
marginRight: 150,
marginLeft: 50,
marginBottom: 25,
animation: Highcharts.svg,
events: {
load: function() {
// 若有第3条线,则添加
// var series_other_property = this.series[2]
// 并在 series: [] 中添加相应的 (name, data) 对
var series_cpu = this.series[0];
var series_mem = this.series[1];
// 定时器,每隔1000ms刷新曲线一次
setInterval(function() {
get_cpu_mem();
// 使用JQuery从后台Servlet获取
// JSON格式的数据,
// 如 "{"cpu": 80,"mem": 10}"
//alert('cpu_value'+cpu_value+',mem_value'+mem_value);
//$.getJSON("", null,function(data) {
// 当前时间,为x轴数据
var x = (new Date()).getTime();
// y轴数据
var cpu = cpu_value;
var mem = mem_value;
// 更新曲线数据
series_cpu.addPoint([x, cpu], true, true);
series_mem.addPoint([x, mem], true, true);
// });
},
1000/*启动间隔,单位ms*/
);
}
}
},
title: {
text: 'CPU 内存使用率(%)',
x: -20
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'CPU 内存使用率(%)'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function()
{
return '<b>'+ this.series.name +'</b><br/>'+
Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) +'<br/>'+
Highcharts.numberFormat(this.y, 2);
}
//valueSuffix: '%'
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: -10,
y: 100,
borderWidth: 0
},
series: [
// 第1条曲线的(name, data)对
{
name: 'CPU',
data: (function() {
var data = [],
time = (new Date()).getTime(),
i;
// 给曲线y值赋初值0
for (i = -9; i <= 0; i++) {
data.push({
x: time + i * 1000,
cpu: 0
});
}
return data;
})()
},
// 第2条曲线的(name, data)对
{
name: '内存',
data: (function() {
var data = [],
time = (new Date()).getTime(),
i;
// 给曲线y值赋初值0
for (i = -9; i <= 0; i++) {
data.push({
x: time + i * 1000,
y: 0
});
}
return data;
})()
},
]
});
});