From 07e42a6e3c0a1af4575990af4535367e5d7f98b2 Mon Sep 17 00:00:00 2001 From: kox13 Date: Sat, 31 Jan 2026 15:10:05 +0100 Subject: [PATCH 01/10] add utility functions --- source/agent/src/utils/utils.cc | 20 ++++++++++++++++++++ source/agent/src/utils/utils.h | 17 +++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 source/agent/src/utils/utils.cc create mode 100644 source/agent/src/utils/utils.h diff --git a/source/agent/src/utils/utils.cc b/source/agent/src/utils/utils.cc new file mode 100644 index 0000000..b70600d --- /dev/null +++ b/source/agent/src/utils/utils.cc @@ -0,0 +1,20 @@ +#include "utils.h" +#include +#include + +bool IsValidIP(const std::string &ip) { + sockaddr_in sa4{}; + sockaddr_in6 sa6{}; + + return inet_pton(AF_INET, ip.c_str(), &sa4.sin_addr) == 1 || + inet_pton(AF_INET6, ip.c_str(), &sa6.sin6_addr) == 1; +} + +bool IsResolvable(const std::string &host) { + addrinfo hints{}, *res = nullptr; + hints.ai_family = AF_UNSPEC; + + bool ok = getaddrinfo(host.c_str(), nullptr, &hints, &res) == 0; + freeaddrinfo(res); + return ok; +} diff --git a/source/agent/src/utils/utils.h b/source/agent/src/utils/utils.h new file mode 100644 index 0000000..23097a6 --- /dev/null +++ b/source/agent/src/utils/utils.h @@ -0,0 +1,17 @@ +#ifndef VOLTA_AGENT_UTILS_UTILS_H_ +#define VOLTA_AGENT_UTILS_UTILS_H_ + +#include + +namespace volta { +namespace agent { +namespace utils { + +bool IsValidIP(const std::string &ip); +bool IsResolvable(const std::string &host); + +} // namespace utils +} // namespace agent +} // namespace volta + +#endif // VOLTA_AGENT_UTILS_UTILS_H_ From 4a88dbe3a17852ebea3249e6f04d268fd5d0d205 Mon Sep 17 00:00:00 2001 From: kox13 Date: Sat, 31 Jan 2026 15:11:10 +0100 Subject: [PATCH 02/10] feat(agent): interval, server address and server port configuration in the config file --- source/agent/src/config/config_loader.cc | 279 +++++++++++++---------- source/agent/src/config/config_loader.h | 26 +-- 2 files changed, 173 insertions(+), 132 deletions(-) diff --git a/source/agent/src/config/config_loader.cc b/source/agent/src/config/config_loader.cc index d763474..767fa0a 100644 --- a/source/agent/src/config/config_loader.cc +++ b/source/agent/src/config/config_loader.cc @@ -1,14 +1,19 @@ #include "config/config_loader.h" +#include +#include #include +#include #include #include #include #include -#include #include "config/config.h" +#include "utils/utils.h" + +namespace utils = volta::agent::utils; namespace volta { namespace agent { @@ -22,150 +27,186 @@ std::filesystem::path ConfigLoader::kConfigFile = "/etc/volta/agent.conf"; std::filesystem::path ConfigLoader::kConfigFile = "agent.conf"; #endif -std::set ConfigLoader::kValidTopLevelKeys = { - "core_affinity", "core_affinity_mask", "interval", - "server_address", "server_port", "collectors"}; +std::set ConfigLoader::kValidTopLevelKeys = {"core_affinity", "core_affinity_mask", + "interval", "server_address", + "server_port", "collectors"}; -std::map> - ConfigLoader::kValidCollectorMetrics = { - {"cpu", {"proc_stat", "cpu_freq", "rapl", "zenpower", "pmu"}}, - {"gpu", {"nvml", "dcgm", "rocm", "level_zero"}}, - {"ram", {"mem_info", "vm_stat"}}, - {"io", {"disk_stats", "net_dev"}}}; +std::map> ConfigLoader::kValidCollectorMetrics = { + {"cpu", {"proc_stat", "cpu_freq", "rapl", "zenpower", "pmu"}}, + {"gpu", {"nvml", "dcgm", "rocm", "level_zero"}}, + {"ram", {"mem_info", "vm_stat"}}, + {"io", {"disk_stats", "net_dev"}}}; Config ConfigLoader::LoadConfig() { - Config config = LoadDefaultConfig(); - LoadConfigFile(config); - return config; + Config config = LoadDefaultConfig(); + LoadConfigFile(config); + return config; } Config ConfigLoader::LoadDefaultConfig() { - Config config; - - CollectorConfig nvml_collector; - nvml_collector.enabled = true; - nvml_collector.metrics = { - {"gpu_utilization", true}, - {"memory_utilization", true}, - {"temperature", true}, - }; - config.collectors[CollectorNames::kNvml] = nvml_collector; - - CollectorConfig proc_stat_config; - proc_stat_config.enabled = true; - proc_stat_config.metrics["cpu_usage_percent"] = true; - config.collectors[CollectorNames::kProcStat] = proc_stat_config; - - return config; + Config config; + + CollectorConfig nvml_collector; + nvml_collector.enabled = true; + nvml_collector.metrics = { + {"gpu_utilization", true}, + {"memory_utilization", true}, + {"temperature", true}, + }; + config.collectors[CollectorNames::kNvml] = nvml_collector; + + CollectorConfig proc_stat_config; + proc_stat_config.enabled = true; + proc_stat_config.metrics["cpu_usage_percent"] = true; + config.collectors[CollectorNames::kProcStat] = proc_stat_config; + + return config; } inline unsigned int MaxOnlineCpus() { - long n = sysconf(_SC_NPROCESSORS_ONLN); - return (n > 0) ? static_cast(n) : 0; + long n = sysconf(_SC_NPROCESSORS_ONLN); + return (n > 0) ? static_cast(n) : 0; } -bool AddCpu(cpu_set_t& set, unsigned int cpu, unsigned int max_cpu) { - if (cpu >= max_cpu) return false; - CPU_SET(cpu, &set); - return true; +bool AddCpu(cpu_set_t &set, unsigned int cpu, unsigned int max_cpu) { + if (cpu >= max_cpu) + return false; + CPU_SET(cpu, &set); + return true; } -bool AddRange(cpu_set_t& set, unsigned int from, unsigned int to, - unsigned int max_cpu) { - if (from > to || to >= max_cpu) return false; - for (unsigned int i = from; i <= to; ++i) CPU_SET(i, &set); - return true; +bool AddRange(cpu_set_t &set, unsigned int from, unsigned int to, unsigned int max_cpu) { + if (from > to || to >= max_cpu) + return false; + for (unsigned int i = from; i <= to; ++i) + CPU_SET(i, &set); + return true; } -void ConfigLoader::LoadConfigFile(Config& out_config) { - if (!std::filesystem::exists(kConfigFile)) { - std::cout << "Agent config file not found, loading default settings." - << std::endl; - return; - } - - try { - toml::table tbl = toml::parse_file(kConfigFile.string()); - - if (auto val = tbl["core_affinity"]) { - unsigned int max_cpu = MaxOnlineCpus(); - cpu_set_t mask; - CPU_ZERO(&mask); - - // core_affinity = "all" - if (auto s = val.value(); s && *s == "all") { - for (unsigned int i = 0; i < max_cpu; ++i) CPU_SET(i, &mask); - - out_config.core_affinity = mask; - } - // core_affinity = [ ... ] - else if (auto arr = val.as_array()) { - for (auto& item : *arr) { - // liczba CPU - if (auto cpu = item.value()) { - if (!AddCpu(mask, *cpu, max_cpu)) { - std::cerr << "CPU index out of range: " << *cpu << "\n"; - return; +void ConfigLoader::LoadConfigFile(Config &out_config) { + if (!std::filesystem::exists(kConfigFile)) { + std::cout << "Agent config file not found, loading default settings." << std::endl; + return; + } + + try { + toml::table tbl = toml::parse_file(kConfigFile.string()); + + if (auto val = tbl["core_affinity"]) { + // core_affinity = "all" + if (auto s = val.value(); s && *s == "all") { + out_config.core_affinity = Config::kDefaultAffinity; } - } - // zakres "X-Y" - else if (auto str = item.value()) { - unsigned int from, to; - if (sscanf(str->c_str(), "%u-%u", &from, &to) == 2) { - if (!AddRange(mask, from, to, max_cpu)) { - std::cerr << "Invalid CPU range: " << *str << "\n"; - return; - } + // core_affinity = [ ... ] + else if (auto arr = val.as_array()) { + unsigned int max_cpu = MaxOnlineCpus(); + cpu_set_t mask; + CPU_ZERO(&mask); + + for (auto &item : *arr) { + // liczba CPU + if (auto cpu = item.value()) { + if (!AddCpu(mask, *cpu, max_cpu)) { + std::cerr << "CPU index out of range: " << *cpu << "\n"; + return; + } + } + // zakres "X-Y" + else if (auto str = item.value()) { + unsigned int from, to; + if (sscanf(str->c_str(), "%u-%u", &from, &to) == 2) { + if (!AddRange(mask, from, to, max_cpu)) { + std::cerr << "Invalid CPU range: " << *str << "\n"; + return; + } + } else { + std::cerr << "Invalid core_affinity entry: " << *str << "\n"; + return; + } + } else { + std::cerr << "Invalid core_affinity element type\n"; + return; + } + } + if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { + perror("sched_setaffinity"); + } else { + std::cout << "Successfully set CPU affinity mask." << std::endl; + } + + out_config.core_affinity = mask; } else { - std::cerr << "Invalid core_affinity entry: " << *str << "\n"; - return; + std::cerr << "Invalid core_affinity value\n"; } - } else { - std::cerr << "Invalid core_affinity element type\n"; - return; - } } - if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { - perror("sched_setaffinity"); - } else { - std::cout << "Successfully set CPU affinity mask." << std::endl; + + // interval + if (auto val = tbl["interval"]) { + if (auto ms = val.value()) { + out_config.collection_interval = std::chrono::milliseconds(*ms); + std::cout << "Collection Interval set to: " << out_config.collection_interval + << std::endl; + } else { + std::cerr << "Invalid interval value type, use uint32" << std::endl; + } } - out_config.core_affinity = mask; - } else { - std::cerr << "Invalid core_affinity value\n"; - } - } - // interval - // server_address - // server_port - auto collectors_node = tbl["collectors"].as_table(); - if (!collectors_node) return; + // server_address + if (auto val = tbl["server_address"]) { + if (auto str = val.value()) { + if (utils::IsValidIP(*str) || utils::IsResolvable(*str)) { + out_config.server_address = *str; + std::cout << "Server Adress set to " << *str << std::endl; + } else { + std::cerr << "Invalid server_address format" << std::endl; + } + } else { + std::cerr << "Invalid server_address value type, use string" << std::endl; + } + } + + // server_port + if (auto val = tbl["server_port"]) { + if (auto port = val.value(); port && *port > 0) { + out_config.server_port = *port; + std::cout << "Server port set to " << *port << std::endl; + } else { + std::cerr << "server_port has an incorrect type or value, use number from range " + "[1, 65535]" + << std::endl; + } + } - for (auto& [collector_name, collector_node] : *collectors_node) { - auto collector_table = collector_node.as_table(); - if (!collector_table) continue; + // collectors + auto collectors_node = tbl["collectors"].as_table(); + if (!collectors_node) + return; - CollectorConfig collector; + for (auto &[collector_name, collector_node] : *collectors_node) { + auto collector_table = collector_node.as_table(); + if (!collector_table) + continue; - if (auto enabled_array = (*collector_table)["enabled"].as_array()) { - for (auto& item : *enabled_array) { - if (auto str = item.value()) { - collector.metrics[*str] = true; - } - } + CollectorConfig collector; - collector.enabled = !collector.metrics.empty(); - } + if (auto enabled_array = (*collector_table)["enabled"].as_array()) { + for (auto &item : *enabled_array) { + if (auto str = item.value()) { + collector.metrics[*str] = true; + } + } - out_config.collectors[std::string{collector_name.str()}] = collector; + collector.enabled = !collector.metrics.empty(); + } + + out_config.collectors[std::string{collector_name.str()}] = collector; + } + } catch (const toml::parse_error &err) { + std::cerr << "Parsing Agent config failed: " << err.description() << " at " + << err.source().begin << std::endl; } - } catch (const toml::parse_error& err) { - std::cerr << "Parsing Agent config failed: " << err.description() << " at " - << err.source().begin << std::endl; - } } -} // namespace config -} // namespace agent -} // namespace volta +} // namespace config +} // namespace agent +} // namespace volta diff --git a/source/agent/src/config/config_loader.h b/source/agent/src/config/config_loader.h index 4e70ca5..f26b190 100644 --- a/source/agent/src/config/config_loader.h +++ b/source/agent/src/config/config_loader.h @@ -12,22 +12,22 @@ namespace agent { namespace config { class ConfigLoader { - public: - static Config LoadConfig(); + public: + static Config LoadConfig(); + static Config LoadDefaultConfig(); - private: - ConfigLoader() = delete; + private: + ConfigLoader() = delete; - static Config LoadDefaultConfig(); - static void LoadConfigFile(Config& out_config); + static void LoadConfigFile(Config &out_config); - static std::filesystem::path kConfigFile; - static std::set kValidTopLevelKeys; - static std::map> kValidCollectorMetrics; + static std::filesystem::path kConfigFile; + static std::set kValidTopLevelKeys; + static std::map> kValidCollectorMetrics; }; -} // namespace config -} // namespace agent -} // namespace volta +} // namespace config +} // namespace agent +} // namespace volta -#endif // VOLTA_AGENT_CONFIG_CONFIG_LOADER_H_ +#endif // VOLTA_AGENT_CONFIG_CONFIG_LOADER_H_ From 58110cf474b4d7f6822a8cdb0c401dfa224aac65 Mon Sep 17 00:00:00 2001 From: kox13 Date: Sat, 31 Jan 2026 15:26:00 +0100 Subject: [PATCH 03/10] add namespace --- source/agent/src/utils/utils.cc | 9 +++++++++ source/agent/src/utils/utils.h | 12 ++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/source/agent/src/utils/utils.cc b/source/agent/src/utils/utils.cc index b70600d..e2a6888 100644 --- a/source/agent/src/utils/utils.cc +++ b/source/agent/src/utils/utils.cc @@ -1,7 +1,12 @@ #include "utils.h" + #include #include +namespace volta { +namespace agent { +namespace utils { + bool IsValidIP(const std::string &ip) { sockaddr_in sa4{}; sockaddr_in6 sa6{}; @@ -18,3 +23,7 @@ bool IsResolvable(const std::string &host) { freeaddrinfo(res); return ok; } + +} // namespace utils +} // namespace agent +} // namespace volta diff --git a/source/agent/src/utils/utils.h b/source/agent/src/utils/utils.h index 23097a6..133977d 100644 --- a/source/agent/src/utils/utils.h +++ b/source/agent/src/utils/utils.h @@ -7,11 +7,11 @@ namespace volta { namespace agent { namespace utils { -bool IsValidIP(const std::string &ip); -bool IsResolvable(const std::string &host); +bool IsValidIP(const std::string& ip); +bool IsResolvable(const std::string& host); -} // namespace utils -} // namespace agent -} // namespace volta +} // namespace utils +} // namespace agent +} // namespace volta -#endif // VOLTA_AGENT_UTILS_UTILS_H_ +#endif // VOLTA_AGENT_UTILS_UTILS_H_ From 40b047d20d3f8472040a0dbb04e017943ef1c149 Mon Sep 17 00:00:00 2001 From: kox13 Date: Sat, 31 Jan 2026 19:51:43 +0100 Subject: [PATCH 04/10] feat(agent): reading hardware and collectors --- source/agent/src/config/config.h | 119 ++++++++++++----------- source/agent/src/config/config_loader.cc | 64 +++++++----- source/agent/src/config/config_loader.h | 5 +- 3 files changed, 104 insertions(+), 84 deletions(-) diff --git a/source/agent/src/config/config.h b/source/agent/src/config/config.h index 7af79da..7aba75b 100644 --- a/source/agent/src/config/config.h +++ b/source/agent/src/config/config.h @@ -13,79 +13,82 @@ namespace volta { namespace agent { namespace config { - +// TODO: Metrics and Collector names into something that can be read with a string namespace CollectorNames { // CPU -static constexpr char const* kProcStat = "proc_stat"; -static constexpr char const* kCpuFreq = "cpu_freq"; -static constexpr char const* kRapl = "rapl"; -static constexpr char const* kZenPower = "zenpower"; -static constexpr char const* kPmu = "pmu"; +static constexpr char const *kProcStat = "proc_stat"; +static constexpr char const *kCpuFreq = "cpu_freq"; +static constexpr char const *kRapl = "rapl"; +static constexpr char const *kZenPower = "zenpower"; +static constexpr char const *kPmu = "pmu"; // GPU -static constexpr char const* kNvml = "nvml"; -static constexpr char const* kDcgm = "dcgm"; -static constexpr char const* kRocm = "rocm"; -static constexpr char const* kLevelZero = "level_zero"; +static constexpr char const *kNvml = "nvml"; +static constexpr char const *kDcgm = "dcgm"; +static constexpr char const *kRocm = "rocm"; +static constexpr char const *kLevelZero = "level_zero"; // RAM -static constexpr char const* kMemInfo = "mem_info"; -static constexpr char const* kVmStat = "vm_stat"; +static constexpr char const *kMemInfo = "mem_info"; +static constexpr char const *kVmStat = "vm_stat"; // Disc and Network (I/O) -static constexpr char const* kDiskStats = "disk_stats"; -static constexpr char const* kNetDev = "net_dev"; -} // namespace CollectorNames +static constexpr char const *kDiskStats = "disk_stats"; +static constexpr char const *kNetDev = "net_dev"; +} // namespace CollectorNames struct CollectorConfig { - bool enabled = false; - std::map metrics; + bool enabled = false; + std::map metrics; }; struct Config { - void PrintCurrentAffinity() { - cpu_set_t set; - CPU_ZERO(&set); - - if (sched_getaffinity(0, sizeof(set), &set) != 0) { - perror("sched_getaffinity"); - return; - } - - long max_cpus = sysconf(_SC_NPROCESSORS_CONF); - std::cout << "Current CPU affinity: "; - - for (int i = 0; i < max_cpus; ++i) { - if (CPU_ISSET(i, &set)) std::cout << i << " "; - } - std::cout << "\n"; - } - - static constexpr int32_t kDefaultIntervalMs = 500; - static constexpr char const* kDefaultServerAddress = "localhost"; - static constexpr uint16_t kDefaultServerPort = 50051; - static inline cpu_set_t kDefaultAffinity = [] { - cpu_set_t mask; - CPU_ZERO(&mask); - unsigned int n_cpus = std::thread::hardware_concurrency(); - for (unsigned int i = 0; i < n_cpus; ++i) { - CPU_SET(i, &mask); + void PrintCurrentAffinity() { + cpu_set_t set; + CPU_ZERO(&set); + + if (sched_getaffinity(0, sizeof(set), &set) != 0) { + // TODO: Log + perror("sched_getaffinity"); + return; + } + + long max_cpus = sysconf(_SC_NPROCESSORS_CONF); + std::cout << "Current CPU affinity: "; + + for (int i = 0; i < max_cpus; ++i) { + if (CPU_ISSET(i, &set)) + std::cout << i << " "; + } + std::cout << "\n"; } - return mask; - }(); - - std::chrono::milliseconds collection_interval = - std::chrono::milliseconds(kDefaultIntervalMs); - cpu_set_t core_affinity = kDefaultAffinity; - - std::string server_address = kDefaultServerAddress; - uint16_t server_port = kDefaultServerPort; - std::map collectors; + static constexpr int32_t kDefaultIntervalMs = 500; + static constexpr char const *kDefaultServerAddress = "localhost"; + static constexpr uint16_t kDefaultServerPort = 50051; + static inline cpu_set_t kDefaultAffinity = [] { + cpu_set_t mask; + CPU_ZERO(&mask); + long n_cpus = sysconf(_SC_NPROCESSORS_ONLN); + n_cpus = std::min(n_cpus, static_cast(CPU_SETSIZE)); + // TODO: Handle sysconf error + for (long i = 0; i < n_cpus; ++i) { + CPU_SET(i, &mask); + } + return mask; + }(); + + std::chrono::milliseconds collection_interval = std::chrono::milliseconds(kDefaultIntervalMs); + cpu_set_t core_affinity = kDefaultAffinity; + + std::string server_address = kDefaultServerAddress; + uint16_t server_port = kDefaultServerPort; + + std::map collectors; }; -} // namespace config -} // namespace agent -} // namespace volta +} // namespace config +} // namespace agent +} // namespace volta -#endif // VOLTA_AGENT_CONFIG_CONFIG_H_ +#endif // VOLTA_AGENT_CONFIG_CONFIG_H_ diff --git a/source/agent/src/config/config_loader.cc b/source/agent/src/config/config_loader.cc index 767fa0a..014b60d 100644 --- a/source/agent/src/config/config_loader.cc +++ b/source/agent/src/config/config_loader.cc @@ -13,8 +13,6 @@ #include "config/config.h" #include "utils/utils.h" -namespace utils = volta::agent::utils; - namespace volta { namespace agent { namespace config { @@ -27,15 +25,14 @@ std::filesystem::path ConfigLoader::kConfigFile = "/etc/volta/agent.conf"; std::filesystem::path ConfigLoader::kConfigFile = "agent.conf"; #endif -std::set ConfigLoader::kValidTopLevelKeys = {"core_affinity", "core_affinity_mask", - "interval", "server_address", - "server_port", "collectors"}; +std::set> ConfigLoader::kValidTopLevelKeys = { + "core_affinity", "interval", "server_address", "server_port", "collectors"}; -std::map> ConfigLoader::kValidCollectorMetrics = { - {"cpu", {"proc_stat", "cpu_freq", "rapl", "zenpower", "pmu"}}, - {"gpu", {"nvml", "dcgm", "rocm", "level_zero"}}, - {"ram", {"mem_info", "vm_stat"}}, - {"io", {"disk_stats", "net_dev"}}}; +std::map>, std::less<>> + ConfigLoader::kValidCollectors = {{"cpu", {"proc_stat", "cpu_freq", "rapl", "zenpower", "pmu"}}, + {"gpu", {"nvml", "dcgm", "rocm", "level_zero"}}, + {"ram", {"mem_info", "vm_stat"}}, + {"io", {"disk_stats", "net_dev"}}}; Config ConfigLoader::LoadConfig() { Config config = LoadDefaultConfig(); @@ -84,6 +81,8 @@ bool AddRange(cpu_set_t &set, unsigned int from, unsigned int to, unsigned int m } void ConfigLoader::LoadConfigFile(Config &out_config) { + // TODO: Proper logging + // TODO: Move some code to separate functions if (!std::filesystem::exists(kConfigFile)) { std::cout << "Agent config file not found, loading default settings." << std::endl; return; @@ -154,6 +153,7 @@ void ConfigLoader::LoadConfigFile(Config &out_config) { // server_address if (auto val = tbl["server_address"]) { if (auto str = val.value()) { + namespace utils = volta::agent::utils; if (utils::IsValidIP(*str) || utils::IsResolvable(*str)) { out_config.server_address = *str; std::cout << "Server Adress set to " << *str << std::endl; @@ -171,7 +171,8 @@ void ConfigLoader::LoadConfigFile(Config &out_config) { out_config.server_port = *port; std::cout << "Server port set to " << *port << std::endl; } else { - std::cerr << "server_port has an incorrect type or value, use number from range " + std::cerr << "server_port has an incorrect type or value, use number " + "from range " "[1, 65535]" << std::endl; } @@ -179,27 +180,42 @@ void ConfigLoader::LoadConfigFile(Config &out_config) { // collectors auto collectors_node = tbl["collectors"].as_table(); - if (!collectors_node) + if (!collectors_node) { return; + } + + for (auto &&[hardware_type, hardware_node] : *collectors_node) { + if (!kValidCollectors.contains(hardware_type.str())) { + std::cerr << "Invalid hardware type: " << hardware_type << std::endl; + continue; + } - for (auto &[collector_name, collector_node] : *collectors_node) { - auto collector_table = collector_node.as_table(); - if (!collector_table) + auto collectors = hardware_node.as_array(); + if (!collectors) { + std::cout << "Element " << hardware_type << " is not an array\n"; continue; + } - CollectorConfig collector; + CollectorConfig collector_config; - if (auto enabled_array = (*collector_table)["enabled"].as_array()) { - for (auto &item : *enabled_array) { - if (auto str = item.value()) { - collector.metrics[*str] = true; + std::cout << hardware_type << std::endl; + for (auto &&collector : *collectors) { + if (auto str = collector.value()) { + const auto &collector_set = kValidCollectors[hardware_type.str()]; + if (!collector_set.contains(*str)) { + std::cout << "Invalid collector: " << *str + << ", for hardware: " << hardware_type << std::endl; + continue; } - } - collector.enabled = !collector.metrics.empty(); - } + std::cout << *str << std::endl; + // TODO: Add metrics - out_config.collectors[std::string{collector_name.str()}] = collector; + collector_config.enabled = !collector_config.metrics.empty(); + } else { + std::cerr << "Invalid type in " << hardware_type << " array\n"; + } + } } } catch (const toml::parse_error &err) { std::cerr << "Parsing Agent config failed: " << err.description() << " at " diff --git a/source/agent/src/config/config_loader.h b/source/agent/src/config/config_loader.h index f26b190..f855241 100644 --- a/source/agent/src/config/config_loader.h +++ b/source/agent/src/config/config_loader.h @@ -22,8 +22,9 @@ class ConfigLoader { static void LoadConfigFile(Config &out_config); static std::filesystem::path kConfigFile; - static std::set kValidTopLevelKeys; - static std::map> kValidCollectorMetrics; + static std::set> kValidTopLevelKeys; + static std::map>, std::less<>> + kValidCollectors; }; } // namespace config From fe4cf6475b2a74cd2d59f308b8190c36f36f2e3f Mon Sep 17 00:00:00 2001 From: kox13 Date: Mon, 2 Feb 2026 15:15:32 +0100 Subject: [PATCH 05/10] feat(agent): checking and logging any incorrect keys in the config file, move config loading functionality into separate functions --- source/agent/src/config/config_loader.cc | 248 +++++++++++++---------- source/agent/src/config/config_loader.h | 7 + 2 files changed, 146 insertions(+), 109 deletions(-) diff --git a/source/agent/src/config/config_loader.cc b/source/agent/src/config/config_loader.cc index 014b60d..baedeb5 100644 --- a/source/agent/src/config/config_loader.cc +++ b/source/agent/src/config/config_loader.cc @@ -8,7 +8,6 @@ #include #include #include -#include #include "config/config.h" #include "utils/utils.h" @@ -82,7 +81,6 @@ bool AddRange(cpu_set_t &set, unsigned int from, unsigned int to, unsigned int m void ConfigLoader::LoadConfigFile(Config &out_config) { // TODO: Proper logging - // TODO: Move some code to separate functions if (!std::filesystem::exists(kConfigFile)) { std::cout << "Agent config file not found, loading default settings." << std::endl; return; @@ -91,135 +89,167 @@ void ConfigLoader::LoadConfigFile(Config &out_config) { try { toml::table tbl = toml::parse_file(kConfigFile.string()); - if (auto val = tbl["core_affinity"]) { - // core_affinity = "all" - if (auto s = val.value(); s && *s == "all") { - out_config.core_affinity = Config::kDefaultAffinity; + LoadCoreAffinity(tbl, out_config); + LoadInterval(tbl, out_config); + LoadServerAddress(tbl, out_config); + LoadServerPort(tbl, out_config); + LoadCollectors(tbl, out_config); + CheckKeys(tbl); + } catch (const toml::parse_error &err) { + std::cerr << "Parsing Agent config failed: " << err.description() << " at " + << err.source().begin << std::endl; + } +} + +void ConfigLoader::LoadCoreAffinity(toml::table &tbl, Config &out_config) { + if (!tbl.contains("core_affinity")) + return; + + auto val = tbl["core_affinity"]; + + // core_affinity = "all" + if (auto s = val.value(); s && *s == "all") { + out_config.core_affinity = Config::kDefaultAffinity; + } + // core_affinity = [ ... ] + else if (auto arr = val.as_array()) { + unsigned int max_cpu = MaxOnlineCpus(); + cpu_set_t mask; + CPU_ZERO(&mask); + // NOTE: Should setting the affinity in here? + for (auto &item : *arr) { + // liczba CPU + if (auto cpu = item.value()) { + if (!AddCpu(mask, *cpu, max_cpu)) { + std::cerr << "CPU index out of range: " << *cpu << "\n"; + return; + } } - // core_affinity = [ ... ] - else if (auto arr = val.as_array()) { - unsigned int max_cpu = MaxOnlineCpus(); - cpu_set_t mask; - CPU_ZERO(&mask); - - for (auto &item : *arr) { - // liczba CPU - if (auto cpu = item.value()) { - if (!AddCpu(mask, *cpu, max_cpu)) { - std::cerr << "CPU index out of range: " << *cpu << "\n"; - return; - } - } - // zakres "X-Y" - else if (auto str = item.value()) { - unsigned int from, to; - if (sscanf(str->c_str(), "%u-%u", &from, &to) == 2) { - if (!AddRange(mask, from, to, max_cpu)) { - std::cerr << "Invalid CPU range: " << *str << "\n"; - return; - } - } else { - std::cerr << "Invalid core_affinity entry: " << *str << "\n"; - return; - } - } else { - std::cerr << "Invalid core_affinity element type\n"; + // zakres "X-Y" + else if (auto str = item.value()) { + unsigned int from, to; + if (sscanf(str->c_str(), "%u-%u", &from, &to) == 2) { + if (!AddRange(mask, from, to, max_cpu)) { + std::cerr << "Invalid CPU range: " << *str << "\n"; return; } - } - if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { - perror("sched_setaffinity"); } else { - std::cout << "Successfully set CPU affinity mask." << std::endl; + std::cerr << "Invalid core_affinity entry: " << *str << "\n"; + return; } - - out_config.core_affinity = mask; } else { - std::cerr << "Invalid core_affinity value\n"; + std::cerr << "Invalid core_affinity element type\n"; + return; } } - - // interval - if (auto val = tbl["interval"]) { - if (auto ms = val.value()) { - out_config.collection_interval = std::chrono::milliseconds(*ms); - std::cout << "Collection Interval set to: " << out_config.collection_interval - << std::endl; - } else { - std::cerr << "Invalid interval value type, use uint32" << std::endl; - } + if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { + perror("sched_setaffinity"); + } else { + std::cout << "Successfully set CPU affinity mask." << std::endl; } - // server_address - if (auto val = tbl["server_address"]) { - if (auto str = val.value()) { - namespace utils = volta::agent::utils; - if (utils::IsValidIP(*str) || utils::IsResolvable(*str)) { - out_config.server_address = *str; - std::cout << "Server Adress set to " << *str << std::endl; - } else { - std::cerr << "Invalid server_address format" << std::endl; - } - } else { - std::cerr << "Invalid server_address value type, use string" << std::endl; - } - } + out_config.core_affinity = mask; + } else { + std::cerr << "Invalid core_affinity value\n"; + } +} - // server_port - if (auto val = tbl["server_port"]) { - if (auto port = val.value(); port && *port > 0) { - out_config.server_port = *port; - std::cout << "Server port set to " << *port << std::endl; - } else { - std::cerr << "server_port has an incorrect type or value, use number " - "from range " - "[1, 65535]" - << std::endl; - } - } +void ConfigLoader::LoadInterval(toml::table &tbl, Config &out_config) { + if (!tbl.contains("interval")) + return; + + auto val = tbl["interval"]; + + if (auto ms = val.value()) { + out_config.collection_interval = std::chrono::milliseconds(*ms); + std::cout << "Collection Interval set to: " << out_config.collection_interval << std::endl; + } else { + std::cerr << "Invalid interval value type, use uint32" << std::endl; + } +} + +void ConfigLoader::LoadServerAddress(toml::table &tbl, Config &out_config) { + if (!tbl.contains("server_address")) + return; - // collectors - auto collectors_node = tbl["collectors"].as_table(); - if (!collectors_node) { - return; + auto val = tbl["server_address"]; + + if (auto str = val.value()) { + namespace utils = volta::agent::utils; + if (utils::IsValidIP(*str) || utils::IsResolvable(*str)) { + out_config.server_address = *str; + std::cout << "Server Address set to " << *str << std::endl; + } else { + std::cerr << "Invalid server_address format" << std::endl; } + } else { + std::cerr << "Invalid server_address value type, use string" << std::endl; + } +} - for (auto &&[hardware_type, hardware_node] : *collectors_node) { - if (!kValidCollectors.contains(hardware_type.str())) { - std::cerr << "Invalid hardware type: " << hardware_type << std::endl; - continue; - } +void ConfigLoader::LoadServerPort(toml::table &tbl, Config &out_config) { + if (!tbl.contains("server_port")) + return; - auto collectors = hardware_node.as_array(); - if (!collectors) { - std::cout << "Element " << hardware_type << " is not an array\n"; - continue; - } + auto val = tbl["server_port"]; - CollectorConfig collector_config; + if (auto port = val.value(); port && *port > 0) { + out_config.server_port = *port; + std::cout << "Server port set to " << *port << std::endl; + } else { + std::cerr << "server_port has an incorrect type or value, use number " + "from range " + "[1, 65535]" + << std::endl; + } +} - std::cout << hardware_type << std::endl; - for (auto &&collector : *collectors) { - if (auto str = collector.value()) { - const auto &collector_set = kValidCollectors[hardware_type.str()]; - if (!collector_set.contains(*str)) { - std::cout << "Invalid collector: " << *str - << ", for hardware: " << hardware_type << std::endl; - continue; - } +void ConfigLoader::LoadCollectors(toml::table &tbl, Config &out_config) { + if (!tbl.contains("collectors")) + return; - std::cout << *str << std::endl; - // TODO: Add metrics + auto collectors_node = tbl["collectors"].as_table(); - collector_config.enabled = !collector_config.metrics.empty(); - } else { - std::cerr << "Invalid type in " << hardware_type << " array\n"; + for (auto &&[hardware_type, hardware_node] : *collectors_node) { + if (!kValidCollectors.contains(hardware_type.str())) { + std::cerr << "Invalid hardware type: " << hardware_type << std::endl; + continue; + } + + auto collectors = hardware_node.as_array(); + if (!collectors) { + std::cout << "Element " << hardware_type << " is not an array\n"; + continue; + } + + CollectorConfig collector_config; + + std::cout << hardware_type << std::endl; + for (auto &&collector : *collectors) { + if (auto str = collector.value()) { + const auto &collector_set = kValidCollectors[hardware_type.str()]; + if (!collector_set.contains(*str)) { + std::cout << "Invalid collector: " << *str + << ", for hardware: " << hardware_type << std::endl; + continue; } + + std::cout << *str << std::endl; + // TODO: Add metrics + + collector_config.enabled = !collector_config.metrics.empty(); + } else { + std::cerr << "Invalid type in " << hardware_type << " array\n"; } } - } catch (const toml::parse_error &err) { - std::cerr << "Parsing Agent config failed: " << err.description() << " at " - << err.source().begin << std::endl; + } +} + +void ConfigLoader::CheckKeys(toml::table &tbl) { + for (auto &&[key, value] : tbl) { + if (!kValidTopLevelKeys.contains(key.str())) { + std::cout << "Key '" << key << "' is not a valid key\n"; + } } } diff --git a/source/agent/src/config/config_loader.h b/source/agent/src/config/config_loader.h index f855241..9d329bf 100644 --- a/source/agent/src/config/config_loader.h +++ b/source/agent/src/config/config_loader.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "config/config.h" @@ -20,6 +21,12 @@ class ConfigLoader { ConfigLoader() = delete; static void LoadConfigFile(Config &out_config); + static void LoadCoreAffinity(toml::table &tbl, Config &out_config); + static void LoadInterval(toml::table &tbl, Config &out_config); + static void LoadServerAddress(toml::table &tbl, Config &out_config); + static void LoadServerPort(toml::table &tbl, Config &out_config); + static void LoadCollectors(toml::table &tbl, Config &out_config); + static void CheckKeys(toml::table &tbl); static std::filesystem::path kConfigFile; static std::set> kValidTopLevelKeys; From 9ec9111ef433094bb09ae69b6bb20174a4a6618c Mon Sep 17 00:00:00 2001 From: kox13 Date: Mon, 2 Feb 2026 15:46:55 +0100 Subject: [PATCH 06/10] chore: correct format --- source/agent/src/config/config.h | 125 ++++---- source/agent/src/config/config_loader.cc | 362 ++++++++++++----------- source/agent/src/config/config_loader.h | 48 +-- source/agent/src/utils/utils.cc | 53 +++- source/agent/src/utils/utils.h | 1 + 5 files changed, 311 insertions(+), 278 deletions(-) diff --git a/source/agent/src/config/config.h b/source/agent/src/config/config.h index 7aba75b..06421b8 100644 --- a/source/agent/src/config/config.h +++ b/source/agent/src/config/config.h @@ -13,82 +13,85 @@ namespace volta { namespace agent { namespace config { -// TODO: Metrics and Collector names into something that can be read with a string +// TODO: Metrics and Collector names into something that can be read with a +// string namespace CollectorNames { // CPU -static constexpr char const *kProcStat = "proc_stat"; -static constexpr char const *kCpuFreq = "cpu_freq"; -static constexpr char const *kRapl = "rapl"; -static constexpr char const *kZenPower = "zenpower"; -static constexpr char const *kPmu = "pmu"; +static constexpr char const* kProcStat = "proc_stat"; +static constexpr char const* kCpuFreq = "cpu_freq"; +static constexpr char const* kRapl = "rapl"; +static constexpr char const* kZenPower = "zenpower"; +static constexpr char const* kPmu = "pmu"; // GPU -static constexpr char const *kNvml = "nvml"; -static constexpr char const *kDcgm = "dcgm"; -static constexpr char const *kRocm = "rocm"; -static constexpr char const *kLevelZero = "level_zero"; +static constexpr char const* kNvml = "nvml"; +static constexpr char const* kDcgm = "dcgm"; +static constexpr char const* kRocm = "rocm"; +static constexpr char const* kLevelZero = "level_zero"; // RAM -static constexpr char const *kMemInfo = "mem_info"; -static constexpr char const *kVmStat = "vm_stat"; +static constexpr char const* kMemInfo = "mem_info"; +static constexpr char const* kVmStat = "vm_stat"; // Disc and Network (I/O) -static constexpr char const *kDiskStats = "disk_stats"; -static constexpr char const *kNetDev = "net_dev"; -} // namespace CollectorNames +static constexpr char const* kDiskStats = "disk_stats"; +static constexpr char const* kNetDev = "net_dev"; +} // namespace CollectorNames struct CollectorConfig { - bool enabled = false; - std::map metrics; + bool enabled = false; + std::map metrics; }; struct Config { - void PrintCurrentAffinity() { - cpu_set_t set; - CPU_ZERO(&set); - - if (sched_getaffinity(0, sizeof(set), &set) != 0) { - // TODO: Log - perror("sched_getaffinity"); - return; - } - - long max_cpus = sysconf(_SC_NPROCESSORS_CONF); - std::cout << "Current CPU affinity: "; - - for (int i = 0; i < max_cpus; ++i) { - if (CPU_ISSET(i, &set)) - std::cout << i << " "; - } - std::cout << "\n"; + void PrintCurrentAffinity() { + cpu_set_t set; + CPU_ZERO(&set); + + if (sched_getaffinity(0, sizeof(set), &set) != 0) { + // TODO: Log + perror("sched_getaffinity"); + return; } - static constexpr int32_t kDefaultIntervalMs = 500; - static constexpr char const *kDefaultServerAddress = "localhost"; - static constexpr uint16_t kDefaultServerPort = 50051; - static inline cpu_set_t kDefaultAffinity = [] { - cpu_set_t mask; - CPU_ZERO(&mask); - long n_cpus = sysconf(_SC_NPROCESSORS_ONLN); - n_cpus = std::min(n_cpus, static_cast(CPU_SETSIZE)); - // TODO: Handle sysconf error - for (long i = 0; i < n_cpus; ++i) { - CPU_SET(i, &mask); - } - return mask; - }(); - - std::chrono::milliseconds collection_interval = std::chrono::milliseconds(kDefaultIntervalMs); - cpu_set_t core_affinity = kDefaultAffinity; - - std::string server_address = kDefaultServerAddress; - uint16_t server_port = kDefaultServerPort; - - std::map collectors; + long max_cpus = sysconf(_SC_NPROCESSORS_CONF); + std::cout << "Current CPU affinity: "; + + for (int i = 0; i < max_cpus; ++i) { + if (CPU_ISSET(i, &set)) std::cout << i << " "; + } + std::cout << "\n"; + } + + static constexpr int32_t kDefaultIntervalMs = 500; + static constexpr char const* kDefaultServerAddress = "localhost"; + static constexpr uint16_t kDefaultServerPort = 50051; + static inline cpu_set_t kDefaultAffinity = [] { + cpu_set_t mask; + CPU_ZERO(&mask); + long n_cpus = sysconf(_SC_NPROCESSORS_ONLN); + n_cpus = std::min(n_cpus, static_cast(CPU_SETSIZE)); + // TODO: Handle sysconf error + for (long i = 0; i < n_cpus; ++i) { + CPU_SET(i, &mask); + } + return mask; + }(); + + std::string uuid = ""; + + std::chrono::milliseconds collection_interval = + std::chrono::milliseconds(kDefaultIntervalMs); + cpu_set_t core_affinity = kDefaultAffinity; + + std::string server_address = kDefaultServerAddress; + uint16_t server_port = kDefaultServerPort; + + std::map collectors; }; -} // namespace config -} // namespace agent -} // namespace volta +} // namespace config +} // namespace agent +} // namespace volta -#endif // VOLTA_AGENT_CONFIG_CONFIG_H_ +#endif // VOLTA_AGENT_CONFIG_CONFIG_H_ diff --git a/source/agent/src/config/config_loader.cc b/source/agent/src/config/config_loader.cc index baedeb5..0f43ea7 100644 --- a/source/agent/src/config/config_loader.cc +++ b/source/agent/src/config/config_loader.cc @@ -28,231 +28,233 @@ std::set> ConfigLoader::kValidTopLevelKeys = { "core_affinity", "interval", "server_address", "server_port", "collectors"}; std::map>, std::less<>> - ConfigLoader::kValidCollectors = {{"cpu", {"proc_stat", "cpu_freq", "rapl", "zenpower", "pmu"}}, - {"gpu", {"nvml", "dcgm", "rocm", "level_zero"}}, - {"ram", {"mem_info", "vm_stat"}}, - {"io", {"disk_stats", "net_dev"}}}; + ConfigLoader::kValidCollectors = { + {"cpu", {"proc_stat", "cpu_freq", "rapl", "zenpower", "pmu"}}, + {"gpu", {"nvml", "dcgm", "rocm", "level_zero"}}, + {"ram", {"mem_info", "vm_stat"}}, + {"io", {"disk_stats", "net_dev"}}}; Config ConfigLoader::LoadConfig() { - Config config = LoadDefaultConfig(); - LoadConfigFile(config); - return config; + Config config = LoadDefaultConfig(); + LoadConfigFile(config); + return config; } Config ConfigLoader::LoadDefaultConfig() { - Config config; - - CollectorConfig nvml_collector; - nvml_collector.enabled = true; - nvml_collector.metrics = { - {"gpu_utilization", true}, - {"memory_utilization", true}, - {"temperature", true}, - }; - config.collectors[CollectorNames::kNvml] = nvml_collector; - - CollectorConfig proc_stat_config; - proc_stat_config.enabled = true; - proc_stat_config.metrics["cpu_usage_percent"] = true; - config.collectors[CollectorNames::kProcStat] = proc_stat_config; - - return config; + Config config; + + // load config + // if id file exitsts load else genereate uuid and save to file + LoadUUID(config); + + CollectorConfig nvml_collector; + nvml_collector.enabled = true; + nvml_collector.metrics = { + {"gpu_utilization", true}, + {"memory_utilization", true}, + {"temperature", true}, + }; + config.collectors[CollectorNames::kNvml] = nvml_collector; + + CollectorConfig proc_stat_config; + proc_stat_config.enabled = true; + proc_stat_config.metrics["cpu_usage_percent"] = true; + config.collectors[CollectorNames::kProcStat] = proc_stat_config; + + return config; } inline unsigned int MaxOnlineCpus() { - long n = sysconf(_SC_NPROCESSORS_ONLN); - return (n > 0) ? static_cast(n) : 0; + long n = sysconf(_SC_NPROCESSORS_ONLN); + return (n > 0) ? static_cast(n) : 0; } -bool AddCpu(cpu_set_t &set, unsigned int cpu, unsigned int max_cpu) { - if (cpu >= max_cpu) - return false; - CPU_SET(cpu, &set); - return true; +bool AddCpu(cpu_set_t& set, unsigned int cpu, unsigned int max_cpu) { + if (cpu >= max_cpu) return false; + CPU_SET(cpu, &set); + return true; } -bool AddRange(cpu_set_t &set, unsigned int from, unsigned int to, unsigned int max_cpu) { - if (from > to || to >= max_cpu) - return false; - for (unsigned int i = from; i <= to; ++i) - CPU_SET(i, &set); - return true; +bool AddRange(cpu_set_t& set, unsigned int from, unsigned int to, + unsigned int max_cpu) { + if (from > to || to >= max_cpu) return false; + for (unsigned int i = from; i <= to; ++i) CPU_SET(i, &set); + return true; } -void ConfigLoader::LoadConfigFile(Config &out_config) { - // TODO: Proper logging - if (!std::filesystem::exists(kConfigFile)) { - std::cout << "Agent config file not found, loading default settings." << std::endl; - return; - } - - try { - toml::table tbl = toml::parse_file(kConfigFile.string()); - - LoadCoreAffinity(tbl, out_config); - LoadInterval(tbl, out_config); - LoadServerAddress(tbl, out_config); - LoadServerPort(tbl, out_config); - LoadCollectors(tbl, out_config); - CheckKeys(tbl); - } catch (const toml::parse_error &err) { - std::cerr << "Parsing Agent config failed: " << err.description() << " at " - << err.source().begin << std::endl; - } +void ConfigLoader::LoadConfigFile(Config& out_config) { + // TODO: Proper logging + if (!std::filesystem::exists(kConfigFile)) { + std::cout << "Agent config file not found, loading default settings." + << std::endl; + return; + } + + try { + toml::table tbl = toml::parse_file(kConfigFile.string()); + + LoadCoreAffinity(tbl, out_config); + LoadInterval(tbl, out_config); + LoadServerAddress(tbl, out_config); + LoadServerPort(tbl, out_config); + LoadCollectors(tbl, out_config); + CheckKeys(tbl); + } catch (const toml::parse_error& err) { + std::cerr << "Parsing Agent config failed: " << err.description() << " at " + << err.source().begin << std::endl; + } } -void ConfigLoader::LoadCoreAffinity(toml::table &tbl, Config &out_config) { - if (!tbl.contains("core_affinity")) - return; - - auto val = tbl["core_affinity"]; - - // core_affinity = "all" - if (auto s = val.value(); s && *s == "all") { - out_config.core_affinity = Config::kDefaultAffinity; - } - // core_affinity = [ ... ] - else if (auto arr = val.as_array()) { - unsigned int max_cpu = MaxOnlineCpus(); - cpu_set_t mask; - CPU_ZERO(&mask); - // NOTE: Should setting the affinity in here? - for (auto &item : *arr) { - // liczba CPU - if (auto cpu = item.value()) { - if (!AddCpu(mask, *cpu, max_cpu)) { - std::cerr << "CPU index out of range: " << *cpu << "\n"; - return; - } - } - // zakres "X-Y" - else if (auto str = item.value()) { - unsigned int from, to; - if (sscanf(str->c_str(), "%u-%u", &from, &to) == 2) { - if (!AddRange(mask, from, to, max_cpu)) { - std::cerr << "Invalid CPU range: " << *str << "\n"; - return; - } - } else { - std::cerr << "Invalid core_affinity entry: " << *str << "\n"; - return; - } - } else { - std::cerr << "Invalid core_affinity element type\n"; - return; - } +void ConfigLoader::LoadCoreAffinity(toml::table& tbl, Config& out_config) { + if (!tbl.contains("core_affinity")) return; + + auto val = tbl["core_affinity"]; + + // core_affinity = "all" + if (auto s = val.value(); s && *s == "all") { + out_config.core_affinity = Config::kDefaultAffinity; + } + // core_affinity = [ ... ] + else if (auto arr = val.as_array()) { + unsigned int max_cpu = MaxOnlineCpus(); + cpu_set_t mask; + CPU_ZERO(&mask); + // NOTE: Should setting the affinity in here? + for (auto& item : *arr) { + // liczba CPU + if (auto cpu = item.value()) { + if (!AddCpu(mask, *cpu, max_cpu)) { + std::cerr << "CPU index out of range: " << *cpu << "\n"; + return; } - if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { - perror("sched_setaffinity"); + } + // zakres "X-Y" + else if (auto str = item.value()) { + unsigned int from, to; + if (sscanf(str->c_str(), "%u-%u", &from, &to) == 2) { + if (!AddRange(mask, from, to, max_cpu)) { + std::cerr << "Invalid CPU range: " << *str << "\n"; + return; + } } else { - std::cout << "Successfully set CPU affinity mask." << std::endl; + std::cerr << "Invalid core_affinity entry: " << *str << "\n"; + return; } - - out_config.core_affinity = mask; + } else { + std::cerr << "Invalid core_affinity element type\n"; + return; + } + } + if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { + perror("sched_setaffinity"); } else { - std::cerr << "Invalid core_affinity value\n"; + std::cout << "Successfully set CPU affinity mask." << std::endl; } + + out_config.core_affinity = mask; + } else { + std::cerr << "Invalid core_affinity value\n"; + } } -void ConfigLoader::LoadInterval(toml::table &tbl, Config &out_config) { - if (!tbl.contains("interval")) - return; +void ConfigLoader::LoadInterval(toml::table& tbl, Config& out_config) { + if (!tbl.contains("interval")) return; - auto val = tbl["interval"]; + auto val = tbl["interval"]; - if (auto ms = val.value()) { - out_config.collection_interval = std::chrono::milliseconds(*ms); - std::cout << "Collection Interval set to: " << out_config.collection_interval << std::endl; - } else { - std::cerr << "Invalid interval value type, use uint32" << std::endl; - } + if (auto ms = val.value()) { + out_config.collection_interval = std::chrono::milliseconds(*ms); + std::cout << "Collection Interval set to: " + << out_config.collection_interval << std::endl; + } else { + std::cerr << "Invalid interval value type, use uint32" << std::endl; + } } -void ConfigLoader::LoadServerAddress(toml::table &tbl, Config &out_config) { - if (!tbl.contains("server_address")) - return; +void ConfigLoader::LoadServerAddress(toml::table& tbl, Config& out_config) { + if (!tbl.contains("server_address")) return; - auto val = tbl["server_address"]; + auto val = tbl["server_address"]; - if (auto str = val.value()) { - namespace utils = volta::agent::utils; - if (utils::IsValidIP(*str) || utils::IsResolvable(*str)) { - out_config.server_address = *str; - std::cout << "Server Address set to " << *str << std::endl; - } else { - std::cerr << "Invalid server_address format" << std::endl; - } + if (auto str = val.value()) { + namespace utils = volta::agent::utils; + if (utils::IsValidIP(*str) || utils::IsResolvable(*str)) { + out_config.server_address = *str; + std::cout << "Server Address set to " << *str << std::endl; } else { - std::cerr << "Invalid server_address value type, use string" << std::endl; + std::cerr << "Invalid server_address format" << std::endl; } + } else { + std::cerr << "Invalid server_address value type, use string" << std::endl; + } } -void ConfigLoader::LoadServerPort(toml::table &tbl, Config &out_config) { - if (!tbl.contains("server_port")) - return; +void ConfigLoader::LoadServerPort(toml::table& tbl, Config& out_config) { + if (!tbl.contains("server_port")) return; - auto val = tbl["server_port"]; + auto val = tbl["server_port"]; - if (auto port = val.value(); port && *port > 0) { - out_config.server_port = *port; - std::cout << "Server port set to " << *port << std::endl; - } else { - std::cerr << "server_port has an incorrect type or value, use number " - "from range " - "[1, 65535]" - << std::endl; - } + if (auto port = val.value(); port && *port > 0) { + out_config.server_port = *port; + std::cout << "Server port set to " << *port << std::endl; + } else { + std::cerr << "server_port has an incorrect type or value, use number " + "from range " + "[1, 65535]" + << std::endl; + } } -void ConfigLoader::LoadCollectors(toml::table &tbl, Config &out_config) { - if (!tbl.contains("collectors")) - return; +void ConfigLoader::LoadCollectors(toml::table& tbl, Config& out_config) { + if (!tbl.contains("collectors")) return; - auto collectors_node = tbl["collectors"].as_table(); + auto collectors_node = tbl["collectors"].as_table(); - for (auto &&[hardware_type, hardware_node] : *collectors_node) { - if (!kValidCollectors.contains(hardware_type.str())) { - std::cerr << "Invalid hardware type: " << hardware_type << std::endl; - continue; - } + for (auto&& [hardware_type, hardware_node] : *collectors_node) { + if (!kValidCollectors.contains(hardware_type.str())) { + std::cerr << "Invalid hardware type: " << hardware_type << std::endl; + continue; + } - auto collectors = hardware_node.as_array(); - if (!collectors) { - std::cout << "Element " << hardware_type << " is not an array\n"; - continue; - } + auto collectors = hardware_node.as_array(); + if (!collectors) { + std::cout << "Element " << hardware_type << " is not an array\n"; + continue; + } - CollectorConfig collector_config; - - std::cout << hardware_type << std::endl; - for (auto &&collector : *collectors) { - if (auto str = collector.value()) { - const auto &collector_set = kValidCollectors[hardware_type.str()]; - if (!collector_set.contains(*str)) { - std::cout << "Invalid collector: " << *str - << ", for hardware: " << hardware_type << std::endl; - continue; - } - - std::cout << *str << std::endl; - // TODO: Add metrics - - collector_config.enabled = !collector_config.metrics.empty(); - } else { - std::cerr << "Invalid type in " << hardware_type << " array\n"; - } + CollectorConfig collector_config; + + std::cout << hardware_type << std::endl; + for (auto&& collector : *collectors) { + if (auto str = collector.value()) { + const auto& collector_set = kValidCollectors[hardware_type.str()]; + if (!collector_set.contains(*str)) { + std::cout << "Invalid collector: " << *str + << ", for hardware: " << hardware_type << std::endl; + continue; } + + std::cout << *str << std::endl; + // TODO: Add metrics + + collector_config.enabled = !collector_config.metrics.empty(); + } else { + std::cerr << "Invalid type in " << hardware_type << " array\n"; + } } + } } -void ConfigLoader::CheckKeys(toml::table &tbl) { - for (auto &&[key, value] : tbl) { - if (!kValidTopLevelKeys.contains(key.str())) { - std::cout << "Key '" << key << "' is not a valid key\n"; - } +void ConfigLoader::CheckKeys(toml::table& tbl) { + for (auto&& [key, value] : tbl) { + if (!kValidTopLevelKeys.contains(key.str())) { + std::cout << "Key '" << key << "' is not a valid key\n"; } + } } -} // namespace config -} // namespace agent -} // namespace volta +void ConfigLoader::LoadUUID(Config& out_config) {} + +} // namespace config +} // namespace agent +} // namespace volta diff --git a/source/agent/src/config/config_loader.h b/source/agent/src/config/config_loader.h index 9d329bf..25c4b1b 100644 --- a/source/agent/src/config/config_loader.h +++ b/source/agent/src/config/config_loader.h @@ -13,29 +13,31 @@ namespace agent { namespace config { class ConfigLoader { - public: - static Config LoadConfig(); - static Config LoadDefaultConfig(); - - private: - ConfigLoader() = delete; - - static void LoadConfigFile(Config &out_config); - static void LoadCoreAffinity(toml::table &tbl, Config &out_config); - static void LoadInterval(toml::table &tbl, Config &out_config); - static void LoadServerAddress(toml::table &tbl, Config &out_config); - static void LoadServerPort(toml::table &tbl, Config &out_config); - static void LoadCollectors(toml::table &tbl, Config &out_config); - static void CheckKeys(toml::table &tbl); - - static std::filesystem::path kConfigFile; - static std::set> kValidTopLevelKeys; - static std::map>, std::less<>> - kValidCollectors; + public: + static Config LoadConfig(); + static Config LoadDefaultConfig(); + + private: + ConfigLoader() = delete; + + static void LoadUUID(Config& out_config); + static void LoadConfigFile(Config& out_config); + static void LoadCoreAffinity(toml::table& tbl, Config& out_config); + static void LoadInterval(toml::table& tbl, Config& out_config); + static void LoadServerAddress(toml::table& tbl, Config& out_config); + static void LoadServerPort(toml::table& tbl, Config& out_config); + static void LoadCollectors(toml::table& tbl, Config& out_config); + static void CheckKeys(toml::table& tbl); + + static std::filesystem::path kConfigFile; + static std::set> kValidTopLevelKeys; + static std::map>, + std::less<>> + kValidCollectors; }; -} // namespace config -} // namespace agent -} // namespace volta +} // namespace config +} // namespace agent +} // namespace volta -#endif // VOLTA_AGENT_CONFIG_CONFIG_LOADER_H_ +#endif // VOLTA_AGENT_CONFIG_CONFIG_LOADER_H_ diff --git a/source/agent/src/utils/utils.cc b/source/agent/src/utils/utils.cc index e2a6888..9afc176 100644 --- a/source/agent/src/utils/utils.cc +++ b/source/agent/src/utils/utils.cc @@ -3,27 +3,52 @@ #include #include +#include +#include + namespace volta { namespace agent { namespace utils { -bool IsValidIP(const std::string &ip) { - sockaddr_in sa4{}; - sockaddr_in6 sa6{}; +bool IsValidIP(const std::string& ip) { + sockaddr_in sa4{}; + sockaddr_in6 sa6{}; + + return inet_pton(AF_INET, ip.c_str(), &sa4.sin_addr) == 1 || + inet_pton(AF_INET6, ip.c_str(), &sa6.sin6_addr) == 1; +} + +bool IsResolvable(const std::string& host) { + addrinfo hints{}, *res = nullptr; + hints.ai_family = AF_UNSPEC; - return inet_pton(AF_INET, ip.c_str(), &sa4.sin_addr) == 1 || - inet_pton(AF_INET6, ip.c_str(), &sa6.sin6_addr) == 1; + bool ok = getaddrinfo(host.c_str(), nullptr, &hints, &res) == 0; + freeaddrinfo(res); + return ok; } -bool IsResolvable(const std::string &host) { - addrinfo hints{}, *res = nullptr; - hints.ai_family = AF_UNSPEC; +std::string GenerateUUIDv4() { + std::random_device rd; + std::mt19937_64 gen(rd()); + std::uniform_int_distribution dist; + + uint64_t a = dist(gen); + uint64_t b = dist(gen); + + // version 4 + a = (a & 0xffffffffffff0fffULL) | 0x0000000000004000ULL; + // variant 1 (RFC 4122) + b = (b & 0x3fffffffffffffffULL) | 0x8000000000000000ULL; + + std::ostringstream oss; + oss << std::hex << std::setfill('0') << std::setw(8) << (a >> 32) << "-" + << std::setw(4) << ((a >> 16) & 0xffff) << "-" << std::setw(4) + << (a & 0xffff) << "-" << std::setw(4) << (b >> 48) << "-" + << std::setw(12) << (b & 0x0000ffffffffffffULL); - bool ok = getaddrinfo(host.c_str(), nullptr, &hints, &res) == 0; - freeaddrinfo(res); - return ok; + return oss.str(); } -} // namespace utils -} // namespace agent -} // namespace volta +} // namespace utils +} // namespace agent +} // namespace volta diff --git a/source/agent/src/utils/utils.h b/source/agent/src/utils/utils.h index 133977d..77ae5c9 100644 --- a/source/agent/src/utils/utils.h +++ b/source/agent/src/utils/utils.h @@ -9,6 +9,7 @@ namespace utils { bool IsValidIP(const std::string& ip); bool IsResolvable(const std::string& host); +std::string GenerateUUIDv4(); } // namespace utils } // namespace agent From 5f9c43d0b61f608c37bccea9b77d9c6370592f68 Mon Sep 17 00:00:00 2001 From: kox13 Date: Tue, 3 Feb 2026 13:23:34 +0100 Subject: [PATCH 07/10] chore(agent): add commits that correct format to blame ignore --- .git-blame-ignore-revs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 68bbb0c..f73cfbe 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,2 +1,5 @@ # Mass reformatting - introducing CI Agent (Issue #14) 433cd2b661a88b143fae6e215a487280a5dedf05 +189ff3dffca02d8824919060b24ef0a084c609af +a91de65471c7ad4145a5b509b06a1d08ca1dfd6f + From 029a14ed1758727e96ca1aba39263e6d8e940e11 Mon Sep 17 00:00:00 2001 From: kox13 Date: Tue, 3 Feb 2026 14:15:47 +0100 Subject: [PATCH 08/10] feat(agent): create UUID and save to file, load after each startup --- source/agent/src/config/config_loader.cc | 395 ++++++++++++----------- source/agent/src/config/config_loader.h | 51 +-- 2 files changed, 241 insertions(+), 205 deletions(-) diff --git a/source/agent/src/config/config_loader.cc b/source/agent/src/config/config_loader.cc index 50f40fb..480953b 100644 --- a/source/agent/src/config/config_loader.cc +++ b/source/agent/src/config/config_loader.cc @@ -1,250 +1,285 @@ #include "config/config_loader.h" +#include +#include #include #include #include #include +#include #include "utils/utils.h" +namespace utils = volta::agent::utils; + namespace volta { namespace agent { namespace config { std::filesystem::path ConfigLoader::kConfigFile = "agent.conf"; +std::filesystem::path ConfigLoader::kUUIDFile = "agent.uuid"; std::set> ConfigLoader::kValidTopLevelKeys = { "core_affinity", "interval", "server_address", "server_port", "collectors"}; std::map>, std::less<>> - ConfigLoader::kValidCollectors = { - {"cpu", {"proc_stat", "cpu_freq", "rapl", "zenpower", "pmu"}}, - {"gpu", {"nvml", "dcgm", "rocm", "level_zero"}}, - {"ram", {"mem_info", "vm_stat"}}, - {"io", {"disk_stats", "net_dev"}}}; + ConfigLoader::kValidCollectors = {{"cpu", {"proc_stat", "cpu_freq", "rapl", "zenpower", "pmu"}}, + {"gpu", {"nvml", "dcgm", "rocm", "level_zero"}}, + {"ram", {"mem_info", "vm_stat"}}, + {"io", {"disk_stats", "net_dev"}}}; Config ConfigLoader::LoadConfig() { - Config config = LoadDefaultConfig(); - LoadConfigFile(config); - return config; + Config config = LoadDefaultConfig(); + LoadConfigFile(config); + return config; } Config ConfigLoader::LoadDefaultConfig() { - Config config; - - // load config - // if id file exitsts load else genereate uuid and save to file - LoadUUID(config); - - CollectorConfig nvml_collector; - nvml_collector.enabled = true; - nvml_collector.metrics = { - {"gpu_utilization", true}, - {"memory_utilization", true}, - {"temperature", true}, - }; - config.collectors[CollectorNames::kNvml] = nvml_collector; - - CollectorConfig proc_stat_config; - proc_stat_config.enabled = true; - proc_stat_config.metrics["cpu_usage_percent"] = true; - config.collectors[CollectorNames::kProcStat] = proc_stat_config; - - return config; + Config config; + + if (!LoadUUID(config)) + CreateUUID(config); + + CollectorConfig nvml_collector; + nvml_collector.enabled = true; + nvml_collector.metrics = { + {"gpu_utilization", true}, + {"memory_utilization", true}, + {"temperature", true}, + }; + config.collectors[CollectorNames::kNvml] = nvml_collector; + + CollectorConfig proc_stat_config; + proc_stat_config.enabled = true; + proc_stat_config.metrics["cpu_usage_percent"] = true; + config.collectors[CollectorNames::kProcStat] = proc_stat_config; + + return config; } inline unsigned int MaxOnlineCpus() { - long n = sysconf(_SC_NPROCESSORS_ONLN); - return (n > 0) ? static_cast(n) : 0; -} - -bool AddCpu(cpu_set_t& set, unsigned int cpu, unsigned int max_cpu) { - if (cpu >= max_cpu) return false; - CPU_SET(cpu, &set); - return true; + long n = sysconf(_SC_NPROCESSORS_ONLN); + return (n > 0) ? static_cast(n) : 0; } -bool AddRange(cpu_set_t& set, unsigned int from, unsigned int to, - unsigned int max_cpu) { - if (from > to || to >= max_cpu) return false; - for (unsigned int i = from; i <= to; ++i) CPU_SET(i, &set); - return true; +bool AddCpu(cpu_set_t &set, unsigned int cpu, unsigned int max_cpu) { + if (cpu >= max_cpu) + return false; + CPU_SET(cpu, &set); + return true; } -void ConfigLoader::LoadConfigFile(Config& out_config) { - // TODO: Proper logging - if (!std::filesystem::exists(kConfigFile)) { - std::cout << "Agent config file not found, loading default settings." - << std::endl; - return; - } - - try { - toml::table tbl = toml::parse_file(kConfigFile.string()); - - LoadCoreAffinity(tbl, out_config); - LoadInterval(tbl, out_config); - LoadServerAddress(tbl, out_config); - LoadServerPort(tbl, out_config); - LoadCollectors(tbl, out_config); - CheckKeys(tbl); - } catch (const toml::parse_error& err) { - std::cerr << "Parsing Agent config failed: " << err.description() << " at " - << err.source().begin << std::endl; - } +bool AddRange(cpu_set_t &set, unsigned int from, unsigned int to, unsigned int max_cpu) { + if (from > to || to >= max_cpu) + return false; + for (unsigned int i = from; i <= to; ++i) + CPU_SET(i, &set); + return true; } -void ConfigLoader::LoadCoreAffinity(toml::table& tbl, Config& out_config) { - if (!tbl.contains("core_affinity")) return; - - auto val = tbl["core_affinity"]; - - // core_affinity = "all" - if (auto s = val.value(); s && *s == "all") { - out_config.core_affinity = Config::kDefaultAffinity; - } - // core_affinity = [ ... ] - else if (auto arr = val.as_array()) { - unsigned int max_cpu = MaxOnlineCpus(); - cpu_set_t mask; - CPU_ZERO(&mask); - // NOTE: Should setting the affinity in here? - for (auto& item : *arr) { - // liczba CPU - if (auto cpu = item.value()) { - if (!AddCpu(mask, *cpu, max_cpu)) { - std::cerr << "CPU index out of range: " << *cpu << "\n"; - return; - } - } - // zakres "X-Y" - else if (auto str = item.value()) { - unsigned int from, to; - if (sscanf(str->c_str(), "%u-%u", &from, &to) == 2) { - if (!AddRange(mask, from, to, max_cpu)) { - std::cerr << "Invalid CPU range: " << *str << "\n"; - return; - } - } else { - std::cerr << "Invalid core_affinity entry: " << *str << "\n"; - return; - } - } else { - std::cerr << "Invalid core_affinity element type\n"; +void ConfigLoader::LoadConfigFile(Config &out_config) { + // TODO: Proper logging + if (!std::filesystem::exists(kConfigFile)) { + std::cout << "Agent config file not found, loading default settings." << std::endl; return; - } } - if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { - perror("sched_setaffinity"); - } else { - std::cout << "Successfully set CPU affinity mask." << std::endl; + + try { + toml::table tbl = toml::parse_file(kConfigFile.string()); + + LoadCoreAffinity(tbl, out_config); + LoadInterval(tbl, out_config); + LoadServerAddress(tbl, out_config); + LoadServerPort(tbl, out_config); + LoadCollectors(tbl, out_config); + CheckKeys(tbl); + } catch (const toml::parse_error &err) { + std::cerr << "Parsing Agent config failed: " << err.description() << " at " + << err.source().begin << std::endl; } +} + +bool ConfigLoader::LoadUUID(Config &out_config) { + if (!std::filesystem::exists(kUUIDFile)) + return false; - out_config.core_affinity = mask; - } else { - std::cerr << "Invalid core_affinity value\n"; - } + // TODO: Handle errors + std::fstream f(kUUIDFile); + std::string uuid; + std::getline(f, uuid); + out_config.uuid = uuid; + return true; } -void ConfigLoader::LoadInterval(toml::table& tbl, Config& out_config) { - if (!tbl.contains("interval")) return; +void ConfigLoader::CreateUUID(Config &out_config) { + // TODO: Handle errors + std::string uuid = utils::GenerateUUIDv4(); - auto val = tbl["interval"]; + std::filesystem::path tmp = kUUIDFile; + tmp += ".tmp"; - if (auto ms = val.value()) { - out_config.collection_interval = std::chrono::milliseconds(*ms); - std::cout << "Collection Interval set to: " - << out_config.collection_interval << std::endl; - } else { - std::cerr << "Invalid interval value type, use uint32" << std::endl; - } + { + std::ofstream f(tmp, std::ios::trunc); + f << uuid; + f.flush(); + } + + std::filesystem::rename(tmp, kUUIDFile); + out_config.uuid = uuid; } -void ConfigLoader::LoadServerAddress(toml::table& tbl, Config& out_config) { - if (!tbl.contains("server_address")) return; +void ConfigLoader::LoadCoreAffinity(toml::table &tbl, Config &out_config) { + if (!tbl.contains("core_affinity")) + return; - auto val = tbl["server_address"]; + auto val = tbl["core_affinity"]; - if (auto str = val.value()) { - namespace utils = volta::agent::utils; - if (utils::IsValidIP(*str) || utils::IsResolvable(*str)) { - out_config.server_address = *str; - std::cout << "Server Address set to " << *str << std::endl; + // core_affinity = "all" + if (auto s = val.value(); s && *s == "all") { + out_config.core_affinity = Config::kDefaultAffinity; + } + // core_affinity = [ ... ] + else if (auto arr = val.as_array()) { + unsigned int max_cpu = MaxOnlineCpus(); + cpu_set_t mask; + CPU_ZERO(&mask); + // NOTE: Should setting the affinity in here? + for (auto &item : *arr) { + // liczba CPU + if (auto cpu = item.value()) { + if (!AddCpu(mask, *cpu, max_cpu)) { + std::cerr << "CPU index out of range: " << *cpu << "\n"; + return; + } + } + // zakres "X-Y" + else if (auto str = item.value()) { + unsigned int from, to; + if (sscanf(str->c_str(), "%u-%u", &from, &to) == 2) { + if (!AddRange(mask, from, to, max_cpu)) { + std::cerr << "Invalid CPU range: " << *str << "\n"; + return; + } + } else { + std::cerr << "Invalid core_affinity entry: " << *str << "\n"; + return; + } + } else { + std::cerr << "Invalid core_affinity element type\n"; + return; + } + } + if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { + perror("sched_setaffinity"); + } else { + std::cout << "Successfully set CPU affinity mask." << std::endl; + } + + out_config.core_affinity = mask; } else { - std::cerr << "Invalid server_address format" << std::endl; + std::cerr << "Invalid core_affinity value\n"; } - } else { - std::cerr << "Invalid server_address value type, use string" << std::endl; - } } -void ConfigLoader::LoadServerPort(toml::table& tbl, Config& out_config) { - if (!tbl.contains("server_port")) return; +void ConfigLoader::LoadInterval(toml::table &tbl, Config &out_config) { + if (!tbl.contains("interval")) + return; - auto val = tbl["server_port"]; + auto val = tbl["interval"]; - if (auto port = val.value(); port && *port > 0) { - out_config.server_port = *port; - std::cout << "Server port set to " << *port << std::endl; - } else { - std::cerr << "server_port has an incorrect type or value, use number " - "from range " - "[1, 65535]" - << std::endl; - } + if (auto ms = val.value()) { + out_config.collection_interval = std::chrono::milliseconds(*ms); + std::cout << "Collection Interval set to: " << out_config.collection_interval << std::endl; + } else { + std::cerr << "Invalid interval value type, use uint32" << std::endl; + } } -void ConfigLoader::LoadCollectors(toml::table& tbl, Config& out_config) { - if (!tbl.contains("collectors")) return; +void ConfigLoader::LoadServerAddress(toml::table &tbl, Config &out_config) { + if (!tbl.contains("server_address")) + return; - auto collectors_node = tbl["collectors"].as_table(); + auto val = tbl["server_address"]; - for (auto&& [hardware_type, hardware_node] : *collectors_node) { - if (!kValidCollectors.contains(hardware_type.str())) { - std::cerr << "Invalid hardware type: " << hardware_type << std::endl; - continue; + if (auto str = val.value()) { + if (utils::IsValidIP(*str) || utils::IsResolvable(*str)) { + out_config.server_address = *str; + std::cout << "Server Address set to " << *str << std::endl; + } else { + std::cerr << "Invalid server_address format" << std::endl; + } + } else { + std::cerr << "Invalid server_address value type, use string" << std::endl; } +} + +void ConfigLoader::LoadServerPort(toml::table &tbl, Config &out_config) { + if (!tbl.contains("server_port")) + return; - auto collectors = hardware_node.as_array(); - if (!collectors) { - std::cout << "Element " << hardware_type << " is not an array\n"; - continue; + auto val = tbl["server_port"]; + + if (auto port = val.value(); port && *port > 0) { + out_config.server_port = *port; + std::cout << "Server port set to " << *port << std::endl; + } else { + std::cerr << "server_port has an incorrect type or value, use number " + "from range " + "[1, 65535]" + << std::endl; } +} + +void ConfigLoader::LoadCollectors(toml::table &tbl, Config &out_config) { + if (!tbl.contains("collectors")) + return; - CollectorConfig collector_config; + auto collectors_node = tbl["collectors"].as_table(); - std::cout << hardware_type << std::endl; - for (auto&& collector : *collectors) { - if (auto str = collector.value()) { - const auto& collector_set = kValidCollectors[hardware_type.str()]; - if (!collector_set.contains(*str)) { - std::cout << "Invalid collector: " << *str - << ", for hardware: " << hardware_type << std::endl; - continue; + for (auto &&[hardware_type, hardware_node] : *collectors_node) { + if (!kValidCollectors.contains(hardware_type.str())) { + std::cerr << "Invalid hardware type: " << hardware_type << std::endl; + continue; } - std::cout << *str << std::endl; - // TODO: Add metrics + auto collectors = hardware_node.as_array(); + if (!collectors) { + std::cout << "Element " << hardware_type << " is not an array\n"; + continue; + } - collector_config.enabled = !collector_config.metrics.empty(); - } else { - std::cerr << "Invalid type in " << hardware_type << " array\n"; - } + CollectorConfig collector_config; + + std::cout << hardware_type << std::endl; + for (auto &&collector : *collectors) { + if (auto str = collector.value()) { + const auto &collector_set = kValidCollectors[hardware_type.str()]; + if (!collector_set.contains(*str)) { + std::cout << "Invalid collector: " << *str + << ", for hardware: " << hardware_type << std::endl; + continue; + } + + std::cout << *str << std::endl; + // TODO: Add metrics + + collector_config.enabled = !collector_config.metrics.empty(); + } else { + std::cerr << "Invalid type in " << hardware_type << " array\n"; + } + } } - } } -void ConfigLoader::CheckKeys(toml::table& tbl) { - for (auto&& [key, value] : tbl) { - if (!kValidTopLevelKeys.contains(key.str())) { - std::cout << "Key '" << key << "' is not a valid key\n"; +void ConfigLoader::CheckKeys(toml::table &tbl) { + for (auto &&[key, value] : tbl) { + if (!kValidTopLevelKeys.contains(key.str())) { + std::cout << "Key '" << key << "' is not a valid key\n"; + } } - } } -void ConfigLoader::LoadUUID(Config& out_config) {} - -} // namespace config -} // namespace agent -} // namespace volta +} // namespace config +} // namespace agent +} // namespace volta diff --git a/source/agent/src/config/config_loader.h b/source/agent/src/config/config_loader.h index 25c4b1b..5c06c16 100644 --- a/source/agent/src/config/config_loader.h +++ b/source/agent/src/config/config_loader.h @@ -13,31 +13,32 @@ namespace agent { namespace config { class ConfigLoader { - public: - static Config LoadConfig(); - static Config LoadDefaultConfig(); - - private: - ConfigLoader() = delete; - - static void LoadUUID(Config& out_config); - static void LoadConfigFile(Config& out_config); - static void LoadCoreAffinity(toml::table& tbl, Config& out_config); - static void LoadInterval(toml::table& tbl, Config& out_config); - static void LoadServerAddress(toml::table& tbl, Config& out_config); - static void LoadServerPort(toml::table& tbl, Config& out_config); - static void LoadCollectors(toml::table& tbl, Config& out_config); - static void CheckKeys(toml::table& tbl); - - static std::filesystem::path kConfigFile; - static std::set> kValidTopLevelKeys; - static std::map>, - std::less<>> - kValidCollectors; + public: + static Config LoadConfig(); + static Config LoadDefaultConfig(); + + private: + ConfigLoader() = delete; + + static void LoadConfigFile(Config &out_config); + static bool LoadUUID(Config &out_config); + static void CreateUUID(Config &out_config); + static void LoadCoreAffinity(toml::table &tbl, Config &out_config); + static void LoadInterval(toml::table &tbl, Config &out_config); + static void LoadServerAddress(toml::table &tbl, Config &out_config); + static void LoadServerPort(toml::table &tbl, Config &out_config); + static void LoadCollectors(toml::table &tbl, Config &out_config); + static void CheckKeys(toml::table &tbl); + + static std::filesystem::path kConfigFile; + static std::filesystem::path kUUIDFile; + static std::set> kValidTopLevelKeys; + static std::map>, std::less<>> + kValidCollectors; }; -} // namespace config -} // namespace agent -} // namespace volta +} // namespace config +} // namespace agent +} // namespace volta -#endif // VOLTA_AGENT_CONFIG_CONFIG_LOADER_H_ +#endif // VOLTA_AGENT_CONFIG_CONFIG_LOADER_H_ From 821770ad1742a746b373d2bd0cf081f2eaebedd9 Mon Sep 17 00:00:00 2001 From: kox13 Date: Tue, 3 Feb 2026 19:39:01 +0100 Subject: [PATCH 09/10] style(agent): correct format --- source/agent/src/config/config_loader.cc | 405 +++++++++--------- source/agent/src/config/config_loader.h | 53 +-- .../agent/src/platform/platform_detector.cc | 2 - source/agent/src/platform/platform_detector.h | 2 - source/agent/src/scheduler.cc | 3 +- 5 files changed, 228 insertions(+), 237 deletions(-) diff --git a/source/agent/src/config/config_loader.cc b/source/agent/src/config/config_loader.cc index 480953b..8a81107 100644 --- a/source/agent/src/config/config_loader.cc +++ b/source/agent/src/config/config_loader.cc @@ -1,11 +1,11 @@ #include "config/config_loader.h" -#include -#include #include #include #include +#include +#include #include #include @@ -17,6 +17,7 @@ namespace volta { namespace agent { namespace config { +// TODO: different path for prod build std::filesystem::path ConfigLoader::kConfigFile = "agent.conf"; std::filesystem::path ConfigLoader::kUUIDFile = "agent.uuid"; @@ -24,262 +25,256 @@ std::set> ConfigLoader::kValidTopLevelKeys = { "core_affinity", "interval", "server_address", "server_port", "collectors"}; std::map>, std::less<>> - ConfigLoader::kValidCollectors = {{"cpu", {"proc_stat", "cpu_freq", "rapl", "zenpower", "pmu"}}, - {"gpu", {"nvml", "dcgm", "rocm", "level_zero"}}, - {"ram", {"mem_info", "vm_stat"}}, - {"io", {"disk_stats", "net_dev"}}}; + ConfigLoader::kValidCollectors = { + {"cpu", {"proc_stat", "cpu_freq", "rapl", "zenpower", "pmu"}}, + {"gpu", {"nvml", "dcgm", "rocm", "level_zero"}}, + {"ram", {"mem_info", "vm_stat"}}, + {"io", {"disk_stats", "net_dev"}}}; Config ConfigLoader::LoadConfig() { - Config config = LoadDefaultConfig(); - LoadConfigFile(config); - return config; + Config config = LoadDefaultConfig(); + LoadConfigFile(config); + return config; } Config ConfigLoader::LoadDefaultConfig() { - Config config; - - if (!LoadUUID(config)) - CreateUUID(config); - - CollectorConfig nvml_collector; - nvml_collector.enabled = true; - nvml_collector.metrics = { - {"gpu_utilization", true}, - {"memory_utilization", true}, - {"temperature", true}, - }; - config.collectors[CollectorNames::kNvml] = nvml_collector; - - CollectorConfig proc_stat_config; - proc_stat_config.enabled = true; - proc_stat_config.metrics["cpu_usage_percent"] = true; - config.collectors[CollectorNames::kProcStat] = proc_stat_config; - - return config; + Config config; + + if (!LoadUUID(config)) CreateUUID(config); + + CollectorConfig nvml_collector; + nvml_collector.enabled = true; + nvml_collector.metrics = { + {"gpu_utilization", true}, + {"memory_utilization", true}, + {"temperature", true}, + }; + config.collectors[CollectorNames::kNvml] = nvml_collector; + + CollectorConfig proc_stat_config; + proc_stat_config.enabled = true; + proc_stat_config.metrics["cpu_usage_percent"] = true; + config.collectors[CollectorNames::kProcStat] = proc_stat_config; + + return config; } inline unsigned int MaxOnlineCpus() { - long n = sysconf(_SC_NPROCESSORS_ONLN); - return (n > 0) ? static_cast(n) : 0; + long n = sysconf(_SC_NPROCESSORS_ONLN); + return (n > 0) ? static_cast(n) : 0; } -bool AddCpu(cpu_set_t &set, unsigned int cpu, unsigned int max_cpu) { - if (cpu >= max_cpu) - return false; - CPU_SET(cpu, &set); - return true; +bool AddCpu(cpu_set_t& set, unsigned int cpu, unsigned int max_cpu) { + if (cpu >= max_cpu) return false; + CPU_SET(cpu, &set); + return true; } -bool AddRange(cpu_set_t &set, unsigned int from, unsigned int to, unsigned int max_cpu) { - if (from > to || to >= max_cpu) - return false; - for (unsigned int i = from; i <= to; ++i) - CPU_SET(i, &set); - return true; +bool AddRange(cpu_set_t& set, unsigned int from, unsigned int to, + unsigned int max_cpu) { + if (from > to || to >= max_cpu) return false; + for (unsigned int i = from; i <= to; ++i) CPU_SET(i, &set); + return true; } -void ConfigLoader::LoadConfigFile(Config &out_config) { - // TODO: Proper logging - if (!std::filesystem::exists(kConfigFile)) { - std::cout << "Agent config file not found, loading default settings." << std::endl; - return; - } - - try { - toml::table tbl = toml::parse_file(kConfigFile.string()); - - LoadCoreAffinity(tbl, out_config); - LoadInterval(tbl, out_config); - LoadServerAddress(tbl, out_config); - LoadServerPort(tbl, out_config); - LoadCollectors(tbl, out_config); - CheckKeys(tbl); - } catch (const toml::parse_error &err) { - std::cerr << "Parsing Agent config failed: " << err.description() << " at " - << err.source().begin << std::endl; - } +void ConfigLoader::LoadConfigFile(Config& out_config) { + // TODO: Proper logging + if (!std::filesystem::exists(kConfigFile)) { + std::cout << "Agent config file not found, loading default settings." + << std::endl; + return; + } + + try { + toml::table tbl = toml::parse_file(kConfigFile.string()); + + LoadCoreAffinity(tbl, out_config); + LoadInterval(tbl, out_config); + LoadServerAddress(tbl, out_config); + LoadServerPort(tbl, out_config); + LoadCollectors(tbl, out_config); + CheckKeys(tbl); + } catch (const toml::parse_error& err) { + std::cerr << "Parsing Agent config failed: " << err.description() << " at " + << err.source().begin << std::endl; + } } -bool ConfigLoader::LoadUUID(Config &out_config) { - if (!std::filesystem::exists(kUUIDFile)) - return false; +bool ConfigLoader::LoadUUID(Config& out_config) { + if (!std::filesystem::exists(kUUIDFile)) return false; - // TODO: Handle errors - std::fstream f(kUUIDFile); - std::string uuid; - std::getline(f, uuid); - out_config.uuid = uuid; - return true; + // TODO: Handle errors + std::fstream f(kUUIDFile); + std::string uuid; + std::getline(f, uuid); + out_config.uuid = uuid; + return true; } -void ConfigLoader::CreateUUID(Config &out_config) { - // TODO: Handle errors - std::string uuid = utils::GenerateUUIDv4(); +void ConfigLoader::CreateUUID(Config& out_config) { + // TODO: Handle errors + std::string uuid = utils::GenerateUUIDv4(); - std::filesystem::path tmp = kUUIDFile; - tmp += ".tmp"; + std::filesystem::path tmp = kUUIDFile; + tmp += ".tmp"; - { - std::ofstream f(tmp, std::ios::trunc); - f << uuid; - f.flush(); - } + { + std::ofstream f(tmp, std::ios::trunc); + f << uuid; + f.flush(); + } - std::filesystem::rename(tmp, kUUIDFile); - out_config.uuid = uuid; + std::filesystem::rename(tmp, kUUIDFile); + out_config.uuid = uuid; } -void ConfigLoader::LoadCoreAffinity(toml::table &tbl, Config &out_config) { - if (!tbl.contains("core_affinity")) - return; - - auto val = tbl["core_affinity"]; - - // core_affinity = "all" - if (auto s = val.value(); s && *s == "all") { - out_config.core_affinity = Config::kDefaultAffinity; - } - // core_affinity = [ ... ] - else if (auto arr = val.as_array()) { - unsigned int max_cpu = MaxOnlineCpus(); - cpu_set_t mask; - CPU_ZERO(&mask); - // NOTE: Should setting the affinity in here? - for (auto &item : *arr) { - // liczba CPU - if (auto cpu = item.value()) { - if (!AddCpu(mask, *cpu, max_cpu)) { - std::cerr << "CPU index out of range: " << *cpu << "\n"; - return; - } - } - // zakres "X-Y" - else if (auto str = item.value()) { - unsigned int from, to; - if (sscanf(str->c_str(), "%u-%u", &from, &to) == 2) { - if (!AddRange(mask, from, to, max_cpu)) { - std::cerr << "Invalid CPU range: " << *str << "\n"; - return; - } - } else { - std::cerr << "Invalid core_affinity entry: " << *str << "\n"; - return; - } - } else { - std::cerr << "Invalid core_affinity element type\n"; - return; - } +void ConfigLoader::LoadCoreAffinity(toml::table& tbl, Config& out_config) { + if (!tbl.contains("core_affinity")) return; + + auto val = tbl["core_affinity"]; + + // core_affinity = "all" + if (auto s = val.value(); s && *s == "all") { + out_config.core_affinity = Config::kDefaultAffinity; + } + // core_affinity = [ ... ] + else if (auto arr = val.as_array()) { + unsigned int max_cpu = MaxOnlineCpus(); + cpu_set_t mask; + CPU_ZERO(&mask); + // NOTE: Should setting the affinity in here? + for (auto& item : *arr) { + // liczba CPU + if (auto cpu = item.value()) { + if (!AddCpu(mask, *cpu, max_cpu)) { + std::cerr << "CPU index out of range: " << *cpu << "\n"; + return; } - if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { - perror("sched_setaffinity"); + } + // zakres "X-Y" + else if (auto str = item.value()) { + unsigned int from, to; + if (sscanf(str->c_str(), "%u-%u", &from, &to) == 2) { + if (!AddRange(mask, from, to, max_cpu)) { + std::cerr << "Invalid CPU range: " << *str << "\n"; + return; + } } else { - std::cout << "Successfully set CPU affinity mask." << std::endl; + std::cerr << "Invalid core_affinity entry: " << *str << "\n"; + return; } - - out_config.core_affinity = mask; + } else { + std::cerr << "Invalid core_affinity element type\n"; + return; + } + } + if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { + perror("sched_setaffinity"); } else { - std::cerr << "Invalid core_affinity value\n"; + std::cout << "Successfully set CPU affinity mask." << std::endl; } + + out_config.core_affinity = mask; + } else { + std::cerr << "Invalid core_affinity value\n"; + } } -void ConfigLoader::LoadInterval(toml::table &tbl, Config &out_config) { - if (!tbl.contains("interval")) - return; +void ConfigLoader::LoadInterval(toml::table& tbl, Config& out_config) { + if (!tbl.contains("interval")) return; - auto val = tbl["interval"]; + auto val = tbl["interval"]; - if (auto ms = val.value()) { - out_config.collection_interval = std::chrono::milliseconds(*ms); - std::cout << "Collection Interval set to: " << out_config.collection_interval << std::endl; - } else { - std::cerr << "Invalid interval value type, use uint32" << std::endl; - } + if (auto ms = val.value()) { + out_config.collection_interval = std::chrono::milliseconds(*ms); + std::cout << "Collection Interval set to: " + << out_config.collection_interval << std::endl; + } else { + std::cerr << "Invalid interval value type, use uint32" << std::endl; + } } -void ConfigLoader::LoadServerAddress(toml::table &tbl, Config &out_config) { - if (!tbl.contains("server_address")) - return; +void ConfigLoader::LoadServerAddress(toml::table& tbl, Config& out_config) { + if (!tbl.contains("server_address")) return; - auto val = tbl["server_address"]; + auto val = tbl["server_address"]; - if (auto str = val.value()) { - if (utils::IsValidIP(*str) || utils::IsResolvable(*str)) { - out_config.server_address = *str; - std::cout << "Server Address set to " << *str << std::endl; - } else { - std::cerr << "Invalid server_address format" << std::endl; - } + if (auto str = val.value()) { + if (utils::IsValidIP(*str) || utils::IsResolvable(*str)) { + out_config.server_address = *str; + std::cout << "Server Address set to " << *str << std::endl; } else { - std::cerr << "Invalid server_address value type, use string" << std::endl; + std::cerr << "Invalid server_address format" << std::endl; } + } else { + std::cerr << "Invalid server_address value type, use string" << std::endl; + } } -void ConfigLoader::LoadServerPort(toml::table &tbl, Config &out_config) { - if (!tbl.contains("server_port")) - return; +void ConfigLoader::LoadServerPort(toml::table& tbl, Config& out_config) { + if (!tbl.contains("server_port")) return; - auto val = tbl["server_port"]; + auto val = tbl["server_port"]; - if (auto port = val.value(); port && *port > 0) { - out_config.server_port = *port; - std::cout << "Server port set to " << *port << std::endl; - } else { - std::cerr << "server_port has an incorrect type or value, use number " - "from range " - "[1, 65535]" - << std::endl; - } + if (auto port = val.value(); port && *port > 0) { + out_config.server_port = *port; + std::cout << "Server port set to " << *port << std::endl; + } else { + std::cerr << "server_port has an incorrect type or value, use number " + "from range " + "[1, 65535]" + << std::endl; + } } -void ConfigLoader::LoadCollectors(toml::table &tbl, Config &out_config) { - if (!tbl.contains("collectors")) - return; +void ConfigLoader::LoadCollectors(toml::table& tbl, Config& out_config) { + if (!tbl.contains("collectors")) return; - auto collectors_node = tbl["collectors"].as_table(); + auto collectors_node = tbl["collectors"].as_table(); - for (auto &&[hardware_type, hardware_node] : *collectors_node) { - if (!kValidCollectors.contains(hardware_type.str())) { - std::cerr << "Invalid hardware type: " << hardware_type << std::endl; - continue; - } + for (auto&& [hardware_type, hardware_node] : *collectors_node) { + if (!kValidCollectors.contains(hardware_type.str())) { + std::cerr << "Invalid hardware type: " << hardware_type << std::endl; + continue; + } - auto collectors = hardware_node.as_array(); - if (!collectors) { - std::cout << "Element " << hardware_type << " is not an array\n"; - continue; - } + auto collectors = hardware_node.as_array(); + if (!collectors) { + std::cout << "Element " << hardware_type << " is not an array\n"; + continue; + } - CollectorConfig collector_config; - - std::cout << hardware_type << std::endl; - for (auto &&collector : *collectors) { - if (auto str = collector.value()) { - const auto &collector_set = kValidCollectors[hardware_type.str()]; - if (!collector_set.contains(*str)) { - std::cout << "Invalid collector: " << *str - << ", for hardware: " << hardware_type << std::endl; - continue; - } - - std::cout << *str << std::endl; - // TODO: Add metrics - - collector_config.enabled = !collector_config.metrics.empty(); - } else { - std::cerr << "Invalid type in " << hardware_type << " array\n"; - } + CollectorConfig collector_config; + + std::cout << hardware_type << std::endl; + for (auto&& collector : *collectors) { + if (auto str = collector.value()) { + const auto& collector_set = kValidCollectors[hardware_type.str()]; + if (!collector_set.contains(*str)) { + std::cout << "Invalid collector: " << *str + << ", for hardware: " << hardware_type << std::endl; + continue; } + + std::cout << *str << std::endl; + // TODO: Add metrics + + collector_config.enabled = !collector_config.metrics.empty(); + } else { + std::cerr << "Invalid type in " << hardware_type << " array\n"; + } } + } } -void ConfigLoader::CheckKeys(toml::table &tbl) { - for (auto &&[key, value] : tbl) { - if (!kValidTopLevelKeys.contains(key.str())) { - std::cout << "Key '" << key << "' is not a valid key\n"; - } +void ConfigLoader::CheckKeys(toml::table& tbl) { + for (auto&& [key, value] : tbl) { + if (!kValidTopLevelKeys.contains(key.str())) { + std::cout << "Key '" << key << "' is not a valid key\n"; } + } } -} // namespace config -} // namespace agent -} // namespace volta +} // namespace config +} // namespace agent +} // namespace volta diff --git a/source/agent/src/config/config_loader.h b/source/agent/src/config/config_loader.h index 5c06c16..2014423 100644 --- a/source/agent/src/config/config_loader.h +++ b/source/agent/src/config/config_loader.h @@ -13,32 +13,33 @@ namespace agent { namespace config { class ConfigLoader { - public: - static Config LoadConfig(); - static Config LoadDefaultConfig(); - - private: - ConfigLoader() = delete; - - static void LoadConfigFile(Config &out_config); - static bool LoadUUID(Config &out_config); - static void CreateUUID(Config &out_config); - static void LoadCoreAffinity(toml::table &tbl, Config &out_config); - static void LoadInterval(toml::table &tbl, Config &out_config); - static void LoadServerAddress(toml::table &tbl, Config &out_config); - static void LoadServerPort(toml::table &tbl, Config &out_config); - static void LoadCollectors(toml::table &tbl, Config &out_config); - static void CheckKeys(toml::table &tbl); - - static std::filesystem::path kConfigFile; - static std::filesystem::path kUUIDFile; - static std::set> kValidTopLevelKeys; - static std::map>, std::less<>> - kValidCollectors; + public: + static Config LoadConfig(); + static Config LoadDefaultConfig(); + + private: + ConfigLoader() = delete; + + static void LoadConfigFile(Config& out_config); + static bool LoadUUID(Config& out_config); + static void CreateUUID(Config& out_config); + static void LoadCoreAffinity(toml::table& tbl, Config& out_config); + static void LoadInterval(toml::table& tbl, Config& out_config); + static void LoadServerAddress(toml::table& tbl, Config& out_config); + static void LoadServerPort(toml::table& tbl, Config& out_config); + static void LoadCollectors(toml::table& tbl, Config& out_config); + static void CheckKeys(toml::table& tbl); + + static std::filesystem::path kConfigFile; + static std::filesystem::path kUUIDFile; + static std::set> kValidTopLevelKeys; + static std::map>, + std::less<>> + kValidCollectors; }; -} // namespace config -} // namespace agent -} // namespace volta +} // namespace config +} // namespace agent +} // namespace volta -#endif // VOLTA_AGENT_CONFIG_CONFIG_LOADER_H_ +#endif // VOLTA_AGENT_CONFIG_CONFIG_LOADER_H_ diff --git a/source/agent/src/platform/platform_detector.cc b/source/agent/src/platform/platform_detector.cc index f0ebb48..2de7fbd 100644 --- a/source/agent/src/platform/platform_detector.cc +++ b/source/agent/src/platform/platform_detector.cc @@ -5,9 +5,7 @@ #include #include #include -#include #include -#include #ifdef HAVE_NVML #include diff --git a/source/agent/src/platform/platform_detector.h b/source/agent/src/platform/platform_detector.h index 458f27c..88775ce 100644 --- a/source/agent/src/platform/platform_detector.h +++ b/source/agent/src/platform/platform_detector.h @@ -1,9 +1,7 @@ #ifndef VOLTA_AGENT_PLATFORM_PLATFORM_DETECTOR_H_ #define VOLTA_AGENT_PLATFORM_PLATFORM_DETECTOR_H_ -#include #include -#include #include "platform/hardware_info.h" diff --git a/source/agent/src/scheduler.cc b/source/agent/src/scheduler.cc index 74927c7..d6c806a 100644 --- a/source/agent/src/scheduler.cc +++ b/source/agent/src/scheduler.cc @@ -13,8 +13,7 @@ Scheduler::Scheduler( : config_(config), collectors_(std::move(collectors)) {} void Scheduler::Run() { - std::cout << "[" << typeid(*this).name() - << "] Starting collection loop (Interval: " + std::cout << "[" << config_.uuid << "] Starting collection loop (Interval: " << config_.collection_interval.count() << "ms)..." << std::endl; std::this_thread::sleep_for(config_.collection_interval); From 7a676003f6fb9bd11c44aed7e3693e6fde19c056 Mon Sep 17 00:00:00 2001 From: kox13 Date: Tue, 3 Feb 2026 20:06:40 +0100 Subject: [PATCH 10/10] chore(agent): add style commit to blame ignore --- .git-blame-ignore-revs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index f73cfbe..42becf3 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,5 +1,6 @@ # Mass reformatting - introducing CI Agent (Issue #14) 433cd2b661a88b143fae6e215a487280a5dedf05 + 189ff3dffca02d8824919060b24ef0a084c609af a91de65471c7ad4145a5b509b06a1d08ca1dfd6f - +821770ad1742a746b373d2bd0cf081f2eaebedd9