...
This commit is contained in:
89
pkg/heroagent/web/static/js/charts/cpu-chart.js
Normal file
89
pkg/heroagent/web/static/js/charts/cpu-chart.js
Normal file
@@ -0,0 +1,89 @@
|
||||
// CPU chart initialization and update functions
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Background color for charts
|
||||
var chartBgColor = '#1e1e2f';
|
||||
|
||||
// Initialize CPU chart
|
||||
var cpuChartDom = document.getElementById('cpu-chart');
|
||||
if (!cpuChartDom) return;
|
||||
|
||||
var cpuChart = echarts.init(cpuChartDom, {renderer: 'canvas', useDirtyRect: false, backgroundColor: chartBgColor});
|
||||
var cpuOption = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: function(params) {
|
||||
// Get the PID from the data
|
||||
var pid = params.data.pid || 'N/A';
|
||||
return params.seriesName + '<br/>' +
|
||||
params.name + ' (PID: ' + pid + ')<br/>' +
|
||||
'CPU: ' + Math.round(params.value) + '%';
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 10,
|
||||
top: 'center',
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
},
|
||||
formatter: function(name) {
|
||||
// Display full process name without truncation
|
||||
return name;
|
||||
},
|
||||
itemGap: 8,
|
||||
itemWidth: 15,
|
||||
padding: 10
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Process CPU Usage',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: true,
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: [{ name: 'Loading...', value: 100 }]
|
||||
}
|
||||
]
|
||||
};
|
||||
cpuChart.setOption(cpuOption);
|
||||
|
||||
// Function to update CPU chart
|
||||
window.updateCpuChart = function(processes) {
|
||||
// Calculate total CPU usage for top 5 processes
|
||||
var topProcesses = processes.slice(0, 5);
|
||||
var cpuUsageData = topProcesses.map(p => ({
|
||||
name: p.name, // Use full process name
|
||||
value: p.cpu_percent,
|
||||
pid: p.pid // Store PID for tooltip
|
||||
}));
|
||||
|
||||
// Update chart option
|
||||
cpuOption.series[0].data = cpuUsageData;
|
||||
|
||||
// Apply updated option
|
||||
cpuChart.setOption(cpuOption);
|
||||
};
|
||||
|
||||
// Handle window resize
|
||||
window.addEventListener('resize', function() {
|
||||
cpuChart && cpuChart.resize();
|
||||
});
|
||||
});
|
96
pkg/heroagent/web/static/js/charts/memory-chart.js
Normal file
96
pkg/heroagent/web/static/js/charts/memory-chart.js
Normal file
@@ -0,0 +1,96 @@
|
||||
// Memory chart initialization and update functions
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Background color for charts
|
||||
var chartBgColor = '#1e1e2f';
|
||||
|
||||
// Initialize Memory chart
|
||||
var memoryChartDom = document.getElementById('memory-chart');
|
||||
if (!memoryChartDom) return;
|
||||
|
||||
var memoryChart = echarts.init(memoryChartDom, {renderer: 'canvas', useDirtyRect: false, backgroundColor: chartBgColor});
|
||||
var memoryOption = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: function(params) {
|
||||
// Get the PID from the data
|
||||
var pid = params.data.pid || 'N/A';
|
||||
return params.seriesName + '<br/>' +
|
||||
params.name + ' (PID: ' + pid + ')<br/>' +
|
||||
'Memory: ' + Math.round(params.value) + ' MB';
|
||||
},
|
||||
textStyle: {
|
||||
fontSize: 14
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 10,
|
||||
top: 'center',
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
},
|
||||
formatter: function(name) {
|
||||
// Display full process name without truncation
|
||||
return name;
|
||||
},
|
||||
itemGap: 12, // Increased gap for better readability
|
||||
itemWidth: 15,
|
||||
padding: 10
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Process Memory Usage',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: true,
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: [{ name: 'Loading...', value: 100 }]
|
||||
}
|
||||
]
|
||||
};
|
||||
memoryChart.setOption(memoryOption);
|
||||
|
||||
// Function to update Memory chart
|
||||
window.updateMemoryChart = function(processes) {
|
||||
// Sort processes by memory usage (descending)
|
||||
var topProcesses = processes
|
||||
.slice()
|
||||
.sort((a, b) => b.memory_mb - a.memory_mb)
|
||||
.slice(0, 5);
|
||||
|
||||
var memoryUsageData = topProcesses.map(p => ({
|
||||
name: p.name, // Use full process name
|
||||
value: p.memory_mb,
|
||||
pid: p.pid // Store PID for tooltip
|
||||
}));
|
||||
|
||||
// Update chart option
|
||||
memoryOption.series[0].data = memoryUsageData;
|
||||
|
||||
// Apply updated option
|
||||
memoryChart.setOption(memoryOption);
|
||||
};
|
||||
|
||||
// Handle window resize
|
||||
window.addEventListener('resize', function() {
|
||||
memoryChart && memoryChart.resize();
|
||||
});
|
||||
});
|
116
pkg/heroagent/web/static/js/charts/network-chart.js
Normal file
116
pkg/heroagent/web/static/js/charts/network-chart.js
Normal file
@@ -0,0 +1,116 @@
|
||||
// Network chart initialization and update functions
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Background color for charts
|
||||
var chartBgColor = '#1e1e2f';
|
||||
|
||||
// Initialize network chart
|
||||
var networkChartDom = document.getElementById('network-chart');
|
||||
if (!networkChartDom) return;
|
||||
|
||||
var networkChart = echarts.init(networkChartDom, {renderer: 'canvas', useDirtyRect: false, backgroundColor: chartBgColor});
|
||||
var networkOption = {
|
||||
title: {
|
||||
text: 'Network Traffic',
|
||||
left: 'center',
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
legend: {
|
||||
data: ['Upload', 'Download'],
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
},
|
||||
bottom: 10
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: [],
|
||||
axisLabel: {
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
formatter: '{value} KB/s'
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Upload',
|
||||
type: 'line',
|
||||
data: []
|
||||
},
|
||||
{
|
||||
name: 'Download',
|
||||
type: 'line',
|
||||
data: []
|
||||
}
|
||||
]
|
||||
};
|
||||
networkChart.setOption(networkOption);
|
||||
|
||||
// Data for network chart
|
||||
var timestamps = [];
|
||||
var uploadData = [];
|
||||
var downloadData = [];
|
||||
|
||||
// Function to update network chart
|
||||
window.updateNetworkChart = function(upSpeed, downSpeed) {
|
||||
// Convert speeds to KB/s for consistent units
|
||||
var upKBps = convertToKBps(upSpeed);
|
||||
var downKBps = convertToKBps(downSpeed);
|
||||
|
||||
// Add current timestamp
|
||||
var now = new Date();
|
||||
var timeString = now.getHours() + ':' +
|
||||
(now.getMinutes() < 10 ? '0' + now.getMinutes() : now.getMinutes()) + ':' +
|
||||
(now.getSeconds() < 10 ? '0' + now.getSeconds() : now.getSeconds());
|
||||
|
||||
// Update data arrays
|
||||
timestamps.push(timeString);
|
||||
uploadData.push(upKBps);
|
||||
downloadData.push(downKBps);
|
||||
|
||||
// Keep only the last 10 data points
|
||||
if (timestamps.length > 10) {
|
||||
timestamps.shift();
|
||||
uploadData.shift();
|
||||
downloadData.shift();
|
||||
}
|
||||
|
||||
// Update chart option
|
||||
networkOption.xAxis.data = timestamps;
|
||||
networkOption.series[0].data = uploadData;
|
||||
networkOption.series[1].data = downloadData;
|
||||
|
||||
// Apply updated option
|
||||
networkChart.setOption(networkOption);
|
||||
};
|
||||
|
||||
// Helper function to convert network speeds to KB/s
|
||||
function convertToKBps(speedString) {
|
||||
var value = parseFloat(speedString);
|
||||
var unit = speedString.replace(/[\d.]/g, '');
|
||||
|
||||
if (unit === 'Mbps') {
|
||||
return value * 125; // 1 Mbps = 125 KB/s
|
||||
} else if (unit === 'Kbps') {
|
||||
return value / 8; // 1 Kbps = 0.125 KB/s
|
||||
} else if (unit === 'Gbps') {
|
||||
return value * 125000; // 1 Gbps = 125000 KB/s
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle window resize
|
||||
window.addEventListener('resize', function() {
|
||||
networkChart && networkChart.resize();
|
||||
});
|
||||
});
|
88
pkg/heroagent/web/static/js/charts/stats-fetcher.js
Normal file
88
pkg/heroagent/web/static/js/charts/stats-fetcher.js
Normal file
@@ -0,0 +1,88 @@
|
||||
// Data fetching functions for system stats
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Function to fetch hardware stats
|
||||
function fetchHardwareStats() {
|
||||
fetch('/api/hardware-stats')
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
// Extract network speeds
|
||||
var upSpeed = data.network && data.network.upload_speed ? data.network.upload_speed : '0Mbps';
|
||||
var downSpeed = data.network && data.network.download_speed ? data.network.download_speed : '0Mbps';
|
||||
|
||||
// Update the network chart
|
||||
if (window.updateNetworkChart) {
|
||||
window.updateNetworkChart(upSpeed, downSpeed);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching hardware stats:', error);
|
||||
});
|
||||
}
|
||||
|
||||
// Function to fetch process stats
|
||||
function fetchProcessStats() {
|
||||
fetch('/api/process-stats')
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
// Update the CPU and Memory charts with new data
|
||||
if (window.updateCpuChart && data.processes) {
|
||||
window.updateCpuChart(data.processes);
|
||||
}
|
||||
if (window.updateMemoryChart && data.processes) {
|
||||
window.updateMemoryChart(data.processes);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching process stats:', error);
|
||||
});
|
||||
}
|
||||
|
||||
// Function to fetch all stats
|
||||
function fetchAllStats() {
|
||||
fetchHardwareStats();
|
||||
fetchProcessStats();
|
||||
|
||||
// Schedule the next update - use requestAnimationFrame for smoother updates
|
||||
requestAnimationFrame(function() {
|
||||
setTimeout(fetchAllStats, 2000); // Update every 2 seconds
|
||||
});
|
||||
}
|
||||
|
||||
// Start fetching all stats if we're on the system info page
|
||||
if (document.getElementById('cpu-chart') ||
|
||||
document.getElementById('memory-chart') ||
|
||||
document.getElementById('network-chart')) {
|
||||
fetchAllStats();
|
||||
}
|
||||
|
||||
// Also update the chart when new hardware stats are loaded via Unpoly
|
||||
document.addEventListener('up:fragment:loaded', function(event) {
|
||||
if (event.target && event.target.classList.contains('hardware-stats')) {
|
||||
// Extract network speeds from the table
|
||||
var networkCell = event.target.querySelector('tr:nth-child(4) td');
|
||||
if (networkCell) {
|
||||
var networkText = networkCell.textContent;
|
||||
var upMatch = networkText.match(/Up: ([\d.]+Mbps)/);
|
||||
var downMatch = networkText.match(/Down: ([\d.]+Mbps)/);
|
||||
|
||||
var upSpeed = upMatch ? upMatch[1] : '0Mbps';
|
||||
var downSpeed = downMatch ? downMatch[1] : '0Mbps';
|
||||
|
||||
// Update the chart with new data
|
||||
if (window.updateNetworkChart) {
|
||||
window.updateNetworkChart(upSpeed, downSpeed);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user