aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/system.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2026-04-13 12:09:05 +0200
committerGitHub Enterprise <[email protected]>2026-04-13 12:09:05 +0200
commite0879bed083eab09cfa28043a3b210714d0884b9 (patch)
tree00d5dddc9a046bd0112e1fddcfce430ced14a355 /src/zencore/system.cpp
parentupdate minio (#947) (diff)
downloadzen-e0879bed083eab09cfa28043a3b210714d0884b9.tar.xz
zen-e0879bed083eab09cfa28043a3b210714d0884b9.zip
Logging and diagnostics improvements (#941)
Core logging and system diagnostics improvements, extracted from the compute branch. ### Logging - **Elapsed timestamps**: Console log now shows elapsed time since launch `[HH:MM:SS.mmm]` instead of full date/time; file logging is unchanged - **Short level names**: 3-letter short level names (`trc`/`dbg`/`inf`/`wrn`/`err`/`crt`) used by both console and file formatters via `ShortToStringView()` - **Consistent field order**: Standardized to `[timestamp] [level] [logger]` across both console and file formatters - **Slim LogMessage/LogPoint**: Remove redundant fields from `LogMessage` (derive level/source from `LogPoint`), flatten `LogPoint` to inline filename/line fields, shrink `LogLevel` to `int8_t` with `static_assert(sizeof(LogPoint) <= 32)` - **Remove default member initializers** and static default `LogPoint` from `LogMessage` — all fields initialized by constructor - **LoggerRef string constructor**: Convenience constructor accepting a string directly - **Fix SendMessage macro collision**: Replace `thread.h` include in `logmsg.h` with a forward declaration of `GetCurrentThreadId()` to avoid pulling in `windows.h` transitively ### System Diagnostics - **Cache static system metrics**: Add `RefreshDynamicSystemMetrics()` that only queries values that change at runtime (available memory, uptime, swap). `SystemMetricsTracker` snapshots full `GetSystemMetrics()` once at construction and reuses cached topology/total memory on each `Query()`, avoiding repeated `GetLogicalProcessorInformationEx` traversal on Windows, `/proc/cpuinfo` parsing on Linux, and `sysctl` topology calls on macOS
Diffstat (limited to 'src/zencore/system.cpp')
-rw-r--r--src/zencore/system.cpp97
1 files changed, 95 insertions, 2 deletions
diff --git a/src/zencore/system.cpp b/src/zencore/system.cpp
index 6909e1a9b..486050d83 100644
--- a/src/zencore/system.cpp
+++ b/src/zencore/system.cpp
@@ -148,6 +148,18 @@ GetSystemMetrics()
return Metrics;
}
+void
+RefreshDynamicSystemMetrics(SystemMetrics& Metrics)
+{
+ MEMORYSTATUSEX MemStatus{.dwLength = sizeof(MEMORYSTATUSEX)};
+ GlobalMemoryStatusEx(&MemStatus);
+
+ Metrics.AvailSystemMemoryMiB = MemStatus.ullAvailPhys / 1024 / 1024;
+ Metrics.AvailVirtualMemoryMiB = MemStatus.ullAvailVirtual / 1024 / 1024;
+ Metrics.AvailPageFileMiB = MemStatus.ullAvailPageFile / 1024 / 1024;
+ Metrics.UptimeSeconds = GetTickCount64() / 1000;
+}
+
std::vector<std::string>
GetLocalIpAddresses()
{
@@ -324,6 +336,51 @@ GetSystemMetrics()
return Metrics;
}
+
+void
+RefreshDynamicSystemMetrics(SystemMetrics& Metrics)
+{
+ long PageSize = sysconf(_SC_PAGE_SIZE);
+ long AvailPages = sysconf(_SC_AVPHYS_PAGES);
+
+ if (AvailPages > 0 && PageSize > 0)
+ {
+ Metrics.AvailSystemMemoryMiB = (AvailPages * PageSize) / 1024 / 1024;
+ Metrics.AvailVirtualMemoryMiB = Metrics.AvailSystemMemoryMiB;
+ }
+
+ if (FILE* UptimeFile = fopen("/proc/uptime", "r"))
+ {
+ double UptimeSec = 0;
+ if (fscanf(UptimeFile, "%lf", &UptimeSec) == 1)
+ {
+ Metrics.UptimeSeconds = static_cast<uint64_t>(UptimeSec);
+ }
+ fclose(UptimeFile);
+ }
+
+ if (FILE* MemInfo = fopen("/proc/meminfo", "r"))
+ {
+ char Line[256];
+ long SwapFree = 0;
+
+ while (fgets(Line, sizeof(Line), MemInfo))
+ {
+ if (strncmp(Line, "SwapFree:", 9) == 0)
+ {
+ sscanf(Line, "SwapFree: %ld kB", &SwapFree);
+ break;
+ }
+ }
+ fclose(MemInfo);
+
+ if (SwapFree > 0)
+ {
+ Metrics.AvailPageFileMiB = SwapFree / 1024;
+ }
+ }
+}
+
#elif ZEN_PLATFORM_MAC
std::string
GetMachineName()
@@ -398,6 +455,36 @@ GetSystemMetrics()
return Metrics;
}
+
+void
+RefreshDynamicSystemMetrics(SystemMetrics& Metrics)
+{
+ vm_size_t PageSize = 0;
+ host_page_size(mach_host_self(), &PageSize);
+
+ vm_statistics64_data_t VmStats;
+ mach_msg_type_number_t InfoCount = sizeof(VmStats) / sizeof(natural_t);
+ host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t)&VmStats, &InfoCount);
+
+ uint64_t FreeMemory = (uint64_t)(VmStats.free_count + VmStats.inactive_count) * PageSize;
+ Metrics.AvailSystemMemoryMiB = FreeMemory / 1024 / 1024;
+ Metrics.AvailVirtualMemoryMiB = Metrics.VirtualMemoryMiB;
+
+ xsw_usage SwapUsage;
+ size_t Size = sizeof(SwapUsage);
+ sysctlbyname("vm.swapusage", &SwapUsage, &Size, nullptr, 0);
+ Metrics.AvailPageFileMiB = (SwapUsage.xsu_total - SwapUsage.xsu_used) / 1024 / 1024;
+
+ struct timeval BootTime
+ {
+ };
+ Size = sizeof(BootTime);
+ if (sysctlbyname("kern.boottime", &BootTime, &Size, nullptr, 0) == 0)
+ {
+ Metrics.UptimeSeconds = static_cast<uint64_t>(time(nullptr) - BootTime.tv_sec);
+ }
+}
+
#else
# error "Unknown platform"
#endif
@@ -655,11 +742,16 @@ struct SystemMetricsTracker::Impl
std::mutex Mutex;
CpuSampler Sampler;
+ SystemMetrics CachedMetrics;
float CachedCpuPercent = 0.0f;
Clock::time_point NextSampleTime = Clock::now();
std::chrono::milliseconds MinInterval;
- explicit Impl(std::chrono::milliseconds InMinInterval) : MinInterval(InMinInterval) {}
+ explicit Impl(std::chrono::milliseconds InMinInterval) : MinInterval(InMinInterval)
+ {
+ // Capture topology and total memory once; these don't change at runtime
+ CachedMetrics = GetSystemMetrics();
+ }
float SampleCpu()
{
@@ -683,7 +775,8 @@ ExtendedSystemMetrics
SystemMetricsTracker::Query()
{
ExtendedSystemMetrics Metrics;
- static_cast<SystemMetrics&>(Metrics) = GetSystemMetrics();
+ static_cast<SystemMetrics&>(Metrics) = m_Impl->CachedMetrics;
+ RefreshDynamicSystemMetrics(Metrics);
std::lock_guard Lock(m_Impl->Mutex);
Metrics.CpuUsagePercent = m_Impl->SampleCpu();