secubox-openwrt/luci-app-netdata-dashboard/htdocs/luci-static/resources/view/netdata-dashboard/processes.js

170 lines
5.9 KiB
JavaScript

'use strict';
'require view';
'require secubox-theme/bootstrap as Theme';
'require poll';
'require dom';
'require ui';
'require netdata-dashboard.api as api';
return view.extend({
title: _('Processes'),
load: function() {
return api.getProcesses();
},
render: function(data) {
var procs = data || {};
var topProcs = procs.top || [];
var view = E('div', { 'class': 'netdata-dashboard' }, [
// Header
E('div', { 'class': 'nd-header' }, [
E('div', { 'class': 'nd-logo' }, [
E('div', { 'class': 'nd-logo-icon' }, '⚙️'),
E('div', { 'class': 'nd-logo-text' }, ['Process ', E('span', {}, 'Monitor')])
]),
E('div', { 'class': 'nd-header-info' }, [
E('div', { 'class': 'nd-live-badge' }, [
E('span', { 'class': 'nd-live-dot' }),
'Live'
])
])
]),
// Quick Stats
E('div', { 'class': 'nd-quick-stats' }, [
E('div', { 'class': 'nd-quick-stat' }, [
E('div', { 'class': 'nd-quick-stat-value info' }, procs.total || 0),
E('div', { 'class': 'nd-quick-stat-label' }, 'Total Processes')
]),
E('div', { 'class': 'nd-quick-stat' }, [
E('div', { 'class': 'nd-quick-stat-value good' }, procs.running || 0),
E('div', { 'class': 'nd-quick-stat-label' }, 'Running')
]),
E('div', { 'class': 'nd-quick-stat' }, [
E('div', { 'class': 'nd-quick-stat-value warning' }, procs.sleeping || 0),
E('div', { 'class': 'nd-quick-stat-label' }, 'Sleeping')
])
]),
// Process List
E('div', { 'class': 'nd-chart-card', 'style': 'margin-top:16px' }, [
E('div', { 'class': 'nd-chart-header' }, [
E('div', { 'class': 'nd-chart-title' }, [
E('span', { 'class': 'nd-chart-title-icon' }, '📋'),
'Process List'
]),
E('div', { 'class': 'nd-chart-value' }, topProcs.length + ' processes')
]),
E('div', { 'class': 'nd-chart-body', 'style': 'padding:0;overflow-x:auto' }, [
E('table', { 'class': 'nd-table' }, [
E('thead', {}, [
E('tr', {}, [
E('th', { 'style': 'width:80px' }, 'PID'),
E('th', { 'style': 'width:100px' }, 'User'),
E('th', {}, 'Command'),
E('th', { 'style': 'width:100px' }, 'Memory'),
E('th', { 'style': 'width:80px' }, 'State')
])
]),
E('tbody', {},
topProcs.map(function(proc) {
var stateText = '';
var stateClass = '';
switch(proc.state) {
case 'R': stateText = 'Running'; stateClass = 'up'; break;
case 'S': stateText = 'Sleeping'; stateClass = 'unknown'; break;
case 'D': stateText = 'Disk'; stateClass = 'warning'; break;
case 'Z': stateText = 'Zombie'; stateClass = 'down'; break;
case 'T': stateText = 'Stopped'; stateClass = 'down'; break;
default: stateText = proc.state; stateClass = 'unknown';
}
return E('tr', {}, [
E('td', { 'class': 'mono' }, proc.pid),
E('td', {}, proc.user || 'root'),
E('td', { 'title': proc.cmd }, E('code', { 'style': 'font-size:11px;color:#58a6ff' }, proc.cmd || '-')),
E('td', { 'class': 'mono value' }, api.formatKB(proc.vsz || 0)),
E('td', {}, E('span', { 'class': 'nd-status ' + stateClass }, stateText))
]);
})
)
])
])
]),
// Process State Distribution
E('div', { 'class': 'nd-charts-grid', 'style': 'margin-top:16px' }, [
E('div', { 'class': 'nd-chart-card' }, [
E('div', { 'class': 'nd-chart-header' }, [
E('div', { 'class': 'nd-chart-title' }, [
E('span', { 'class': 'nd-chart-title-icon' }, '📊'),
'Process States'
])
]),
E('div', { 'class': 'nd-chart-body' }, [
E('div', { 'class': 'nd-bar-chart' }, [
E('div', { 'class': 'nd-bar-item' }, [
E('span', { 'class': 'nd-bar-label' }, 'Running'),
E('div', { 'class': 'nd-bar-track' }, [
E('div', {
'class': 'nd-bar-fill',
'style': 'width:' + (procs.total > 0 ? (procs.running / procs.total) * 100 : 0) + '%;background:linear-gradient(90deg,#3fb950,#56d364)'
})
]),
E('span', { 'class': 'nd-bar-value' }, procs.running || 0)
]),
E('div', { 'class': 'nd-bar-item' }, [
E('span', { 'class': 'nd-bar-label' }, 'Sleeping'),
E('div', { 'class': 'nd-bar-track' }, [
E('div', {
'class': 'nd-bar-fill',
'style': 'width:' + (procs.total > 0 ? (procs.sleeping / procs.total) * 100 : 0) + '%;background:linear-gradient(90deg,#58a6ff,#79c0ff)'
})
]),
E('span', { 'class': 'nd-bar-value' }, procs.sleeping || 0)
])
])
])
]),
// Memory Usage by Processes
E('div', { 'class': 'nd-chart-card' }, [
E('div', { 'class': 'nd-chart-header' }, [
E('div', { 'class': 'nd-chart-title' }, [
E('span', { 'class': 'nd-chart-title-icon' }, '🧠'),
'Top Memory Consumers'
])
]),
E('div', { 'class': 'nd-chart-body' }, [
E('div', { 'class': 'nd-bar-chart' },
topProcs.slice(0, 5).map(function(proc, i) {
var maxMem = topProcs[0] ? topProcs[0].vsz : 1;
var pct = maxMem > 0 ? (proc.vsz / maxMem) * 100 : 0;
var colors = ['#3fb950', '#58a6ff', '#a371f7', '#d29922', '#f85149'];
return E('div', { 'class': 'nd-bar-item' }, [
E('span', { 'class': 'nd-bar-label', 'title': proc.cmd }, proc.cmd ? proc.cmd.split('/').pop().substring(0, 12) : 'PID ' + proc.pid),
E('div', { 'class': 'nd-bar-track' }, [
E('div', { 'class': 'nd-bar-fill', 'style': 'width:' + pct + '%;background:' + colors[i % colors.length] })
]),
E('span', { 'class': 'nd-bar-value' }, api.formatKB(proc.vsz || 0))
]);
})
)
])
])
])
]);
var cssLink = E('link', { 'rel': 'stylesheet', 'href': L.resource('netdata-dashboard/dashboard.css') });
document.head.appendChild(cssLink);
return view;
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});