From 4ca0852455b3bb8ec860bce86c69f64c61c16357 Mon Sep 17 00:00:00 2001
From: Niko Ehrenfeuchter <nikolaus.ehrenfeuchter@unibas.ch>
Date: Sun, 11 Mar 2018 16:49:40 +0100
Subject: [PATCH] Add class for CPU load monitoring.

Placed in namespace ATxCommon.Monitoring, using its own timer to update
the values.
---
 ATxCommon/ATxCommon.csproj  |  1 +
 ATxCommon/Monitoring/Cpu.cs | 55 +++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)
 create mode 100644 ATxCommon/Monitoring/Cpu.cs

diff --git a/ATxCommon/ATxCommon.csproj b/ATxCommon/ATxCommon.csproj
index 96b7ac8..d281301 100644
--- a/ATxCommon/ATxCommon.csproj
+++ b/ATxCommon/ATxCommon.csproj
@@ -47,6 +47,7 @@
     <Compile Include="BuildDetails.cs" />
     <Compile Include="Conv.cs" />
     <Compile Include="FsUtils.cs" />
+    <Compile Include="Monitoring\Cpu.cs" />
     <Compile Include="NLog\RateLimitWrapper.cs" />
     <Compile Include="Serializables\DriveToCheck.cs" />
     <Compile Include="Serializables\ServiceConfig.cs" />
diff --git a/ATxCommon/Monitoring/Cpu.cs b/ATxCommon/Monitoring/Cpu.cs
new file mode 100644
index 0000000..c0272ee
--- /dev/null
+++ b/ATxCommon/Monitoring/Cpu.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Timers;
+using NLog;
+
+namespace ATxCommon.Monitoring
+{
+    public class Cpu
+    {
+        private static readonly Logger Log = LogManager.GetCurrentClassLogger();
+
+        private readonly Timer _monitoringTimer;
+        private readonly PerformanceCounter _cpuCounter;
+        private readonly float[] _loadReadings = {0F, 0F, 0F, 0F};
+        private float _load;
+
+        public float Load() => _load;
+
+        public Cpu() {
+            Log.Debug("Initializing CPU monitoring...");
+            try {
+                _cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
+                _monitoringTimer = new Timer(250);
+                _monitoringTimer.Elapsed += UpdateCpuLoad;
+                _monitoringTimer.Enabled = true;
+            }
+            catch (Exception ex) {
+                Log.Error("Initializing CPU monitoring completed ({1}): {0}", ex.Message, ex.GetType());
+                throw;
+            }
+
+            Log.Debug("Initializing CPU monitoring completed.");
+        }
+
+        private void UpdateCpuLoad(object sender, ElapsedEventArgs e) {
+            _monitoringTimer.Enabled = false;
+            try {
+                Log.Trace("load values: {0}, average: {1}", string.Join(", ", _loadReadings), _load);
+                // ConstrainedCopy seems to be the most efficient approach to shift the array:
+                Array.ConstrainedCopy(_loadReadings, 1, _loadReadings, 0, 3);
+                _loadReadings[3] = _cpuCounter.NextValue();
+                _load = _loadReadings.Average();
+                Log.Trace("load values: {0}, average: {1}", string.Join(", ", _loadReadings), _load);
+            }
+            catch (Exception ex) {
+                Log.Error("UpdateCpuLoad failed: {0}", ex.Message);
+            }
+            finally {
+                _monitoringTimer.Enabled = true;
+            }
+        }
+
+    }
+}
-- 
GitLab