Enhance monitoring features and UI:
- Add detailed CPU core monitoring option for better performance control - Update monitoring settings in app configuration - Improve parallel task execution for resource usage monitoring - Modify Telegram notification service to skip alerts from svchost processes - Add "Memory %" column to process table in HTML and update related JavaScript - Create performance test scripts for API response time evaluation
This commit is contained in:
@@ -8,6 +8,7 @@ namespace ResourceMonitorService.Configuration
|
|||||||
public bool EnableDiskMonitoring { get; set; } = true;
|
public bool EnableDiskMonitoring { get; set; } = true;
|
||||||
public bool EnableTemperatureMonitoring { get; set; } = true;
|
public bool EnableTemperatureMonitoring { get; set; } = true;
|
||||||
public bool EnableProcessMonitoring { get; set; } = true;
|
public bool EnableProcessMonitoring { get; set; } = true;
|
||||||
|
public bool EnableDetailedCpuCoreMonitoring { get; set; } = false; // Disable by default for better performance
|
||||||
public bool EnableGameDetection { get; set; } = true;
|
public bool EnableGameDetection { get; set; } = true;
|
||||||
public bool EnableAlerts { get; set; } = true;
|
public bool EnableAlerts { get; set; } = true;
|
||||||
public int MaxProcessesToTrack { get; set; } = 10;
|
public int MaxProcessesToTrack { get; set; } = 10;
|
||||||
|
|||||||
@@ -96,32 +96,26 @@ namespace ResourceMonitorService.Services
|
|||||||
{
|
{
|
||||||
var timestamp = DateTime.Now;
|
var timestamp = DateTime.Now;
|
||||||
|
|
||||||
var tasks = new List<Task>
|
// Execute all monitoring tasks in parallel and capture results
|
||||||
{
|
var cpuTask = GetCpuUsageAsync();
|
||||||
Task.Run(async () => await GetCpuUsageAsync()),
|
var memoryTask = GetMemoryUsageAsync();
|
||||||
Task.Run(async () => await GetMemoryUsageAsync())
|
var gpuTask = _settings.EnableGpuMonitoring ? GetGpuUsageAsync() : Task.FromResult(new GpuUsage());
|
||||||
};
|
var diskTask = _settings.EnableDiskMonitoring ? GetDiskUsageAsync() : Task.FromResult(new List<DiskUsage>());
|
||||||
|
var processTask = _settings.EnableProcessMonitoring ? GetTopProcessesAsync(_settings.MaxProcessesToTrack) : Task.FromResult(new List<ProcessInfo>());
|
||||||
|
var temperatureTask = _settings.EnableTemperatureMonitoring ? GetTemperatureInfoAsync() : Task.FromResult(new TemperatureInfo());
|
||||||
|
|
||||||
if (_settings.EnableGpuMonitoring)
|
// Wait for all tasks to complete
|
||||||
tasks.Add(Task.Run(async () => await GetGpuUsageAsync()));
|
await Task.WhenAll(cpuTask, memoryTask, gpuTask, diskTask, processTask, temperatureTask);
|
||||||
|
|
||||||
if (_settings.EnableDiskMonitoring)
|
|
||||||
tasks.Add(Task.Run(async () => await GetDiskUsageAsync()));
|
|
||||||
|
|
||||||
if (_settings.EnableProcessMonitoring)
|
|
||||||
tasks.Add(Task.Run(async () => await GetTopProcessesAsync(_settings.MaxProcessesToTrack)));
|
|
||||||
|
|
||||||
await Task.WhenAll(tasks);
|
|
||||||
|
|
||||||
return new ResourceUsage
|
return new ResourceUsage
|
||||||
{
|
{
|
||||||
Timestamp = timestamp,
|
Timestamp = timestamp,
|
||||||
CPU = await GetCpuUsageAsync(),
|
CPU = await cpuTask,
|
||||||
Memory = await GetMemoryUsageAsync(),
|
Memory = await memoryTask,
|
||||||
GPU = _settings.EnableGpuMonitoring ? await GetGpuUsageAsync() : new GpuUsage(),
|
GPU = await gpuTask,
|
||||||
Disks = _settings.EnableDiskMonitoring ? await GetDiskUsageAsync() : new List<DiskUsage>(),
|
Disks = await diskTask,
|
||||||
TopProcesses = _settings.EnableProcessMonitoring ? await GetTopProcessesAsync(_settings.MaxProcessesToTrack) : new List<ProcessInfo>(),
|
TopProcesses = await processTask,
|
||||||
Temperature = _settings.EnableTemperatureMonitoring ? await GetTemperatureInfoAsync() : new TemperatureInfo()
|
Temperature = await temperatureTask
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,20 +130,23 @@ namespace ResourceMonitorService.Services
|
|||||||
#pragma warning disable CA1416 // Validate platform compatibility
|
#pragma warning disable CA1416 // Validate platform compatibility
|
||||||
var usage = _counters.TryGetValue("cpu", out var cpuCounter) ? cpuCounter.NextValue() : 0f;
|
var usage = _counters.TryGetValue("cpu", out var cpuCounter) ? cpuCounter.NextValue() : 0f;
|
||||||
|
|
||||||
// Get per-core usage
|
// Get per-core usage (only if enabled for performance)
|
||||||
var coreUsages = new List<float>();
|
var coreUsages = new List<float>();
|
||||||
for (int i = 0; i < Environment.ProcessorCount; i++)
|
if (_settings.EnableDetailedCpuCoreMonitoring)
|
||||||
{
|
{
|
||||||
try
|
for (int i = 0; i < Environment.ProcessorCount; i++)
|
||||||
{
|
{
|
||||||
using var coreCounter = new PerformanceCounter("Processor", "% Processor Time", i.ToString());
|
try
|
||||||
coreCounter.NextValue();
|
{
|
||||||
Thread.Sleep(100); // Small delay for accurate reading
|
using var coreCounter = new PerformanceCounter("Processor", "% Processor Time", i.ToString());
|
||||||
coreUsages.Add(coreCounter.NextValue());
|
coreCounter.NextValue();
|
||||||
}
|
Thread.Sleep(50); // Reduced delay for faster reading while maintaining accuracy
|
||||||
catch
|
coreUsages.Add(coreCounter.NextValue());
|
||||||
{
|
}
|
||||||
coreUsages.Add(0f);
|
catch
|
||||||
|
{
|
||||||
|
coreUsages.Add(0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,15 @@ namespace ResourceMonitorService.Services
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ignore alerts from svchost processes
|
||||||
|
if (alert.Component.Contains("svchost", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
alert.Message.Contains("svchost", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Skipping Telegram alert for svchost process: {Component} - {Message}",
|
||||||
|
alert.Component, alert.Message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var message = FormatAlertMessage(alert, _telegramSettings.MessageTemplate);
|
var message = FormatAlertMessage(alert, _telegramSettings.MessageTemplate);
|
||||||
|
|
||||||
foreach (var chatId in _telegramSettings.ChatIds)
|
foreach (var chatId in _telegramSettings.ChatIds)
|
||||||
@@ -110,6 +119,15 @@ namespace ResourceMonitorService.Services
|
|||||||
if (_botClient == null || !_telegramSettings.IsEnabled || !_telegramSettings.SendResolutionNotifications)
|
if (_botClient == null || !_telegramSettings.IsEnabled || !_telegramSettings.SendResolutionNotifications)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Ignore alerts from svchost processes
|
||||||
|
if (alert.Component.Contains("svchost", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
alert.Message.Contains("svchost", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Skipping Telegram resolution notification for svchost process: {Component} - {Message}",
|
||||||
|
alert.Component, alert.Message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var message = FormatAlertMessage(alert, _telegramSettings.ResolutionTemplate);
|
var message = FormatAlertMessage(alert, _telegramSettings.ResolutionTemplate);
|
||||||
|
|
||||||
foreach (var chatId in _telegramSettings.ChatIds)
|
foreach (var chatId in _telegramSettings.ChatIds)
|
||||||
|
|||||||
+2
-1
@@ -22,13 +22,14 @@
|
|||||||
"BasePath": "/api"
|
"BasePath": "/api"
|
||||||
},
|
},
|
||||||
"MonitoringSettings": {
|
"MonitoringSettings": {
|
||||||
"UpdateIntervalMs": 120000,
|
"UpdateIntervalMs": 60000,
|
||||||
"DataRetentionDays": 7,
|
"DataRetentionDays": 7,
|
||||||
"EnableGpuMonitoring": true,
|
"EnableGpuMonitoring": true,
|
||||||
"EnableDiskMonitoring": true,
|
"EnableDiskMonitoring": true,
|
||||||
"EnableNetworkMonitoring": true,
|
"EnableNetworkMonitoring": true,
|
||||||
"EnableTemperatureMonitoring": true,
|
"EnableTemperatureMonitoring": true,
|
||||||
"EnableProcessMonitoring": true,
|
"EnableProcessMonitoring": true,
|
||||||
|
"EnableDetailedCpuCoreMonitoring": false,
|
||||||
"EnableGameDetection": true,
|
"EnableGameDetection": true,
|
||||||
"EnableAlerts": true,
|
"EnableAlerts": true,
|
||||||
"MaxProcessesToTrack": 10,
|
"MaxProcessesToTrack": 10,
|
||||||
|
|||||||
@@ -77,6 +77,25 @@ try {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check if service is currently running and stop it before building
|
||||||
|
Write-Host "Checking for existing service..."
|
||||||
|
try {
|
||||||
|
$existingService = Get-Service -Name $SERVICE_NAME -ErrorAction SilentlyContinue
|
||||||
|
if ($existingService) {
|
||||||
|
Write-Host "Found existing service: $($existingService.Status)" -ForegroundColor Yellow
|
||||||
|
if ($existingService.Status -eq "Running") {
|
||||||
|
Write-Host "Stopping running service before build..."
|
||||||
|
Stop-Service -Name $SERVICE_NAME -Force -ErrorAction Stop
|
||||||
|
Write-Host "Service stopped successfully" -ForegroundColor Green
|
||||||
|
Start-Sleep -Seconds 2 # Give it a moment to fully stop
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Host "No existing service found" -ForegroundColor Gray
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Host "Warning: Could not check existing service status: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
# Build the service in release mode
|
# Build the service in release mode
|
||||||
Write-Host "Building service..."
|
Write-Host "Building service..."
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Quick API Test Command
|
||||||
|
# Run this after starting the service with: dotnet run
|
||||||
|
|
||||||
|
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
|
||||||
|
try {
|
||||||
|
$response = Invoke-WebRequest -Uri "http://localhost:5000/api/resource/usage" -UseBasicParsing
|
||||||
|
$stopwatch.Stop()
|
||||||
|
$content = $response.Content | ConvertFrom-Json
|
||||||
|
|
||||||
|
Write-Host "✅ API Response Time: $($stopwatch.ElapsedMilliseconds)ms" -ForegroundColor Green
|
||||||
|
Write-Host " Status: $($response.StatusCode)" -ForegroundColor Cyan
|
||||||
|
Write-Host " CPU Usage: $($content.CPU.Usage)%" -ForegroundColor White
|
||||||
|
Write-Host " Memory Usage: $($content.Memory.UsagePercentage)%" -ForegroundColor White
|
||||||
|
Write-Host " Core Count: $($content.CPU.CoreUsages.Length)" -ForegroundColor White
|
||||||
|
|
||||||
|
if ($stopwatch.ElapsedMilliseconds -lt 1000) {
|
||||||
|
Write-Host "🚀 Excellent performance!" -ForegroundColor Green
|
||||||
|
} elseif ($stopwatch.ElapsedMilliseconds -lt 2000) {
|
||||||
|
Write-Host "✅ Good performance" -ForegroundColor Yellow
|
||||||
|
} else {
|
||||||
|
Write-Host "⚠️ Could be faster" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$stopwatch.Stop()
|
||||||
|
Write-Host "❌ Error after $($stopwatch.ElapsedMilliseconds)ms: $($_.Exception.Message)" -ForegroundColor Red
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# Performance test script for ResourceUsage API
|
||||||
|
Write-Host "Waiting for service to start..." -ForegroundColor Yellow
|
||||||
|
Start-Sleep -Seconds 5
|
||||||
|
|
||||||
|
Write-Host "Testing API response time..." -ForegroundColor Green
|
||||||
|
$times = @()
|
||||||
|
$errors = 0
|
||||||
|
|
||||||
|
for ($i = 1; $i -le 5; $i++) {
|
||||||
|
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
|
||||||
|
try {
|
||||||
|
$response = Invoke-WebRequest -Uri "http://localhost:5000/api/resource/usage" -UseBasicParsing -TimeoutSec 30
|
||||||
|
$stopwatch.Stop()
|
||||||
|
$time = $stopwatch.ElapsedMilliseconds
|
||||||
|
$times += $time
|
||||||
|
Write-Host "Test $i - Response time: ${time}ms - Status: $($response.StatusCode)" -ForegroundColor Cyan
|
||||||
|
|
||||||
|
# Show first response content for verification
|
||||||
|
if ($i -eq 1) {
|
||||||
|
$jsonContent = $response.Content | ConvertFrom-Json
|
||||||
|
Write-Host "Sample response - CPU Usage: $($jsonContent.CPU.Usage)%" -ForegroundColor White
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$stopwatch.Stop()
|
||||||
|
$errors++
|
||||||
|
Write-Host "Test $i - Error after $($stopwatch.ElapsedMilliseconds)ms: $($_.Exception.Message)" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($i -lt 5) {
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($times.Count -gt 0) {
|
||||||
|
$avgTime = ($times | Measure-Object -Average).Average
|
||||||
|
$minTime = ($times | Measure-Object -Minimum).Minimum
|
||||||
|
$maxTime = ($times | Measure-Object -Maximum).Maximum
|
||||||
|
|
||||||
|
Write-Host "`nPerformance Results:" -ForegroundColor Green
|
||||||
|
Write-Host " Average response time: $([math]::Round($avgTime, 2))ms" -ForegroundColor White
|
||||||
|
Write-Host " Minimum response time: ${minTime}ms" -ForegroundColor White
|
||||||
|
Write-Host " Maximum response time: ${maxTime}ms" -ForegroundColor White
|
||||||
|
Write-Host " Successful requests: $($times.Count)/5" -ForegroundColor White
|
||||||
|
Write-Host " Failed requests: $errors/5" -ForegroundColor White
|
||||||
|
|
||||||
|
if ($avgTime -lt 1000) {
|
||||||
|
Write-Host "✅ Performance looks good!" -ForegroundColor Green
|
||||||
|
} elseif ($avgTime -lt 3000) {
|
||||||
|
Write-Host "⚠️ Performance is acceptable but could be better" -ForegroundColor Yellow
|
||||||
|
} else {
|
||||||
|
Write-Host "❌ Performance needs improvement" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Host "❌ All requests failed!" -ForegroundColor Red
|
||||||
|
}
|
||||||
@@ -140,6 +140,7 @@
|
|||||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Process</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Process</th>
|
||||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">CPU %</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">CPU %</th>
|
||||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Memory</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Memory</th>
|
||||||
|
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Memory %</th>
|
||||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Action</th>
|
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|||||||
@@ -428,7 +428,7 @@ class ResourceDashboard {
|
|||||||
|
|
||||||
if (!processes || !Array.isArray(processes)) {
|
if (!processes || !Array.isArray(processes)) {
|
||||||
const row = document.createElement('tr');
|
const row = document.createElement('tr');
|
||||||
row.innerHTML = '<td colspan="4" class="px-4 py-4 text-center text-gray-500">No process data available</td>';
|
row.innerHTML = '<td colspan="5" class="px-4 py-4 text-center text-gray-500">No process data available</td>';
|
||||||
tableBody.appendChild(row);
|
tableBody.appendChild(row);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -448,6 +448,7 @@ class ResourceDashboard {
|
|||||||
const processId = process.processId || 0;
|
const processId = process.processId || 0;
|
||||||
const cpuUsage = process.cpuUsage || 0;
|
const cpuUsage = process.cpuUsage || 0;
|
||||||
const memoryUsage = process.memoryUsage || 0;
|
const memoryUsage = process.memoryUsage || 0;
|
||||||
|
const memoryUsagePercentage = process.memoryUsagePercentage || 0;
|
||||||
|
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<td class="px-4 py-4 whitespace-nowrap">
|
<td class="px-4 py-4 whitespace-nowrap">
|
||||||
@@ -462,6 +463,9 @@ class ResourceDashboard {
|
|||||||
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-900">
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-900">
|
||||||
${(memoryUsage / 1024 / 1024).toFixed(1)} MB
|
${(memoryUsage / 1024 / 1024).toFixed(1)} MB
|
||||||
</td>
|
</td>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-900">
|
||||||
|
${memoryUsagePercentage.toFixed(1)}%
|
||||||
|
</td>
|
||||||
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-900">
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-900">
|
||||||
<button onclick="dashboard.killProcess(${processId}, '${processName}')"
|
<button onclick="dashboard.killProcess(${processId}, '${processName}')"
|
||||||
class="${killButtonClass}" ${killButtonDisabled}>
|
class="${killButtonClass}" ${killButtonDisabled}>
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Process Table Test</title>
|
||||||
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-gray-100 p-8">
|
||||||
|
<div class="max-w-4xl mx-auto">
|
||||||
|
<h1 class="text-2xl font-bold mb-6">Process Table with Memory Percentage</h1>
|
||||||
|
|
||||||
|
<div class="bg-white rounded-lg shadow-lg p-6">
|
||||||
|
<h2 class="text-xl font-bold text-gray-800 mb-4">
|
||||||
|
<i class="fas fa-list mr-2"></i>Top Processes
|
||||||
|
</h2>
|
||||||
|
<div class="overflow-x-auto">
|
||||||
|
<table class="min-w-full table-auto">
|
||||||
|
<thead>
|
||||||
|
<tr class="bg-gray-50">
|
||||||
|
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Process</th>
|
||||||
|
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">CPU %</th>
|
||||||
|
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Memory</th>
|
||||||
|
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Memory %</th>
|
||||||
|
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr class="hover:bg-gray-50">
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="text-sm font-medium text-gray-900">chrome.exe</div>
|
||||||
|
<div class="text-sm text-gray-500 ml-2">PID: 1234</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-900">15.2%</td>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-900">512.3 MB</td>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-900">3.2%</td>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-900">
|
||||||
|
<button class="bg-red-500 hover:bg-red-700 text-white px-2 py-1 rounded text-xs">
|
||||||
|
Kill
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="hover:bg-gray-50">
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="text-sm font-medium text-gray-900">notepad.exe</div>
|
||||||
|
<div class="text-sm text-gray-500 ml-2">PID: 5678</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-900">2.1%</td>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-900">25.6 MB</td>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-900">0.2%</td>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-900">
|
||||||
|
<button class="bg-red-500 hover:bg-red-700 text-white px-2 py-1 rounded text-xs">
|
||||||
|
Kill
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-6 p-4 bg-green-100 border border-green-200 rounded-lg">
|
||||||
|
<h3 class="font-bold text-green-800">✅ Changes Made:</h3>
|
||||||
|
<ul class="list-disc list-inside text-green-700 mt-2">
|
||||||
|
<li>Added "Memory %" column to the process table</li>
|
||||||
|
<li>Updated HTML table header to include the new column</li>
|
||||||
|
<li>Modified JavaScript to display memory percentage from backend data</li>
|
||||||
|
<li>Backend already calculates MemoryUsagePercentage based on total system memory</li>
|
||||||
|
<li>Updated colspan for "No data" message from 4 to 5 columns</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user