96 lines
3.8 KiB
C++
96 lines
3.8 KiB
C++
#pragma once
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace fgc::hostmetrics {
|
|
|
|
// Host (LattePanda / Linux) health reads, for the `test host` subsystem and the
|
|
// running program's CPU watch (ThermalGuard). Pure parsers are split from the
|
|
// live readers so they unit-test without a real /sys or /proc. All readers
|
|
// degrade gracefully (ok=false) rather than throw.
|
|
//
|
|
// `root` is put in front of every /sys and /proc path ("/" = the real ones), so
|
|
// a test or a throttling simulation can hand in a fake tree:
|
|
// <root>/sys/class/thermal/thermal_zone*/{temp,type}
|
|
// <root>/sys/devices/system/cpu/cpu*/cpufreq/{scaling_cur_freq,cpuinfo_max_freq,scaling_max_freq}
|
|
// <root>/sys/devices/system/cpu/cpu*/thermal_throttle/{package,core}_throttle_count
|
|
// <root>/proc/stat (when the tree has none, the real /proc/stat)
|
|
|
|
struct ThermalInfo {
|
|
bool ok = false;
|
|
double max_temp_c = 0.0; // hottest thermal zone
|
|
std::string hottest_zone; // e.g. "x86_pkg_temp"
|
|
bool throttled = false; // best-effort (false if unknown)
|
|
// The CPU's own zone, for the CPU guard: x86_pkg_temp where there is one,
|
|
// else the hottest. Not simply the hottest: the towers also list the Wi-Fi
|
|
// card (iwlwifi_1) and the ACPI zone, and the guard watches the CPU.
|
|
double cpu_temp_c = 0.0;
|
|
std::string cpu_zone;
|
|
};
|
|
|
|
// CPU clock, from cpufreq. MHz.
|
|
struct CpuFreqInfo {
|
|
bool ok = false;
|
|
double mean_mhz = 0.0; // mean of scaling_cur_freq over the cores
|
|
double hw_max_mhz = 0.0; // cpuinfo_max_freq: what the chip can do
|
|
double cap_mhz = 0.0; // lowest scaling_max_freq: what it may do now
|
|
std::vector<double> core_mhz; // per core, cpu0 first
|
|
};
|
|
|
|
// The kernel's count of times the CPU slowed itself because it ran too hot
|
|
// (x86 thermal_throttle). It only rises; a rise between two reads is throttling.
|
|
// Slow-downs to stay inside the power limit are NOT counted here - ThrottleWatch
|
|
// (ThermalGuard.h) also watches the clock for those.
|
|
struct ThrottleCount {
|
|
bool ok = false;
|
|
long long events = 0; // package count (cpu0) + every core's count
|
|
};
|
|
|
|
// Cumulative CPU time from the first line of /proc/stat, in clock ticks. Busy %
|
|
// is the change in `busy` over the change in `total` between two reads.
|
|
struct CpuTimes {
|
|
bool ok = false;
|
|
long long busy = 0;
|
|
long long total = 0;
|
|
};
|
|
|
|
struct DiskInfo {
|
|
bool ok = false;
|
|
std::string path;
|
|
double total_gb = 0.0;
|
|
double free_gb = 0.0;
|
|
double used_pct = 0.0;
|
|
};
|
|
|
|
struct MemInfo {
|
|
bool ok = false;
|
|
double total_mb = 0.0;
|
|
double avail_mb = 0.0;
|
|
double swap_used_mb = 0.0;
|
|
};
|
|
|
|
struct LoadInfo {
|
|
bool ok = false;
|
|
double load1 = 0.0, load5 = 0.0, load15 = 0.0;
|
|
int cpus = 0;
|
|
};
|
|
|
|
// ---- live readers ----
|
|
ThermalInfo readThermal(const std::string& root = "/"); // scans sys/class/thermal
|
|
CpuFreqInfo readCpuFreq(const std::string& root = "/");
|
|
ThrottleCount readThrottleCount(const std::string& root = "/");
|
|
CpuTimes readCpuTimes(const std::string& root = "/");
|
|
DiskInfo readDisk(const std::string& path); // statvfs() on the filesystem holding `path`
|
|
MemInfo readMeminfo(); // /proc/meminfo
|
|
LoadInfo readLoad(); // getloadavg() + nproc
|
|
|
|
// ---- pure parsers (reused by the readers; exposed for tests) ----
|
|
MemInfo parseMeminfo(const std::string& proc_meminfo);
|
|
double parseMilliCelsius(const std::string& zone_temp_contents); // "52000\n" -> 52.0
|
|
CpuTimes parseProcStatCpu(const std::string& proc_stat); // its "cpu " line
|
|
// Busy percentage between two reads; -1 when either is bad or no time passed.
|
|
double busyPercent(const CpuTimes& before, const CpuTimes& after);
|
|
|
|
} // namespace fgc::hostmetrics
|