mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-07-27 10:31:38 +08:00
364 lines
10 KiB
JavaScript
364 lines
10 KiB
JavaScript
'use strict';
|
|
'require baseclass';
|
|
'require fs';
|
|
|
|
document.head.append(E('style', {'type': 'text/css'},
|
|
`
|
|
.cpu-status-view-mode-entry {
|
|
display: inline-block;
|
|
cursor: pointer;
|
|
margin: 2px 4px 2px 0 !important;
|
|
padding: 3px 5px;
|
|
border: 1px solid;
|
|
border-color: transparent;
|
|
-webkit-border-radius: 4px;
|
|
-moz-border-radius: 4px;
|
|
border-radius: 4px;
|
|
opacity: 0.7;
|
|
background-color: rgba(100 100 100 / 0.2);
|
|
}
|
|
.cpu-status-view-mode-entry:hover {
|
|
opacity: 0.9;
|
|
}
|
|
.cpu-status-view-mode-entry:active {
|
|
opacity: 1.0;
|
|
}
|
|
.cpu-status-view-mode-entry-checked {
|
|
border: 1px solid;
|
|
opacity: 1.0;
|
|
}
|
|
.cpu-status-view-mode-entry-checked:hover {
|
|
opacity: 1.0;
|
|
}
|
|
`));
|
|
|
|
return baseclass.extend({
|
|
title : _('CPU Load'),
|
|
|
|
viewName : 'cpu_status',
|
|
|
|
availableViewModes: {
|
|
0: [ 'allCPUs', _('Load') ],
|
|
1: [ 'allCPUsDetail', _('Detailed load') ],
|
|
2: [ 'eachCPU', _('Load of each CPU') ],
|
|
3: [ 'eachCPUDetail', _('Detailed load of each CPU') ],
|
|
},
|
|
|
|
viewMode : 0,
|
|
|
|
lastStatArray : null,
|
|
|
|
restoreSettingsFromLocalStorage() {
|
|
let viewModeLocal = localStorage.getItem(`luci-app-${this.viewName}-viewMode`);
|
|
if(viewModeLocal) {
|
|
this.viewMode = Number(viewModeLocal);
|
|
};
|
|
},
|
|
|
|
saveSettingsToLocalStorage(viewMode) {
|
|
if(this.viewMode != viewMode) {
|
|
localStorage.setItem(
|
|
`luci-app-${this.viewName}-viewMode`, String(viewMode));
|
|
};
|
|
},
|
|
|
|
parseProcData(data) {
|
|
let cpuStatArray = [];
|
|
let statItemsArray = data.trim().split('\n').filter(s => s.startsWith('cpu'));
|
|
|
|
for(let str of statItemsArray) {
|
|
let arr = str.split(/\s+/).slice(0, 8);
|
|
arr[0] = (arr[0] == 'cpu') ? Infinity : arr[0].replace('cpu', '');
|
|
cpuStatArray.push(arr.map(e => Number(e)));
|
|
};
|
|
|
|
cpuStatArray.sort((a, b) => a[0] - b[0]);
|
|
|
|
return cpuStatArray;
|
|
},
|
|
|
|
calcCPULoad(cpuStatArray) {
|
|
let retArray = [];
|
|
cpuStatArray.forEach((c, i) => {
|
|
let loadUser = 0,
|
|
loadNice = 0,
|
|
loadSys = 0,
|
|
loadIdle = 0,
|
|
loadIo = 0,
|
|
loadIrq = 0,
|
|
loadSirq = 0,
|
|
loadAvg = 0;
|
|
if(this.lastStatArray !== null && this.lastStatArray.cpuNum == c.cpuNum) {
|
|
let user = c[1] - this.lastStatArray[i][1],
|
|
nice = c[2] - this.lastStatArray[i][2],
|
|
sys = c[3] - this.lastStatArray[i][3],
|
|
idle = c[4] - this.lastStatArray[i][4],
|
|
io = c[5] - this.lastStatArray[i][5],
|
|
irq = c[6] - this.lastStatArray[i][6],
|
|
sirq = c[7] - this.lastStatArray[i][7];
|
|
let sum = user + nice + sys + idle + io + irq + sirq;
|
|
loadUser = Number((100 * user / sum).toFixed(1));
|
|
loadNice = Number((100 * nice / sum).toFixed(1));
|
|
loadSys = Number((100 * sys / sum).toFixed(1));
|
|
loadIdle = Number((100 * idle / sum).toFixed(1));
|
|
loadIo = Number((100 * io / sum).toFixed(1));
|
|
loadIrq = Number((100 * irq / sum).toFixed(1));
|
|
loadSirq = Number((100 * sirq / sum).toFixed(1));
|
|
loadAvg = Math.round(100 * (user + nice + sys + io + irq + sirq) / sum);
|
|
};
|
|
retArray.push(
|
|
{cpuNum: c[0], loadUser, loadNice, loadSys, loadIdle, loadIo, loadIrq, loadSirq, loadAvg});
|
|
});
|
|
return retArray;
|
|
},
|
|
|
|
allCPUs: {
|
|
makeTable() {
|
|
this.table = E('table', { 'class': 'table' });
|
|
},
|
|
append(cpuNum, cpuLoadObj, cpuLoadFlag) {
|
|
if(cpuNum == Infinity) {
|
|
this.table.append(
|
|
E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td left', 'width': '33%' },
|
|
_('Total load')),
|
|
E('td', { 'class': 'td' },
|
|
E('div', {
|
|
'class': 'cbi-progressbar',
|
|
'title': (cpuLoadFlag) ?
|
|
cpuLoadObj.loadAvg + '%' :
|
|
_('Calculating') + '...',
|
|
},
|
|
E('div', { 'style': 'width:' + cpuLoadObj.loadAvg + '%' })
|
|
)
|
|
),
|
|
])
|
|
);
|
|
};
|
|
},
|
|
},
|
|
|
|
allCPUsDetail: {
|
|
cpuTableTitles: [
|
|
_('All CPUs'),
|
|
_('Load'),
|
|
'user %',
|
|
'nice %',
|
|
'system %',
|
|
'idle %',
|
|
'iowait %',
|
|
'irq %',
|
|
'softirq %',
|
|
],
|
|
makeTable() {
|
|
this.table = E('table', { 'class': 'table' },
|
|
E('tr', { 'class': 'tr table-titles' }, [
|
|
E('th', { 'class': 'th left' }, this.cpuTableTitles[0]),
|
|
E('th', { 'class': 'th left' }, this.cpuTableTitles[1]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[2]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[3]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[4]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[5]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[6]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[7]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[8]),
|
|
])
|
|
);
|
|
},
|
|
append(cpuNum, cpuLoadObj, cpuLoadFlag) {
|
|
if(cpuNum == Infinity) {
|
|
this.table.append(
|
|
E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td left', 'data-title': this.cpuTableTitles[0] },
|
|
_('Total load')),
|
|
E('td', { 'class': 'td left', 'data-title': this.cpuTableTitles[1] },
|
|
E('div', {
|
|
'class': 'cbi-progressbar',
|
|
'title': (cpuLoadFlag) ?
|
|
cpuLoadObj.loadAvg + '%' :
|
|
_('Calculating') + '...',
|
|
'style': 'min-width:8em !important',
|
|
},
|
|
E('div', { 'style': 'width:' + cpuLoadObj.loadAvg + '%' })
|
|
)
|
|
),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[2] }, cpuLoadObj.loadUser),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[3] }, cpuLoadObj.loadNice),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[4] }, cpuLoadObj.loadSys),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[5] }, cpuLoadObj.loadIdle),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[6] }, cpuLoadObj.loadIo),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[7] }, cpuLoadObj.loadIrq),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[8] }, cpuLoadObj.loadSirq),
|
|
])
|
|
);
|
|
};
|
|
},
|
|
},
|
|
|
|
eachCPU: {
|
|
makeTable() {
|
|
this.table = E('table', { 'class': 'table' });
|
|
},
|
|
append(cpuNum, cpuLoadObj, cpuLoadFlag) {
|
|
this.table.append(
|
|
E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td left', 'width': '33%' },
|
|
(cpuNum == Infinity) ? _('Total load') : _('CPU') + ' ' + cpuNum),
|
|
E('td', { 'class': 'td' },
|
|
E('div', {
|
|
'class': 'cbi-progressbar',
|
|
'title': (cpuLoadFlag) ?
|
|
cpuLoadObj.loadAvg + '%' :
|
|
_('Calculating') + '...',
|
|
},
|
|
E('div', { 'style': 'width:' + cpuLoadObj.loadAvg + '%' })
|
|
)
|
|
),
|
|
])
|
|
);
|
|
},
|
|
},
|
|
|
|
eachCPUDetail: {
|
|
cpuTableTitles: [
|
|
_('CPU'),
|
|
_('Load'),
|
|
'user %',
|
|
'nice %',
|
|
'system %',
|
|
'idle %',
|
|
'iowait %',
|
|
'irq %',
|
|
'softirq %',
|
|
],
|
|
makeTable() {
|
|
this.table = E('table', { 'class': 'table' },
|
|
E('tr', { 'class': 'tr table-titles' }, [
|
|
E('th', { 'class': 'th left' }, this.cpuTableTitles[0]),
|
|
E('th', { 'class': 'th left' }, this.cpuTableTitles[1]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[2]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[3]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[4]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[5]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[6]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[7]),
|
|
E('th', { 'class': 'th center' }, this.cpuTableTitles[8]),
|
|
])
|
|
);
|
|
},
|
|
append(cpuNum, cpuLoadObj, cpuLoadFlag) {
|
|
this.table.append(
|
|
E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td left', 'data-title': this.cpuTableTitles[0] },
|
|
(cpuNum == Infinity) ? _('Total load') : _('CPU') + ' ' + cpuNum),
|
|
E('td', { 'class': 'td left', 'data-title': this.cpuTableTitles[1] },
|
|
E('div', {
|
|
'class': 'cbi-progressbar',
|
|
'title': (cpuLoadFlag) ?
|
|
cpuLoadObj.loadAvg + '%' :
|
|
_('Calculating') + '...',
|
|
'style': 'min-width:8em !important',
|
|
},
|
|
E('div', { 'style': 'width:' + cpuLoadObj.loadAvg + '%' })
|
|
)
|
|
),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[2] }, cpuLoadObj.loadUser),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[3] }, cpuLoadObj.loadNice),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[4] }, cpuLoadObj.loadSys),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[5] }, cpuLoadObj.loadIdle),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[6] }, cpuLoadObj.loadIo),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[7] }, cpuLoadObj.loadIrq),
|
|
E('td', { 'class': 'td center',
|
|
'data-title': this.cpuTableTitles[8] }, cpuLoadObj.loadSirq),
|
|
])
|
|
);
|
|
},
|
|
},
|
|
|
|
makeCPUTable(cpuLoadArray) {
|
|
let currentView = (this.availableViewModes[this.viewMode] !== undefined) ?
|
|
this[this.availableViewModes[this.viewMode][0]] :
|
|
this[this.availableViewModes[0][0]];
|
|
currentView.makeTable();
|
|
cpuLoadArray.forEach((c, i) => {
|
|
currentView.append(c.cpuNum, c, (this.lastStatArray !== null));
|
|
});
|
|
return currentView.table;
|
|
},
|
|
|
|
load() {
|
|
this.restoreSettingsFromLocalStorage();
|
|
return L.resolveDefault(fs.read('/proc/stat'), null);
|
|
},
|
|
|
|
render(cpuData) {
|
|
if(!cpuData) return;
|
|
|
|
let cpuStatArray = this.parseProcData(cpuData);
|
|
|
|
// For single-core CPU
|
|
if(cpuStatArray.length == 2) {
|
|
cpuStatArray = cpuStatArray.slice(1, 2);
|
|
delete this.availableViewModes[2];
|
|
delete this.availableViewModes[3];
|
|
if(this.viewMode > 1) this.viewMode = 0;
|
|
};
|
|
|
|
let cpuLoadArray = this.calcCPULoad(cpuStatArray);
|
|
let cpuTable = this.makeCPUTable(cpuLoadArray);
|
|
|
|
let viewModeSelectFunc = value => {
|
|
this.saveSettingsToLocalStorage(value);
|
|
this.viewMode = value;
|
|
viewModeEntries.forEach(i => {
|
|
i.classList.remove('cpu-status-view-mode-entry-checked');
|
|
});
|
|
viewModeEntries[value].classList.add('cpu-status-view-mode-entry-checked');
|
|
let newTable = this.makeCPUTable(cpuLoadArray);
|
|
cpuTable.replaceWith(newTable);
|
|
cpuTable = newTable;
|
|
};
|
|
|
|
let viewModeSelectOnClick = ev => {
|
|
viewModeSelectFunc(ev.target.dataset.value);
|
|
ev.target.blur();
|
|
};
|
|
|
|
let viewModeEntries = [];
|
|
|
|
for(let [i, v] of Object.entries(this.availableViewModes)) {
|
|
viewModeEntries.push(
|
|
E('span', {
|
|
'class' : 'cpu-status-view-mode-entry',
|
|
'data-value': i,
|
|
'click' : viewModeSelectOnClick,
|
|
}, v[1])
|
|
);
|
|
};
|
|
|
|
viewModeSelectFunc(this.viewMode);
|
|
|
|
this.lastStatArray = cpuStatArray;
|
|
|
|
return E('div', { 'class': 'cbi-section' }, [
|
|
E('div', { 'style': 'margin-bottom:1em' },
|
|
viewModeEntries
|
|
),
|
|
cpuTable,
|
|
]);
|
|
},
|
|
});
|