aboutsummaryrefslogtreecommitdiff
path: root/src/zenutil/include
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2026-03-23 19:22:08 +0100
committerGitHub Enterprise <[email protected]>2026-03-23 19:22:08 +0100
commit440ef03df8d8bba4432126f36168c1f7631c18dc (patch)
tree07d4bd4446a11589c9a842255bf37c25aaded74b /src/zenutil/include
parentMerge branch 'de/v5.7.25-hotpatch' (#880) (diff)
downloadzen-440ef03df8d8bba4432126f36168c1f7631c18dc.tar.xz
zen-440ef03df8d8bba4432126f36168c1f7631c18dc.zip
Cross-platform process metrics support (#887)
- **Cross-platform `GetProcessMetrics`**: Implement Linux (`/proc/{pid}/stat`, `/proc/{pid}/statm`, `/proc/{pid}/status`) and macOS (`proc_pidinfo(PROC_PIDTASKINFO)`) support for CPU times and memory metrics. Fix Windows to populate the `MemoryBytes` field (was always 0). All platforms now set `MemoryBytes = WorkingSetSize`. - **`ProcessMetricsTracker`**: Experimental utility class (`zenutil`) that periodically samples resource usage for a set of tracked child processes. Supports both a dedicated background thread and an ASIO steady_timer mode. Computes delta-based CPU usage percentage across samples, with batched sampling (8 processes per tick) to limit per-cycle overhead. - **`ProcessHandle` documentation**: Add Doxygen comments to all public methods describing platform-specific behavior. - **Cleanup**: Remove unused `ZEN_RUN_TESTS` macro (inlined at its single call site in `zenserver/main.cpp`), remove dead `#if 0` thread-shutdown workaround block. - **Minor fixes**: Use `HttpClientAccessToken` constructor in hordeclient instead of setting private members directly. Log ASIO version at startup and include it in the server settings list.
Diffstat (limited to 'src/zenutil/include')
-rw-r--r--src/zenutil/include/zenutil/processmetricstracker.h105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/zenutil/include/zenutil/processmetricstracker.h b/src/zenutil/include/zenutil/processmetricstracker.h
new file mode 100644
index 000000000..fdeae2bfa
--- /dev/null
+++ b/src/zenutil/include/zenutil/processmetricstracker.h
@@ -0,0 +1,105 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+#include <zencore/process.h>
+#include <zencore/zencore.h>
+
+#include <memory>
+#include <vector>
+
+namespace asio {
+class io_context;
+}
+
+namespace zen {
+
+/** Tracked process entry with latest metrics snapshot.
+ */
+struct TrackedProcessEntry
+{
+ int Pid = 0;
+ ProcessMetrics Metrics;
+
+ // Derived CPU usage percentage (delta-based, requires two samples).
+ // -1.0 means not yet sampled.
+ float CpuUsagePercent = -1.0f;
+};
+
+/** Aggregate metrics across all tracked processes.
+ */
+struct AggregateProcessMetrics
+{
+ uint64_t TotalWorkingSetSize = 0;
+ uint64_t TotalPeakWorkingSetSize = 0;
+ uint64_t TotalUserTimeMs = 0;
+ uint64_t TotalKernelTimeMs = 0;
+ uint32_t ProcessCount = 0;
+};
+
+/** Background process metrics tracker.
+ *
+ * Maintains a set of child processes keyed by pid and periodically samples
+ * their resource usage (CPU times, memory) in a background thread or via
+ * an ASIO timer on an external io_context.
+ *
+ * The tracker does not take ownership of process handles. On Windows it
+ * duplicates the handle internally; on other platforms it uses the pid
+ * directly.
+ *
+ * Usage (dedicated thread):
+ * ProcessMetricsTracker Tracker;
+ * Tracker.Start();
+ * Tracker.Add(ChildHandle);
+ *
+ * Usage (ASIO timer):
+ * ProcessMetricsTracker Tracker(IoContext);
+ * Tracker.Start();
+ * Tracker.Add(ChildHandle);
+ */
+class ProcessMetricsTracker
+{
+public:
+ /// Construct with a dedicated background thread for sampling.
+ explicit ProcessMetricsTracker(uint64_t SampleIntervalMs = 5000);
+
+ /// Construct with an external io_context — uses an asio::steady_timer
+ /// instead of a dedicated thread. The caller must ensure the io_context
+ /// outlives this tracker and that its run loop is active.
+ ProcessMetricsTracker(asio::io_context& IoContext, uint64_t SampleIntervalMs = 5000);
+
+ ~ProcessMetricsTracker();
+
+ ProcessMetricsTracker(const ProcessMetricsTracker&) = delete;
+ ProcessMetricsTracker& operator=(const ProcessMetricsTracker&) = delete;
+
+ /// Start sampling. Spawns the background thread or enqueues the first timer.
+ void Start();
+
+ /// Stop sampling. Safe to call multiple times.
+ void Stop();
+
+ /// Add a process to track. Internally clones the handle (Windows) or
+ /// copies the pid (Linux/macOS). If the pid is already tracked, replaces it.
+ void Add(const ProcessHandle& Handle);
+
+ /// Remove a tracked process by pid.
+ void Remove(int Pid);
+
+ /// Remove all tracked processes.
+ void Clear();
+
+ /// Returns a snapshot of metrics for all tracked processes.
+ std::vector<TrackedProcessEntry> GetSnapshot() const;
+
+ /// Returns aggregate metrics across all tracked processes.
+ AggregateProcessMetrics GetAggregate() const;
+
+private:
+ struct Impl;
+ std::unique_ptr<Impl> m_Impl;
+};
+
+void processmetricstracker_forcelink(); // internal
+
+} // namespace zen