Skip to content

Commit

Permalink
Sys info metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
ErakhtinB committed Nov 26, 2024
1 parent a68a08a commit 0831592
Showing 1 changed file with 127 additions and 1 deletion.
128 changes: 127 additions & 1 deletion core/telemetry/impl/service_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "telemetry/impl/service_impl.hpp"

#include <sys/utsname.h>
#include <regex>

#include <fmt/core.h>
Expand Down Expand Up @@ -37,6 +38,91 @@ namespace {
document.Accept(writer);
return buffer.GetString();
}
struct SysInfo {
std::optional<std::string> cpu;
std::optional<bool> is_virtual_machine;
std::optional<size_t> core_count;
std::optional<uint64_t> memory;
std::optional<std::string> linux_distro;
};

// Function to read file content into a string
std::optional<std::string> read_file(const std::string &filepath) {
std::ifstream file(filepath);
if (not file.is_open()) {
return std::nullopt;
}
return {std::string((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>())};
}

// Function to extract a single match using regex
template <typename T>
std::optional<T> extract(const std::string &data, const std::regex &pattern) {
std::smatch match;
if (std::regex_search(data, match, pattern)) {
if constexpr (std::is_same<T, std::string>::value) {
return match[1].str();
} else if constexpr (std::is_integral<T>::value) {
return static_cast<T>(std::stoull(match[1].str()));
}
}
return std::nullopt;
}

SysInfo gather_linux_sysinfo() {
const std::regex LINUX_REGEX_CPU(R"(^model name\s*:\s*([^\n]+))",
std::regex_constants::multiline);
const std::regex LINUX_REGEX_PHYSICAL_ID(R"(^physical id\s*:\s*(\d+))",
std::regex_constants::multiline);
const std::regex LINUX_REGEX_CORE_ID(R"(^core id\s*:\s*(\d+))",
std::regex_constants::multiline);
const std::regex LINUX_REGEX_HYPERVISOR(R"(^flags\s*:.+?\bhypervisor\b)",
std::regex_constants::multiline);
const std::regex LINUX_REGEX_MEMORY(R"(^MemTotal:\s*(\d+) kB)",
std::regex_constants::multiline);
const std::regex LINUX_REGEX_DISTRO(R"(PRETTY_NAME\s*=\s*\"([^\"]+)\")",
std::regex_constants::multiline);

SysInfo sysinfo;

if (auto cpuinfo = read_file("/proc/cpuinfo")) {
sysinfo.cpu = extract<std::string>(*cpuinfo, LINUX_REGEX_CPU);
sysinfo.is_virtual_machine =
std::regex_search(*cpuinfo, LINUX_REGEX_HYPERVISOR);

// Extract unique {physical_id, core_id} pairs
std::set<std::pair<uint32_t, uint32_t>> cores;
std::regex section_split("\n\n");
std::sregex_token_iterator sections(
cpuinfo->begin(), cpuinfo->end(), section_split, -1);
std::sregex_token_iterator end;
for (; sections != end; ++sections) {
std::optional<uint32_t> pid =
extract<uint32_t>(*sections, LINUX_REGEX_PHYSICAL_ID);
std::optional<uint32_t> cid =
extract<uint32_t>(*sections, LINUX_REGEX_CORE_ID);
if (pid && cid) {
cores.emplace(*pid, *cid);
}
}
if (not cores.empty()) {
sysinfo.core_count = static_cast<uint32_t>(cores.size());
}
}

if (auto meminfo = read_file("/proc/meminfo")) {
sysinfo.memory =
extract<uint64_t>(*meminfo, LINUX_REGEX_MEMORY).value_or(0) * 1024;
}

if (auto os_release = read_file("/etc/os-release")) {
sysinfo.linux_distro =
extract<std::string>(*os_release, LINUX_REGEX_DISTRO);
}

return sysinfo;
}
} // namespace

namespace kagome::telemetry {
Expand Down Expand Up @@ -251,13 +337,52 @@ namespace kagome::telemetry {
allocator);
return val;
};
auto u64_val = [&allocator](uint64_t val) -> rapidjson::Value & {
static rapidjson::Value v;
v.SetUint64(val);
return v;
};

auto u32_val = [&allocator](uint32_t val) -> rapidjson::Value & {
static rapidjson::Value v;
v.SetUint(val);
return v;
};

auto startup_time =
std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count());

rapidjson::Value payload(rapidjson::kObjectType);
rapidjson::Value sys_info_json(rapidjson::kObjectType);
struct utsname utsmame_info;
if (uname(&utsmame_info) == 0) {
payload.AddMember(
"target_arch", str_val(utsmame_info.machine), allocator);
payload.AddMember("target_os", str_val(utsmame_info.sysname), allocator);
sys_info_json.AddMember(
"linux_kernel", str_val(utsmame_info.release), allocator);
}
const auto sys_info = gather_linux_sysinfo();
if (const auto &memory = sys_info.memory) {
sys_info_json.AddMember("memory", u64_val(*memory), allocator);
}
if (const auto &cpu = sys_info.cpu) {
sys_info_json.AddMember("cpu", str_val(*cpu), allocator);
}
if (const auto &core_count = sys_info.core_count) {
sys_info_json.AddMember("core_count", u32_val(*core_count), allocator);
}
if (const auto &linux_distro = sys_info.linux_distro) {
sys_info_json.AddMember(
"linux_distro", str_val(*linux_distro), allocator);
}
if (const auto &is_virtual = sys_info.is_virtual_machine) {
sys_info_json.AddMember(
"is_virtual", rapidjson::Value{}.SetBool(*is_virtual), allocator);
}

payload
.AddMember(
"authority", app_configuration_.roles().isAuthority(), allocator)
Expand All @@ -270,7 +395,8 @@ namespace kagome::telemetry {
.AddMember("network_id", str_val(host_.getId().toBase58()), allocator)
.AddMember("startup_time", str_val(startup_time), allocator)
.AddMember(
"version", str_val(app_configuration_.nodeVersion()), allocator);
"version", str_val(app_configuration_.nodeVersion()), allocator)
.AddMember("sysinfo", sys_info_json, allocator);

greeting_json_.AddMember("id", 1, allocator)
.AddMember("payload", payload, allocator)
Expand Down

0 comments on commit 0831592

Please sign in to comment.