namespace MoonlightServers.Daemon.Helpers; /// /// Reads Linux system metrics directly from the /proc and /sys /// pseudo-filesystems /// public static partial class SystemMetrics { public record SystemSnapshot( CpuSnapshot Cpu, MemoryInfo Memory, IReadOnlyList Disks, IReadOnlyList Network, TimeSpan Uptime ); /// /// Collects a full system snapshot. The method waits /// milliseconds between the two samples required to compute CPU and network rates. /// All other reads happen in parallel during the second sampling window. /// /// /// Interval between rate-measurement samples in milliseconds. /// Larger values yield smoother CPU and network averages. Defaults to 500. /// /// A fully populated . public static async Task 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 ReadUptimeAsync() { var text = await File.ReadAllTextAsync("/proc/uptime"); var seconds = double.Parse(text.Split(' ')[0], System.Globalization.CultureInfo.InvariantCulture); return TimeSpan.FromSeconds(seconds); } }