///////////////////////////////////////////////////////////////////////////////
/*
graph.js
Using Scalable Vector Graphics (SVG) generate the required graphics.
COPYRIGHT
---------
Copyright (C) 2014-2023 Mark G.Daniel
This program, comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it under the
conditions of the GNU GENERAL PUBLIC LICENSE, version 3, or any later version.
http://www.gnu.org/licenses/gpl.txt
VERSION
-------
22-APR-2014 MGD initial
*/
///////////////////////////////////////////////////////////////////////////////
/*
Generate the bar and history (even if not visible) graphs of the system
"dynamic" data.
*/
function mdsiGraphDynamic()
{
if (!(mdsi_StaticData && mdsi_DynamicData)) return;
mdsiDataAveMax ('cpuBusy');
mdsiDataAveMax ('memInUse');
mdsiDataAveMax ('pageFileUsed');
mdsiDataAveMax ('pageFaults');
mdsiDataAveMax ('bio');
mdsiDataAveMax ('dio');
mdsiDataAveMax ('lockActivity');
mdsiDataAveMax ('netPerSec');
mdsiDataAveMax ('fcpRW');
mdsiDataAveMax ('procTot');
if (mdsi_StaticData.clusterMember)
{
mdsiDataAveMax ('clusterMsgTotal');
mdsiDataAveMax ('clusterKbyteMap');
mdsiDataAveMax ('mscpTotal');
}
mdsiDisplayModes();
mdsiDisplaySummary();
mdsiDisplaySynopsis();
mdsiBarGraph ('cpuBar', 'CPU', 'cpuBusy', null, 'cpuSEK');
mdsiBarGraph ('memBar', 'MEM', 'memInUse');
mdsiBarGraph ('fltsBar', 'FLTS', 'pageFaults', null, 'pageFaultsHard');
mdsiBarGraph ('bioBar', 'BIO', 'bio');
mdsiBarGraph ('dioBar', 'DIO', 'dio');
mdsiBarGraph ('lockBar', 'LOCK', 'lockActivity', 'lockWait');
mdsiBarGraph ('netBar', 'NET', 'netPerSec', 'netRxPerSec');
mdsiBarGraph ('diskBar', 'DISK', 'fcpRW', null, 'fcpWrite');
mdsiBarGraph ('procBar', 'PROC', 'procTot', 'procInt');
if (mdsi_StaticData.clusterMember)
{
mdsiBarGraph ('scsmsgBar', 'SCSMSG', 'clusterMsgTotal',
'clusterMsgSent');
mdsiBarGraph ('scskbBar', 'SCSKB', 'clusterKbyteMap');
mdsiBarGraph ('mscpBar', 'MSCP', 'mscpTotal', 'mscpMsgSent');
}
mdsiHistoryGraph ('cpuHist', 'CPU', 'cpuBusy', null, 'cpuSEK');
mdsiModesGraph ('cpuModesHist', 'CPU');
mdsiHistoryGraph ('memHist', 'MEM \u21b7', 'memInUse');
mdsiHistoryGraph ('pgflHist', 'PGFL \u21b7', 'pageFileUsed');
mdsiHistoryGraph ('fltsHist', 'FLTS', 'pageFaults', null, 'pageFaultsHard');
mdsiHistoryGraph ('bioHist', 'BIO', 'bio');
mdsiHistoryGraph ('dioHist', 'DIO', 'dio');
mdsiHistoryGraph ('lockHist', 'LOCK', 'lockActivity', null, 'lockWait');
var NIlabel = 'NET \u21b7';
var err = mdsiGetData('netErrors');
if (err > 0) NIlabel += '\n!ERR: ' + err;
mdsiHistoryGraph ('netHist', NIlabel, 'netPerSec', 'netRxPerSec');
mdsiHistoryGraph ('netDgramHist', 'DGRAM \u21b7',
'netDgramTx', 'netDgramRx');
mdsiHistoryGraph ('diskHist', 'DISK', 'fcpRW', null, 'fcpWrite');
mdsiHistoryGraph ('procHist', 'PROC', 'procTot', 'procInt');
if (mdsi_StaticData.clusterMember)
{
mdsiHistoryGraph ('scsmsgHist', 'SCSMSG', 'clusterMsgTotal',
'clusterMsgSent');
mdsiHistoryGraph ('scskbHist', 'SCSKB', 'clusterKbyteMap');
mdsiHistoryGraph ('mscpHist', 'MSCP', 'mscpTotal', 'mscpWrite');
}
}
///////////////////////////////////////////////////////////////////////////////
/*
Generate disk graphs.
*/
function mdsiGraphDisk()
{
var cnt = mdsiGetData('diskCount');
for (var idx = 0; idx < cnt; idx++)
{
var disk = 'disk' + idx;
mdsiDataAveMax (disk+'iops');
mdsiDataAveMax (disk+'qlen');
mdsiDataAveMax (disk+'delval');
mdsi_DataMaximum[disk+'delval'] = mdsiGetData(disk+'delta');
mdsi_DataMaximum[disk+'qlen'] = mdsiGetData(disk+'qmax');
}
for (var idx = 0; idx < cnt; idx++)
{
var disk = 'disk' + idx;
var delta = mdsiGetData(disk+'delta');
var delsym = mdsiGetData(disk+'delsym');
var dev = mdsiGetData(disk+'dev');
var err = mdsiGetData(disk+'err');
var free = mdsiGetData(disk+'free');
var iops = mdsiGetData(disk+'iops');
var size = mdsiGetData(disk+'size');
var mvip = mdsiGetData(disk+'mvip');
var qlen = mdsiGetData(disk+'qlen');
var qmax = mdsiGetData(disk+'qmax');
var vol = mdsiGetData(disk+'vol');
if (vol.length) dev += ' ' + vol;
var bardev = dev;
if (vol.length)
bardev += ' \u0394' + mdsiValue(delta,0) + delsym +
' \u2630' + qlen + '/' + qmax;
mdsiBarGraph ('perDiskBar'+idx, bardev, disk+'iops');
if (vol.length)
{
if (!(mdsi_DiskDeltaDisplay || mdsi_DiskQlenDisplay))
dev += ' \u21b7';
dev += '\n' + mdsiValue(size) + 'B ' +
(free * 100 / size).toFixed(0) + '%' +
' \u0394' + mdsiValue(delta,0) + mdsiGetData(disk+'delsym');
dev += '\n\u2630' + qlen + '/' + qmax;
}
if (err > 0) dev += '\n!ERR: ' + err;
if (mvip)
{
if (err == 0) dev += '\n!\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0';
dev += '\u00a0\u00a0\u00a0*** MOUNT VERIFY ***';
}
mdsiHistoryGraph ('perDiskHistIOPs'+idx, dev, disk+'iops');
if (vol.length)
{
dev = mdsiGetData(disk+'dev') +' ' + vol;
if (!(mdsi_DiskDeltaDisplay || mdsi_DiskQlenDisplay))
dev += ' \u21b7\n' + mdsiValue(size) + 'B ' +
(free * 100 / size).toFixed(0) + '%';
}
if (!mdsi_DiskDeltaDisplay && err > 0) dev += '\n!ERR: ' + err;
if (mvip)
{
if (mdsi_DiskDeltaDisplay || err == 0)
dev += '\n!\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0';
dev += '\u00a0\u00a0\u00a0*** MOUNT VERIFY ***';
}
mdsiHistoryGraph ('perDiskHistQlen'+idx, dev, disk+'qlen', disk);
mdsiHistoryGraph ('perDiskHistDelta'+idx, dev, disk+'delval', disk);
}
}
///////////////////////////////////////////////////////////////////////////////
/*
Generate the per-process history graph (irrespective of visibility).
*/
function mdsiGraphPerProcess()
{
if (!mdsi_PerProcessPid) return;
var pid = mdsi_PerProcessPid;
mdsiDataAveMax (pid+'CPU');
mdsiDataAveMax (pid+'BufIO');
mdsiDataAveMax (pid+'DirIO');
mdsiDataAveMax (pid+'PageFaults');
mdsiDataAveMax (pid+'PageFileUsed');
mdsiDataAveMax (pid+'PrivatePages');
mdsiDataAveMax (pid+'WorkingSet');
mdsiHistoryGraph ('perCpuHist', 'CPU\u2020', pid+'CPU', null, pid+'SEK');
mdsiHistoryGraph ('perWsetHist', 'WSET\u2020 \u21b7', pid+'WorkingExtent',
pid+'WorkingSet');
mdsiHistoryGraph ('perPgflHist', 'PGFL\u2020', pid+'PageFileQuota',
pid+'PageFileUsed');
mdsiHistoryGraph ('perPgsHist', 'PGS\u2020', pid+'PrivatePages',
pid+'GlobalPages');
mdsiHistoryGraph ('perBioHist', 'BIO\u2020', pid+'BufIO');
mdsiHistoryGraph ('perDioHist', 'DIO\u2020', pid+'DirIO');
mdsiHistoryGraph ('perFltsHist', 'FLTS\u2020', pid+'PageFaults');
}
///////////////////////////////////////////////////////////////////////////////
/*
*/
var mdsi_HistoryHeight = mdsi_HistHeight,
mdsi_HistoryWidth = mdsi_HistWidth5;
function mdsiSetHistoryWidth (seconds)
{
mdsiCSS ('.history', 'width', seconds+'px');
mdsiCSS ('.diskory', 'width', seconds+'px');
mdsi_HistoryWidth = seconds;
mdsi_ModesWidth = seconds;
mdsiStoreSeconds (seconds);
}
function mdsiSetHistoryHeight (height)
{
mdsiCSS ('.history', 'height', height+'px');
mdsiCSS ('.diskory', 'height', height+'px');
mdsi_HistoryHeight = height;
mdsi_ModesHeight = height;
}
///////////////////////////////////////////////////////////////////////////////
/*
Scan all data in the (dynamic) DataStore for the given datum. Calculate
maximum and average values and store in the respective arrays.
*/
var mdsi_DataAverage = [],
mdsi_DataMaximum = [],
mdsi_DataMinimum = [];
function mdsiDataAveMax (datum)
{
var val,
ave = 0,
cnt = 0,
len = mdsiStoreSize()-1,
max = 0,
min = 9007199254740992;
for (var idx = 0; idx < len; idx++)
{
cnt++;
val = mdsiGetData(datum,null,idx);
ave += val;
if (val > max) max = val;
if (val < min) min = val;
}
if (cnt) mdsi_DataAverage[datum] = ave / cnt;
mdsi_DataMaximum[datum] = max;
mdsi_DataMinimum[datum] = min;
}
///////////////////////////////////////////////////////////////////////////////
/*
Generate the instantaneous data display bar graph.
The function parameters can take one to three additional arguments. These are
the names of each of the data. The first is plotted in green, the second in
blue, the third in red. Any may be omitted except the first.
*/
var mdsi_BarClass = [];
mdsi_BarClass [0] = 'bar_red';
mdsi_BarClass [1] = 'bar_green';
mdsi_BarClass [2] = 'bar_blue';
mdsi_BarClass [3] = 'bar_red';
function mdsiBarGraph (name,title)
{
if (!mdsiStoreSize()) return;
var ave, color, dcnt, max, plot, string, val;
var datum = [];
var id = $byId(name);
// datum has [1]..[n] from arguments [2]..[n]
for (dcnt = 1; dcnt <= 3 && dcnt <= arguments.length-2; dcnt++)
datum[dcnt] = arguments[dcnt+1];
///////////////////
// special cases //
///////////////////
if (name == 'cpuBar')
{
var cpuActive = mdsiGetData('cpuActive');
if (cpuActive > 1)
{
max = 100 * cpuActive;
title = 'CPUx' + cpuActive;
}
else
max = 100;
ave = mdsi_DataAverage[datum[1]];
}
else
if (name == 'memBar')
{
max = mdsi_StaticData.memSize;
ave = mdsi_DataAverage['memInUse'];
}
else
if (name.substr(0,4) == 'mode')
{
var cpuActive = mdsiGetData('cpuActive');
if (cpuActive > 1)
max = 100 * cpuActive;
else
max = 100;
ave = mdsi_DataAverage[datum[1]];
}
else
{
max = mdsi_DataMaximum[datum[1]];
ave = mdsi_DataAverage[datum[1]];
}
///////////////////
// generate bars //
///////////////////
var svg = '';
id.innerHTML = svg;
}
///////////////////////////////////////////////////////////////////////////////
/*
Generate and display the history (line) graph.
The function parameters can take one to three additional arguments. These are
the names of each of the data. The first is plotted in green, the second in
blue, the third in red. Any may be omitted except the first.
*/
var mdsi_HistoryClass = [];
mdsi_HistoryClass [1] = ['hist_green','hist_text_green'];
mdsi_HistoryClass [2] = ['hist_blue','hist_text_blue'];
mdsi_HistoryClass [3] = ['hist_red','hist_text_red'];
function mdsiHistoryGraph (name,title)
{
if (!mdsiStoreSize()) return;
var ave, dcnt, dscnt, lastXnone, max, string, tcnt, val;
var datum = [],
points = [],
valdcnt = [];
var xpos = mdsi_HistoryWidth,
lastXpos = mdsi_HistoryWidth;
var id = $byId(name);
// datum has [1]..[n] from arguments [2]..[n]
for (dcnt = 1; dcnt <= 3 && dcnt <= arguments.length-2; dcnt++)
{
datum[dcnt] = arguments[dcnt+1];
points[dcnt] = '';
}
var interval = mdsi_StaticData.interval;
var timestamp = mdsiGetData('timestamp');
///////////////////
// special cases //
///////////////////
if (name == 'cpuHist' || name == 'perCpuHist')
{
var cpuActive = mdsiGetData('cpuActive');
if (cpuActive > 1)
{
max = 100 * cpuActive;
title = 'CPUx' + cpuActive;
}
else
max = 100;
ave = mdsi_DataAverage[datum[1]];
}
else
if (name == 'memHist')
{
max = mdsi_StaticData.memSize;
ave = mdsi_DataAverage['memInUse'];
}
else
if (name == 'pgflHist')
{
max = mdsiGetData('pageFileSize');
ave = mdsi_DataAverage['pageFileUsed'];
}
else
if (name == 'perWsetHist')
{
max = mdsiGetData(datum[1]);
ave = mdsi_DataAverage[datum[2]];
// bit shonky here
datum[1] = datum[2];
datum[2] = datum[3];
datum[3] = null;
}
else
if (name == 'perPgflHist')
{
max = mdsiGetData(datum[1]);
ave = mdsi_DataAverage[datum[2]];
// bit shonky here
datum[1] = datum[2];
datum[2] = null;
datum[3] = null;
}
else
if (name == 'netDgramHist')
{
if (mdsiGetData(datum[1]) > mdsiGetData(datum[2]))
{
mdsiDataAveMax (datum[1]);
max = mdsi_DataMaximum[datum[1]];
ave = mdsi_DataAverage[datum[1]];
}
else
{
mdsiDataAveMax (datum[2]);
max = mdsi_DataMaximum[datum[2]];
ave = mdsi_DataAverage[datum[2]];
}
}
else
{
max = mdsi_DataMaximum[datum[1]];
ave = mdsi_DataAverage[datum[1]];
}
//////////////////////////
// generate data points //
//////////////////////////
var svg = '';
id.innerHTML = svg;
}
///////////////////////////////////////////////////////////////////////////////
/*
Generate and display the history (line) graph.
The function parameters can take one to three additional arguments. These are
the names of each of the data. The first is plotted in green, the second in
blue, the third in red. Any may be omitted except the first.
*/
var mdsi_ModesNames = ['','cpuBusy','modeKER','modeEXE','modeSUP','modeUSE',
'modeINT','modeMPS'];
var mdsi_ModesCount = mdsi_ModesNames.length - 1;
var mdsi_ModesWidth = mdsi_HistoryWidth,
mdsi_ModesHeight = mdsi_HistoryHeight;
var mdsi_ModesClass = [];
mdsi_ModesClass [1] = ['modes_total','modes_text_total'];
mdsi_ModesClass [2] = ['modes_kernel','modes_text_kernel'];
mdsi_ModesClass [3] = ['modes_exec','modes_text_exec'];
mdsi_ModesClass [4] = ['modes_super','modes_text_super'];
mdsi_ModesClass [5] = ['modes_user','modes_text_user'];
mdsi_ModesClass [6] = ['modes_inter','modes_text_inter'];
mdsi_ModesClass [7] = ['modes_mpsyn','modes_text_mpsyn'];
function mdsiModesGraph (name,title)
{
if (!mdsiStoreSize()) return;
var dcnt, dscnt, lastXnone, max, string, tcnt, val, x2;
var datum = [],
points = [],
valdcnt = [];
var xpos = mdsi_ModesWidth,
lastXpos = mdsi_ModesWidth;
var id = $byId(name);
for (dcnt = 1; dcnt <= mdsi_ModesCount; dcnt++)
{
datum[dcnt] = mdsiGetData(mdsi_ModesNames[dcnt]);
points[dcnt] = '';
}
var interval = mdsi_StaticData.interval;
var timestamp = mdsiGetData('timestamp');
var cpuActive = mdsiGetData('cpuActive');
if (cpuActive > 1)
{
max = 100 * cpuActive;
title = 'CPUx' + cpuActive;
}
else
max = 100;
//////////////////////////
// generate data points //
//////////////////////////
var svg = '';
id.innerHTML = svg;
}
///////////////////////////////////////////////////////////////////////////////
/*
Return a string respresenting the value paramater transmogrified to kilos and
megas as seem more meaningful. Kilo == 1024!
*/
function mdsiValue (value,kat)
{
// useful during development :-)
if (typeof value == 'undefined') return '?';
if (typeof kat == 'undefined') kat = 10;
var fixed = 0;
if (value > 1099511627776)
{
if (value > 1099511627776*100)
fixed = 1;
else
if (value > 1099511627776*10)
fixed = 2;
else
fixed = 3;
var string = ((value/1099511627776).toFixed(fixed)-0).toString() + 'T';
}
else
if (value > 1073741824)
{
if (value > 1073741824*100)
fixed = 1;
else
if (value > 1073741824*10)
fixed = 2;
else
fixed = 3;
var string = ((value/1073741824).toFixed(fixed)-0).toString() + 'G';
}
else
if (value > 1048576)
{
if (value > 1048576*100)
fixed = 1;
else
if (value > 1048576*10)
fixed = 2;
else
fixed = 3;
var string = ((value/1048576).toFixed(fixed)-0).toString() + 'M';
}
else
if (value > 1024*kat)
{
if (value <= 1024*100) fixed = 1;
var string = ((value/1024).toFixed(fixed)-0).toString() + 'k';
}
else
var string = value.toFixed(0);
return string;
}
///////////////////////////////////////////////////////////////////////////////
function mdsiWithCommas(num)
{
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, mdsi_ThousandComma);
}
///////////////////////////////////////////////////////////////////////////////
function mdsiPixelWidth(string)
{
var length = string.length;
// whadda kludge!
if (string.indexOf('\u2630') >= 0) length += 0.5;
return (length * 7);
}
///////////////////////////////////////////////////////////////////////////////