59 lines
2.4 KiB
C#
59 lines
2.4 KiB
C#
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);
|
|
}
|
|
} |