Implemented node system statistics

This commit is contained in:
2026-03-21 18:21:09 +00:00
parent ba5e364c05
commit 6d447a0ff9
28 changed files with 1402 additions and 156 deletions

View File

@@ -0,0 +1,59 @@
namespace MoonlightServers.Daemon.Helpers;
/// <summary>
/// Reads Linux system metrics directly from the <c>/proc</c> and <c>/sys</c>
/// pseudo-filesystems
/// </summary>
public static partial class SystemMetrics
{
public record SystemSnapshot(
CpuSnapshot Cpu,
MemoryInfo Memory,
IReadOnlyList<DiskInfo> Disks,
IReadOnlyList<NetworkInterfaceInfo> Network,
TimeSpan Uptime
);
/// <summary>
/// Collects a full system snapshot. The method waits <paramref name="sampleIntervalMs"/>
/// milliseconds between the two samples required to compute CPU and network rates.
/// All other reads happen in parallel during the second sampling window.
/// </summary>
/// <param name="sampleIntervalMs">
/// Interval between rate-measurement samples in milliseconds.
/// Larger values yield smoother CPU and network averages. Defaults to <c>500</c>.
/// </param>
/// <returns>A fully populated <see cref="SystemSnapshot"/>.</returns>
public static async Task<SystemSnapshot> ReadAllAsync(int sampleIntervalMs = 500)
{
// First samples — must complete before the delay.
var cpuSample1Task = ReadRawCpuStatsAsync();
var netSample1Task = ReadRawNetStatsAsync();
await Task.WhenAll(cpuSample1Task, netSample1Task);
await Task.Delay(sampleIntervalMs);
// Second samples + all independent reads run concurrently.
var cpuSample2Task = ReadRawCpuStatsAsync();
var netSample2Task = ReadRawNetStatsAsync();
var memTask = ReadMemoryAsync();
var diskTask = ReadDisksAsync();
var uptimeTask = ReadUptimeAsync();
var cpuNameTask = ReadCpuModelNameAsync();
await Task.WhenAll(cpuSample2Task, netSample2Task, memTask, diskTask, uptimeTask, cpuNameTask);
var cpu = ComputeCpuUsage(cpuNameTask.Result, cpuSample1Task.Result, cpuSample2Task.Result);
var network = ComputeNetworkRates(netSample1Task.Result, netSample2Task.Result, sampleIntervalMs / 1000.0);
return new SystemSnapshot(cpu, memTask.Result, diskTask.Result, network, uptimeTask.Result);
}
// Uptime
private static async Task<TimeSpan> ReadUptimeAsync()
{
var text = await File.ReadAllTextAsync("/proc/uptime");
var seconds = double.Parse(text.Split(' ')[0], System.Globalization.CultureInfo.InvariantCulture);
return TimeSpan.FromSeconds(seconds);
}
}