#include "fgc/HostMetrics.h" #include #include #include #include #include #include #include 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(vfs.f_frsize); const double total = static_cast(vfs.f_blocks) * frsize; const double avail = static_cast(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(n) : 0; return l; } } // namespace fgc::hostmetrics