mirror of
https://github.com/ryzij/ServerMonitor.git
synced 2026-07-14 03:46:58 +00:00
Добавил метод для получения нагрузки на процессор
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
namespace MonitorAgent.API.Contracts;
|
||||||
|
|
||||||
|
public class CpuUsageResponse(decimal total, IEnumerable<decimal> cores)
|
||||||
|
{
|
||||||
|
public decimal Total { get; set; } = total;
|
||||||
|
public List<decimal> Cores { get; set; } = new([.. cores]);
|
||||||
|
}
|
||||||
@@ -1,11 +1,15 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using MonitorAgent.API.Contracts;
|
using MonitorAgent.API.Contracts;
|
||||||
|
using MonitorAgent.Application.Services;
|
||||||
using MonitorAgent.Core.Abstraction;
|
using MonitorAgent.Core.Abstraction;
|
||||||
namespace MonitorAgent.API.Controllers;
|
namespace MonitorAgent.API.Controllers;
|
||||||
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("[controller]")]
|
[Route("[controller]")]
|
||||||
public class MonitorController(IMonitorService monitorService) : ControllerBase
|
public class MonitorController(
|
||||||
|
IMonitorService monitorService,
|
||||||
|
CpuMonitorBackgroundService cpuMonitorService)
|
||||||
|
: ControllerBase
|
||||||
{
|
{
|
||||||
[HttpGet("uptime")]
|
[HttpGet("uptime")]
|
||||||
public async Task<ActionResult<decimal>> GetUptimeAsync(CancellationToken cancellationToken = default)
|
public async Task<ActionResult<decimal>> GetUptimeAsync(CancellationToken cancellationToken = default)
|
||||||
@@ -30,9 +34,18 @@ public class MonitorController(IMonitorService monitorService) : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("loadavg")]
|
[HttpGet("loadavg")]
|
||||||
public async Task<ActionResult<LoadAverageResponse>> GetActionResultAsync(CancellationToken cancellationToken = default)
|
public async Task<ActionResult<LoadAverageResponse>> GetLoadAverageAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var response = new LoadAverageResponse(await monitorService.GetLoadAverageAsync(cancellationToken));
|
var response = new LoadAverageResponse(await monitorService.GetLoadAverageAsync(cancellationToken));
|
||||||
return Ok(response);
|
return Ok(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("cpuUsage")]
|
||||||
|
public async Task<ActionResult<CpuUsageResponse>> GetCpuUsageAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var usage = await cpuMonitorService.GetCpuUsageAsync(cancellationToken);
|
||||||
|
var response = new CpuUsageResponse(usage.TotalUsagePercent, usage.CoresUsagePercent);
|
||||||
|
|
||||||
|
return Ok(response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using MonitorAgent.Core.Abstraction;
|
using MonitorAgent.Core.Abstraction;
|
||||||
using MonitorAgent.Application.Services;
|
using MonitorAgent.Application.Services;
|
||||||
|
using MonitorAgent.Application.Settings;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
@@ -12,7 +13,12 @@ builder.Services.AddOpenApi();
|
|||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
builder.Services.Configure<CpuMonitorSettings>(builder.Configuration.GetSection("CpuMonitorSettings"));
|
||||||
|
|
||||||
builder.Services.AddScoped<IMonitorService, MonitorService>();
|
builder.Services.AddScoped<IMonitorService, MonitorService>();
|
||||||
|
builder.Services.AddSingleton<RawCpuMonitorService>();
|
||||||
|
builder.Services.AddSingleton<CpuMonitorBackgroundService>();
|
||||||
|
builder.Services.AddHostedService(provider => provider.GetRequiredService<CpuMonitorBackgroundService>());
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
|||||||
@@ -5,5 +5,8 @@
|
|||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*"
|
"AllowedHosts": "*",
|
||||||
|
"CpuMonitorSettings": {
|
||||||
|
"DelayTime": 2000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
<ProjectReference Include="..\MonitorAgent.Core\MonitorAgent.Core.csproj" />
|
<ProjectReference Include="..\MonitorAgent.Core\MonitorAgent.Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net10.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using MonitorAgent.Application.Settings;
|
||||||
|
using MonitorAgent.Core.Models;
|
||||||
|
|
||||||
|
namespace MonitorAgent.Application.Services;
|
||||||
|
|
||||||
|
public class CpuMonitorBackgroundService(
|
||||||
|
RawCpuMonitorService cpuMonitorService,
|
||||||
|
IOptions<CpuMonitorSettings> options,
|
||||||
|
ILogger<CpuMonitorBackgroundService> logger) : BackgroundService
|
||||||
|
{
|
||||||
|
private RawCpuStatsCollection? _prevStats;
|
||||||
|
private RawCpuStatsCollection? _nextStats;
|
||||||
|
|
||||||
|
public async Task<CpuUsage> GetCpuUsageAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
RawCpuStatsCollection prev, next;
|
||||||
|
if (_prevStats != null)
|
||||||
|
prev = _prevStats;
|
||||||
|
else
|
||||||
|
prev = await cpuMonitorService.ParseRawCpuStatsAsync(cancellationToken);
|
||||||
|
if (_nextStats != null)
|
||||||
|
next = _nextStats;
|
||||||
|
else
|
||||||
|
next = await cpuMonitorService.ParseRawCpuStatsAsync(cancellationToken);
|
||||||
|
|
||||||
|
var total = CalcUsage(prev.Total, next.Total);
|
||||||
|
var cores = new List<decimal>(prev.Cores.Count);
|
||||||
|
for (int i = 0; i < prev.Cores.Count; i++)
|
||||||
|
cores.Add(CalcUsage(prev.Cores[i], next.Cores[i]));
|
||||||
|
|
||||||
|
return new CpuUsage(total, cores);
|
||||||
|
}
|
||||||
|
|
||||||
|
private decimal CalcUsage(RawCpuStats prev, RawCpuStats next)
|
||||||
|
{
|
||||||
|
decimal deltaTotal = next.Total - prev.Total;
|
||||||
|
decimal deltaIdle = next.Idle - prev.Idle;
|
||||||
|
|
||||||
|
return (1 - deltaIdle / deltaTotal) * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_prevStats = _nextStats;
|
||||||
|
_nextStats = await cpuMonitorService.ParseRawCpuStatsAsync(stoppingToken);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e.Message);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
await Task.Delay(options.Value.DelayTime, stoppingToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using MonitorAgent.Core.Abstraction;
|
||||||
|
using MonitorAgent.Core.Models;
|
||||||
|
|
||||||
|
namespace MonitorAgent.Application.Services;
|
||||||
|
|
||||||
|
public class RawCpuMonitorService : ICpuMonitorService
|
||||||
|
{
|
||||||
|
public async Task<RawCpuStatsCollection> ParseRawCpuStatsAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var raw = await File.ReadAllLinesAsync("/proc/stat", cancellationToken);
|
||||||
|
|
||||||
|
var total = RawCpuStats.Parse(raw[0]);
|
||||||
|
var cores = new List<RawCpuStats>();
|
||||||
|
for (int i = 1; i < raw.Length && raw[i].StartsWith("cpu"); i++)
|
||||||
|
cores.Add(RawCpuStats.Parse(raw[i]));
|
||||||
|
|
||||||
|
return new RawCpuStatsCollection(total, cores);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace MonitorAgent.Application.Settings;
|
||||||
|
|
||||||
|
public class CpuMonitorSettings
|
||||||
|
{
|
||||||
|
public int DelayTime { get; set; } = 1000;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using MonitorAgent.Core.Models;
|
||||||
|
|
||||||
|
namespace MonitorAgent.Core.Abstraction;
|
||||||
|
|
||||||
|
public interface ICpuMonitorService
|
||||||
|
{
|
||||||
|
public Task<RawCpuStatsCollection> ParseRawCpuStatsAsync(CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace MonitorAgent.Core.Models;
|
||||||
|
|
||||||
|
public class CpuUsage(decimal totalUsagePercent, IEnumerable<decimal> coresUsagePercent)
|
||||||
|
{
|
||||||
|
public readonly decimal TotalUsagePercent = totalUsagePercent;
|
||||||
|
public readonly ReadOnlyCollection<decimal> CoresUsagePercent = new([.. coresUsagePercent]);
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
namespace MonitorAgent.Core.Models;
|
||||||
|
|
||||||
|
public struct RawCpuStats
|
||||||
|
{
|
||||||
|
public long User { get; set; }
|
||||||
|
public long Nice { get; set; }
|
||||||
|
public long System { get; set; }
|
||||||
|
public long Idle { get; set; }
|
||||||
|
public long Iowait { get; set; }
|
||||||
|
public long Irq { get; set; }
|
||||||
|
public long Softirq { get; set; }
|
||||||
|
public long Steal { get; set; }
|
||||||
|
public long Guest { get; set; }
|
||||||
|
public long GuestNice { get; set; }
|
||||||
|
|
||||||
|
public readonly long Total => User + Nice + System + Idle + Irq + Softirq + Steal;
|
||||||
|
public readonly long TotalIdle => Idle + Iowait;
|
||||||
|
|
||||||
|
public static RawCpuStats Parse(string s)
|
||||||
|
{
|
||||||
|
var stats = s.Split();
|
||||||
|
if (!stats[0].StartsWith("cpu"))
|
||||||
|
throw new FormatException($"The input string '{s}' was not in a correct format.");
|
||||||
|
|
||||||
|
var longStats = new List<long>();
|
||||||
|
for (int i = 1; i < stats.Length; i++)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(stats[i]))
|
||||||
|
longStats.Add(long.Parse(stats[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RawCpuStats
|
||||||
|
{
|
||||||
|
User = longStats[0],
|
||||||
|
Nice = longStats[1],
|
||||||
|
System = longStats[2],
|
||||||
|
Idle = longStats[3],
|
||||||
|
Iowait = longStats[4],
|
||||||
|
Irq = longStats[5],
|
||||||
|
Softirq = longStats[6],
|
||||||
|
Steal = longStats[7],
|
||||||
|
Guest = longStats[8],
|
||||||
|
GuestNice = longStats[9]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace MonitorAgent.Core.Models;
|
||||||
|
|
||||||
|
public class RawCpuStatsCollection(RawCpuStats total, IEnumerable<RawCpuStats> cores)
|
||||||
|
{
|
||||||
|
public readonly RawCpuStats Total = total;
|
||||||
|
public readonly ReadOnlyCollection<RawCpuStats> Cores = new([.. cores]);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user