mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
Add Memory Monitor VSCode Extension (#6951)
Co-authored-by: openhands <openhands@all-hands.dev> Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
This commit is contained in:
parent
42332294a1
commit
02bc7de36d
@ -64,11 +64,17 @@ RUN if [ -z "${RELEASE_TAG}" ]; then \
|
||||
if [ -d "${OPENVSCODE_SERVER_ROOT}" ]; then rm -rf "${OPENVSCODE_SERVER_ROOT}"; fi && \
|
||||
mv ${RELEASE_TAG}-linux-${arch} ${OPENVSCODE_SERVER_ROOT} && \
|
||||
cp ${OPENVSCODE_SERVER_ROOT}/bin/remote-cli/openvscode-server ${OPENVSCODE_SERVER_ROOT}/bin/remote-cli/code && \
|
||||
rm -f ${RELEASE_TAG}-linux-${arch}.tar.gz && \
|
||||
# Install our custom extension
|
||||
mkdir -p ${OPENVSCODE_SERVER_ROOT}/extensions/openhands-hello-world && \
|
||||
rm -f ${RELEASE_TAG}-linux-${arch}.tar.gz
|
||||
|
||||
{% endmacro %}
|
||||
|
||||
{% macro install_vscode_extensions() %}
|
||||
# Install our custom extension
|
||||
RUN mkdir -p ${OPENVSCODE_SERVER_ROOT}/extensions/openhands-hello-world && \
|
||||
cp -r /openhands/code/openhands/runtime/utils/vscode-extensions/hello-world/* ${OPENVSCODE_SERVER_ROOT}/extensions/openhands-hello-world/
|
||||
|
||||
RUN mkdir -p ${OPENVSCODE_SERVER_ROOT}/extensions/openhands-memory-monitor && \
|
||||
cp -r /openhands/code/openhands/runtime/utils/vscode-extensions/memory-monitor/* ${OPENVSCODE_SERVER_ROOT}/extensions/openhands-memory-monitor/
|
||||
{% endmacro %}
|
||||
|
||||
{% macro install_dependencies() %}
|
||||
@ -147,6 +153,7 @@ RUN chmod a+rwx /openhands/code/openhands/__init__.py
|
||||
# ================================================================
|
||||
{% if build_from_versioned %}
|
||||
{{ install_dependencies() }}
|
||||
{{ install_vscode_extensions() }}
|
||||
{% endif %}
|
||||
|
||||
# Install extra dependencies if specified
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
# OpenHands Memory Monitor
|
||||
|
||||
A VSCode extension for monitoring system and process memory usage in real-time.
|
||||
|
||||
## Features
|
||||
|
||||
- **Real-time Memory Monitoring**: Displays current memory usage in the status bar
|
||||
- **Detailed Memory Information**: View detailed memory statistics in a graphical interface
|
||||
- **Process Monitoring**: See top processes by memory usage
|
||||
- **Memory Usage History**: Track memory usage over time with interactive charts
|
||||
- **Cross-Platform Support**: Works on Windows, macOS, and Linux
|
||||
|
||||
## Usage
|
||||
|
||||
The extension automatically starts monitoring memory usage when VSCode is launched. You can interact with it in the following ways:
|
||||
|
||||
### Status Bar Indicator
|
||||
|
||||
A memory usage indicator is displayed in the status bar showing the current system memory usage percentage. Click on this indicator to open the detailed memory view.
|
||||
|
||||
### Commands
|
||||
|
||||
The following commands are available in the Command Palette (`Ctrl+Shift+P` or `Cmd+Shift+P`):
|
||||
|
||||
- **Start Memory Monitor**: Start monitoring memory usage
|
||||
- **Stop Memory Monitor**: Stop monitoring memory usage
|
||||
- **Show Memory Details**: Open the detailed memory view
|
||||
|
||||
## Detailed Memory View
|
||||
|
||||
The detailed memory view provides comprehensive information about:
|
||||
|
||||
1. **System Memory**: Total, used, and free memory
|
||||
2. **Process Memory**: Memory usage of the VSCode extension host process
|
||||
3. **Memory History**: Chart showing memory usage over time
|
||||
4. **Top Processes**: List of processes using the most memory
|
||||
|
||||
## Development
|
||||
|
||||
This extension is part of the OpenHands project. To modify or extend it:
|
||||
|
||||
1. Make changes to the source files
|
||||
2. Test the extension in a development VSCode instance
|
||||
3. Package the extension for distribution
|
||||
|
||||
## License
|
||||
|
||||
This extension is licensed under the MIT license.
|
||||
@ -0,0 +1,42 @@
|
||||
const vscode = require('vscode');
|
||||
const MemoryMonitor = require('./memory_monitor');
|
||||
|
||||
function activate(context) {
|
||||
// Create memory monitor instance
|
||||
const memoryMonitor = new MemoryMonitor();
|
||||
|
||||
// Store the context in the memory monitor
|
||||
memoryMonitor.context = context;
|
||||
|
||||
// Register memory monitor start command
|
||||
let startMonitorCommand = vscode.commands.registerCommand('openhands-memory-monitor.startMemoryMonitor', function () {
|
||||
memoryMonitor.start();
|
||||
});
|
||||
|
||||
// Register memory monitor stop command
|
||||
let stopMonitorCommand = vscode.commands.registerCommand('openhands-memory-monitor.stopMemoryMonitor', function () {
|
||||
memoryMonitor.stop();
|
||||
});
|
||||
|
||||
// Register memory details command
|
||||
let showMemoryDetailsCommand = vscode.commands.registerCommand('openhands-memory-monitor.showMemoryDetails', function () {
|
||||
memoryMonitor.showDetails();
|
||||
});
|
||||
|
||||
// Add all commands to subscriptions
|
||||
context.subscriptions.push(startMonitorCommand);
|
||||
context.subscriptions.push(stopMonitorCommand);
|
||||
context.subscriptions.push(showMemoryDetailsCommand);
|
||||
|
||||
// Start memory monitoring by default
|
||||
memoryMonitor.start();
|
||||
}
|
||||
|
||||
function deactivate() {
|
||||
// Clean up resources if needed
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
activate,
|
||||
deactivate
|
||||
}
|
||||
@ -0,0 +1,343 @@
|
||||
const os = require('os');
|
||||
const vscode = require('vscode');
|
||||
const ProcessMonitor = require('./process_monitor');
|
||||
|
||||
class MemoryMonitor {
|
||||
constructor() {
|
||||
this.isMonitoring = false;
|
||||
this.intervalId = null;
|
||||
this.statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
|
||||
this.statusBarItem.command = 'openhands-memory-monitor.showMemoryDetails';
|
||||
this.processMonitor = new ProcessMonitor();
|
||||
this.memoryHistory = [];
|
||||
this.maxHistoryLength = 60; // Keep 5 minutes of data with 5-second intervals
|
||||
this.context = null; // Will be set in activate
|
||||
}
|
||||
|
||||
start(interval = 5000) {
|
||||
if (this.isMonitoring) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isMonitoring = true;
|
||||
this.statusBarItem.show();
|
||||
|
||||
// Initial update
|
||||
this.updateMemoryInfo();
|
||||
|
||||
// Set interval for updates
|
||||
this.intervalId = setInterval(() => {
|
||||
this.updateMemoryInfo();
|
||||
}, interval);
|
||||
|
||||
vscode.window.showInformationMessage('Memory monitoring started');
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (!this.isMonitoring) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isMonitoring = false;
|
||||
clearInterval(this.intervalId);
|
||||
this.statusBarItem.hide();
|
||||
|
||||
vscode.window.showInformationMessage('Memory monitoring stopped');
|
||||
}
|
||||
|
||||
updateMemoryInfo() {
|
||||
const totalMem = os.totalmem();
|
||||
const freeMem = os.freemem();
|
||||
const usedMem = totalMem - freeMem;
|
||||
|
||||
// Calculate memory usage percentage
|
||||
const memUsagePercent = Math.round((usedMem / totalMem) * 100);
|
||||
|
||||
// Format memory values to MB
|
||||
const usedMemMB = Math.round(usedMem / (1024 * 1024));
|
||||
const totalMemMB = Math.round(totalMem / (1024 * 1024));
|
||||
|
||||
// Update status bar
|
||||
this.statusBarItem.text = `$(pulse) Mem: ${memUsagePercent}%`;
|
||||
this.statusBarItem.tooltip = `Memory Usage: ${usedMemMB}MB / ${totalMemMB}MB`;
|
||||
|
||||
// Store memory data in history
|
||||
this.memoryHistory.push({
|
||||
timestamp: new Date(),
|
||||
usedMemMB,
|
||||
totalMemMB,
|
||||
memUsagePercent,
|
||||
processMemory: process.memoryUsage()
|
||||
});
|
||||
|
||||
// Limit history length
|
||||
if (this.memoryHistory.length > this.maxHistoryLength) {
|
||||
this.memoryHistory.shift();
|
||||
}
|
||||
}
|
||||
|
||||
showDetails() {
|
||||
// Create and show a webview panel with detailed memory information
|
||||
const panel = vscode.window.createWebviewPanel(
|
||||
'memoryMonitor',
|
||||
'Memory Monitor',
|
||||
vscode.ViewColumn.One,
|
||||
{
|
||||
enableScripts: true
|
||||
}
|
||||
);
|
||||
|
||||
// Set up message handler for real-time updates
|
||||
panel.webview.onDidReceiveMessage(
|
||||
message => {
|
||||
if (message.command === 'requestUpdate') {
|
||||
this.updateWebviewContent(panel);
|
||||
}
|
||||
},
|
||||
undefined,
|
||||
this.context ? this.context.subscriptions : []
|
||||
);
|
||||
|
||||
// Initial update
|
||||
this.updateWebviewContent(panel);
|
||||
|
||||
// Handle panel disposal
|
||||
panel.onDidDispose(() => {
|
||||
// Clean up any resources if needed
|
||||
}, null, this.context ? this.context.subscriptions : []);
|
||||
}
|
||||
|
||||
updateWebviewContent(panel) {
|
||||
// Get system memory info
|
||||
const totalMem = os.totalmem();
|
||||
const freeMem = os.freemem();
|
||||
const usedMem = totalMem - freeMem;
|
||||
|
||||
// Format memory values
|
||||
const usedMemMB = Math.round(usedMem / (1024 * 1024));
|
||||
const freeMemMB = Math.round(freeMem / (1024 * 1024));
|
||||
const totalMemMB = Math.round(totalMem / (1024 * 1024));
|
||||
|
||||
// Get process memory usage
|
||||
const processMemory = process.memoryUsage();
|
||||
const rss = Math.round(processMemory.rss / (1024 * 1024));
|
||||
const heapTotal = Math.round(processMemory.heapTotal / (1024 * 1024));
|
||||
const heapUsed = Math.round(processMemory.heapUsed / (1024 * 1024));
|
||||
|
||||
// Get process information
|
||||
this.processMonitor.getProcessInfo((error, processInfo) => {
|
||||
if (error) {
|
||||
console.error('Error getting process info:', error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create HTML content for the webview
|
||||
const htmlContent = this.generateHtmlReport(
|
||||
usedMemMB, freeMemMB, totalMemMB,
|
||||
rss, heapTotal, heapUsed,
|
||||
processInfo
|
||||
);
|
||||
|
||||
// Set the webview's HTML content
|
||||
panel.webview.html = htmlContent;
|
||||
});
|
||||
}
|
||||
|
||||
generateHtmlReport(usedMemMB, freeMemMB, totalMemMB, rss, heapTotal, heapUsed, processInfo) {
|
||||
// Create memory usage history data for chart
|
||||
const memoryLabels = this.memoryHistory.map((entry, index) => index);
|
||||
const memoryData = this.memoryHistory.map(entry => entry.memUsagePercent);
|
||||
const heapData = this.memoryHistory.map(entry =>
|
||||
Math.round(entry.processMemory.heapUsed / (1024 * 1024))
|
||||
);
|
||||
|
||||
// Format process info table
|
||||
let processTable = '';
|
||||
if (processInfo && processInfo.processes) {
|
||||
processTable = `
|
||||
<h3>Top Processes by Memory Usage</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th>PID</th>
|
||||
<th>Memory %</th>
|
||||
<th>CPU %</th>
|
||||
<th>Command</th>
|
||||
</tr>
|
||||
${processInfo.processes.map(proc => `
|
||||
<tr>
|
||||
<td>${proc.pid}</td>
|
||||
<td>${proc.memPercent}%</td>
|
||||
<td>${proc.cpuPercent || 'N/A'}</td>
|
||||
<td>${proc.cmd}</td>
|
||||
</tr>
|
||||
`).join('')}
|
||||
</table>
|
||||
`;
|
||||
}
|
||||
|
||||
return `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Memory Monitor</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
padding: 20px;
|
||||
color: var(--vscode-foreground);
|
||||
background-color: var(--vscode-editor-background);
|
||||
}
|
||||
.memory-card {
|
||||
background-color: var(--vscode-editor-background);
|
||||
border: 1px solid var(--vscode-panel-border);
|
||||
border-radius: 5px;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.memory-info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
}
|
||||
.memory-stat {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
}
|
||||
.memory-value {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin: 10px 0;
|
||||
}
|
||||
.memory-label {
|
||||
font-size: 14px;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
}
|
||||
.chart-container {
|
||||
height: 300px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 20px 0;
|
||||
}
|
||||
th, td {
|
||||
text-align: left;
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid var(--vscode-panel-border);
|
||||
}
|
||||
th {
|
||||
background-color: var(--vscode-editor-background);
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Memory Monitor</h1>
|
||||
|
||||
<div class="memory-card">
|
||||
<h2>System Memory</h2>
|
||||
<div class="memory-info">
|
||||
<div class="memory-stat">
|
||||
<div class="memory-label">Used Memory</div>
|
||||
<div class="memory-value">${usedMemMB} MB</div>
|
||||
</div>
|
||||
<div class="memory-stat">
|
||||
<div class="memory-label">Free Memory</div>
|
||||
<div class="memory-value">${freeMemMB} MB</div>
|
||||
</div>
|
||||
<div class="memory-stat">
|
||||
<div class="memory-label">Total Memory</div>
|
||||
<div class="memory-value">${totalMemMB} MB</div>
|
||||
</div>
|
||||
<div class="memory-stat">
|
||||
<div class="memory-label">Usage</div>
|
||||
<div class="memory-value">${Math.round(usedMemMB / totalMemMB * 100)}%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="memory-card">
|
||||
<h2>Process Memory (VSCode Extension Host)</h2>
|
||||
<div class="memory-info">
|
||||
<div class="memory-stat">
|
||||
<div class="memory-label">RSS</div>
|
||||
<div class="memory-value">${rss} MB</div>
|
||||
</div>
|
||||
<div class="memory-stat">
|
||||
<div class="memory-label">Heap Used</div>
|
||||
<div class="memory-value">${heapUsed} MB</div>
|
||||
</div>
|
||||
<div class="memory-stat">
|
||||
<div class="memory-label">Heap Total</div>
|
||||
<div class="memory-value">${heapTotal} MB</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="memory-card">
|
||||
<h2>Memory Usage History</h2>
|
||||
<div class="chart-container">
|
||||
<canvas id="memoryChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="memory-card">
|
||||
${processTable}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Create memory usage chart
|
||||
const ctx = document.getElementById('memoryChart').getContext('2d');
|
||||
const memoryChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ${JSON.stringify(memoryLabels)},
|
||||
datasets: [
|
||||
{
|
||||
label: 'System Memory Usage (%)',
|
||||
data: ${JSON.stringify(memoryData)},
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||
tension: 0.4
|
||||
},
|
||||
{
|
||||
label: 'Process Heap Usage (MB)',
|
||||
data: ${JSON.stringify(heapData)},
|
||||
borderColor: 'rgba(255, 99, 132, 1)',
|
||||
backgroundColor: 'rgba(255, 99, 132, 0.2)',
|
||||
tension: 0.4
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Set up real-time updates
|
||||
const vscode = acquireVsCodeApi();
|
||||
|
||||
// Request updates every 5 seconds
|
||||
setInterval(() => {
|
||||
vscode.postMessage({
|
||||
command: 'requestUpdate'
|
||||
});
|
||||
}, 5000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MemoryMonitor;
|
||||
@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "openhands-memory-monitor",
|
||||
"displayName": "OpenHands Memory Monitor",
|
||||
"description": "A VSCode extension for monitoring system and process memory usage",
|
||||
"version": "0.1.0",
|
||||
"publisher": "openhands",
|
||||
"engines": {
|
||||
"vscode": "^1.94.0"
|
||||
},
|
||||
"categories": [
|
||||
"Other",
|
||||
"Monitoring"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onStartupFinished"
|
||||
],
|
||||
"main": "./extension.js",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "openhands-memory-monitor.startMemoryMonitor",
|
||||
"title": "Start Memory Monitor"
|
||||
},
|
||||
{
|
||||
"command": "openhands-memory-monitor.stopMemoryMonitor",
|
||||
"title": "Stop Memory Monitor"
|
||||
},
|
||||
{
|
||||
"command": "openhands-memory-monitor.showMemoryDetails",
|
||||
"title": "Show Memory Details"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
"commandPalette": [
|
||||
{
|
||||
"command": "openhands-memory-monitor.startMemoryMonitor",
|
||||
"group": "OpenHands"
|
||||
},
|
||||
{
|
||||
"command": "openhands-memory-monitor.stopMemoryMonitor",
|
||||
"group": "OpenHands"
|
||||
},
|
||||
{
|
||||
"command": "openhands-memory-monitor.showMemoryDetails",
|
||||
"group": "OpenHands"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,143 @@
|
||||
const { exec } = require('child_process');
|
||||
const os = require('os');
|
||||
|
||||
class ProcessMonitor {
|
||||
constructor() {
|
||||
this.platform = os.platform();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get detailed process information based on the platform
|
||||
* @param {Function} callback - Callback function to receive process data
|
||||
*/
|
||||
getProcessInfo(callback) {
|
||||
if (this.platform === 'linux') {
|
||||
this.getLinuxProcessInfo(callback);
|
||||
} else if (this.platform === 'darwin') {
|
||||
this.getMacProcessInfo(callback);
|
||||
} else if (this.platform === 'win32') {
|
||||
this.getWindowsProcessInfo(callback);
|
||||
} else {
|
||||
callback(new Error(`Unsupported platform: ${this.platform}`), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get process information on Linux
|
||||
* @param {Function} callback - Callback function to receive process data
|
||||
*/
|
||||
getLinuxProcessInfo(callback) {
|
||||
// Get top processes by memory usage
|
||||
exec('ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem | head -n 11', (error, stdout) => {
|
||||
if (error) {
|
||||
callback(error, null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the output
|
||||
const lines = stdout.trim().split('\n');
|
||||
const header = lines[0];
|
||||
const processes = lines.slice(1).map(line => {
|
||||
const parts = line.trim().split(/\s+/);
|
||||
const pid = parts[0];
|
||||
const ppid = parts[1];
|
||||
const memPercent = parseFloat(parts[parts.length - 2]);
|
||||
const cpuPercent = parseFloat(parts[parts.length - 1]);
|
||||
const cmd = parts.slice(2, parts.length - 2).join(' ');
|
||||
|
||||
return {
|
||||
pid,
|
||||
ppid,
|
||||
cmd,
|
||||
memPercent,
|
||||
cpuPercent
|
||||
};
|
||||
});
|
||||
|
||||
callback(null, { header, processes });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get process information on macOS
|
||||
* @param {Function} callback - Callback function to receive process data
|
||||
*/
|
||||
getMacProcessInfo(callback) {
|
||||
// Similar to Linux but with slightly different ps command
|
||||
exec('ps -eo pid,ppid,command,%mem,%cpu -r | head -n 11', (error, stdout) => {
|
||||
if (error) {
|
||||
callback(error, null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the output
|
||||
const lines = stdout.trim().split('\n');
|
||||
const header = lines[0];
|
||||
const processes = lines.slice(1).map(line => {
|
||||
const parts = line.trim().split(/\s+/);
|
||||
const pid = parts[0];
|
||||
const ppid = parts[1];
|
||||
const memPercent = parseFloat(parts[parts.length - 2]);
|
||||
const cpuPercent = parseFloat(parts[parts.length - 1]);
|
||||
const cmd = parts.slice(2, parts.length - 2).join(' ');
|
||||
|
||||
return {
|
||||
pid,
|
||||
ppid,
|
||||
cmd,
|
||||
memPercent,
|
||||
cpuPercent
|
||||
};
|
||||
});
|
||||
|
||||
callback(null, { header, processes });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get process information on Windows
|
||||
* @param {Function} callback - Callback function to receive process data
|
||||
*/
|
||||
getWindowsProcessInfo(callback) {
|
||||
// Windows command to get process info
|
||||
exec('wmic process get ProcessId,ParentProcessId,CommandLine,WorkingSetSize /format:csv', (error, stdout) => {
|
||||
if (error) {
|
||||
callback(error, null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the CSV output
|
||||
const lines = stdout.trim().split('\n');
|
||||
const header = "PID,PPID,Command,Memory (bytes)";
|
||||
|
||||
// Skip empty lines and the header
|
||||
const dataLines = lines.filter(line => line.trim() !== '' && !line.includes('Node,'));
|
||||
|
||||
const processes = dataLines.map(line => {
|
||||
const parts = line.split(',');
|
||||
if (parts.length < 4) return null;
|
||||
|
||||
// Last part is the node name, then ProcessId, ParentProcessId, CommandLine, WorkingSetSize
|
||||
const pid = parts[parts.length - 4];
|
||||
const ppid = parts[parts.length - 3];
|
||||
const cmd = parts[parts.length - 2];
|
||||
const memBytes = parseInt(parts[parts.length - 1], 10);
|
||||
const memPercent = (memBytes / os.totalmem() * 100).toFixed(1);
|
||||
|
||||
return {
|
||||
pid,
|
||||
ppid,
|
||||
cmd,
|
||||
memPercent,
|
||||
memBytes
|
||||
};
|
||||
}).filter(Boolean)
|
||||
.sort((a, b) => b.memBytes - a.memBytes)
|
||||
.slice(0, 10);
|
||||
|
||||
callback(null, { header, processes });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ProcessMonitor;
|
||||
Loading…
x
Reference in New Issue
Block a user