fwt_software/src/core/HostMetrics.cpp

118 lines
3.4 KiB
C++

#include "fgc/HostMetrics.h"
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <sstream>
#include <string>
#include <sys/statvfs.h>
#include <unistd.h>
namespace fgc::hostmetrics {
namespace fs = std::filesystem;
namespace {
std::string readFile(const fs::path& p) {
std::ifstream f(p);
if (!f) return {};
std::ostringstream ss;
ss << f.rdbuf();
return ss.str();
}
} // namespace
double parseMilliCelsius(const std::string& s) {
try {
return std::stod(s) / 1000.0; // sysfs reports milli-degrees C
} catch (...) {
return 0.0;
}
}
MemInfo parseMeminfo(const std::string& text) {
MemInfo m;
std::istringstream in(text);
std::string line;
double mem_total_kb = 0, mem_avail_kb = 0, swap_total_kb = 0, swap_free_kb = 0;
bool have_total = false, have_avail = false;
while (std::getline(in, line)) {
std::istringstream ls(line);
std::string key, val, unit;
if (!(ls >> key >> val)) continue;
double kb = 0;
try { kb = std::stod(val); } catch (...) { continue; }
if (key == "MemTotal:") { mem_total_kb = kb; have_total = true; }
else if (key == "MemAvailable:") { mem_avail_kb = kb; have_avail = true; }
else if (key == "SwapTotal:") swap_total_kb = kb;
else if (key == "SwapFree:") swap_free_kb = kb;
}
m.ok = have_total && have_avail;
m.total_mb = mem_total_kb / 1024.0;
m.avail_mb = mem_avail_kb / 1024.0;
m.swap_used_mb = (swap_total_kb - swap_free_kb) / 1024.0;
return m;
}
ThermalInfo readThermal() {
ThermalInfo t;
const fs::path root = "/sys/class/thermal";
std::error_code ec;
if (!fs::exists(root, ec)) return t;
for (auto& e : fs::directory_iterator(root, ec)) {
const auto name = e.path().filename().string();
if (name.rfind("thermal_zone", 0) != 0) continue;
std::string temp_s = readFile(e.path() / "temp");
if (temp_s.empty()) continue;
double c = parseMilliCelsius(temp_s);
if (!t.ok || c > t.max_temp_c) {
t.ok = true;
t.max_temp_c = c;
std::string type = readFile(e.path() / "type");
// strip trailing newline
while (!type.empty() && (type.back() == '\n' || type.back() == '\r')) type.pop_back();
t.hottest_zone = type.empty() ? name : type;
}
}
return t;
}
DiskInfo readDisk(const std::string& path) {
DiskInfo d;
d.path = path;
struct statvfs vfs {};
if (statvfs(path.c_str(), &vfs) != 0) return d;
const double frsize = static_cast<double>(vfs.f_frsize);
const double total = static_cast<double>(vfs.f_blocks) * frsize;
const double avail = static_cast<double>(vfs.f_bavail) * frsize;
const double gb = 1024.0 * 1024.0 * 1024.0;
d.ok = true;
d.total_gb = total / gb;
d.free_gb = avail / gb;
d.used_pct = total > 0 ? 100.0 * (total - avail) / total : 0.0;
return d;
}
MemInfo readMeminfo() {
return parseMeminfo(readFile("/proc/meminfo"));
}
LoadInfo readLoad() {
LoadInfo l;
double avg[3] = {0, 0, 0};
if (getloadavg(avg, 3) == 3) {
l.ok = true;
l.load1 = avg[0];
l.load5 = avg[1];
l.load15 = avg[2];
}
long n = sysconf(_SC_NPROCESSORS_ONLN);
l.cpus = (n > 0) ? static_cast<int>(n) : 0;
return l;
}
} // namespace fgc::hostmetrics