Explorar o código

Merge pull request #134 from nickbabcock/nvme-health

Add NVMe SMART Sensors
Nick Babcock %!s(int64=5) %!d(string=hai) anos
pai
achega
1ca03f2466
Modificáronse 3 ficheiros con 135 adicións e 0 borrados
  1. 66 0
      OhmGraphite/OhmNvme.cs
  2. 42 0
      OhmGraphite/OhmSensor.cs
  3. 27 0
      OhmGraphite/SensorCollector.cs

+ 66 - 0
OhmGraphite/OhmNvme.cs

@@ -0,0 +1,66 @@
+using LibreHardwareMonitor.Hardware;
+using LibreHardwareMonitor.Hardware.Storage;
+
+namespace OhmGraphite
+{
+    // LibreHardwareMonitor doesn't expose all the SMART attributes on a generic NVMe drive
+    // so we create our own pseudo-hardware class that exposes some important factors
+    internal class OhmNvme
+    {
+        private readonly NVMeGeneric _nvme;
+
+        public OhmNvme(NVMeGeneric nvme)
+        {
+            _nvme = nvme;
+            var factor = LibreHardwareMonitor.Hardware.SensorType.Factor.ToString().ToLowerInvariant();
+            ErrorInfoLogEntryCount = new OhmSensor
+            {
+                Identifier = new Identifier(nvme.Identifier, factor, "error_info_log_entries"),
+                Name = "Error Info Log Entries",
+                Hardware = nvme,
+                SensorType = LibreHardwareMonitor.Hardware.SensorType.Factor,
+            };
+
+            MediaErrors = new OhmSensor
+            {
+                Identifier = new Identifier(nvme.Identifier, factor, "media_errors"),
+                Name = "Media Errors",
+                Hardware = nvme,
+                SensorType = LibreHardwareMonitor.Hardware.SensorType.Factor,
+            };
+
+            PowerCycles = new OhmSensor
+            {
+                Identifier = new Identifier(nvme.Identifier, factor, "power_cycles"),
+                Name = "Power Cycles",
+                Hardware = nvme,
+                SensorType = LibreHardwareMonitor.Hardware.SensorType.Factor,
+            };
+
+            UnsafeShutdowns = new OhmSensor
+            {
+                Identifier = new Identifier(nvme.Identifier, factor, "unsafe_shutdowns"),
+                Name = "Unsafe Shutdowns",
+                Hardware = nvme,
+                SensorType = LibreHardwareMonitor.Hardware.SensorType.Factor,
+            };
+        }
+
+        public OhmSensor UnsafeShutdowns { get; }
+
+        public OhmSensor PowerCycles { get; }
+
+        public OhmSensor MediaErrors { get; }
+
+        public OhmSensor ErrorInfoLogEntryCount { get; }
+
+        public void Update()
+        {
+            var health = _nvme.Smart.GetHealthInfo();
+            ErrorInfoLogEntryCount.Value = health.ErrorInfoLogEntryCount;
+            MediaErrors.Value = health.MediaErrors;
+            PowerCycles.Value = health.PowerCycle;
+            UnsafeShutdowns.Value = health.UnsafeShutdowns;
+        }
+    }
+}

+ 42 - 0
OhmGraphite/OhmSensor.cs

@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using LibreHardwareMonitor.Hardware;
+
+namespace OhmGraphite
+{
+    class OhmSensor : ISensor
+    {
+        public void Accept(IVisitor visitor)
+        {
+        }
+
+        public void Traverse(IVisitor visitor)
+        {
+        }
+
+        public IControl Control => null;
+        public IHardware Hardware { get; set; }
+        public Identifier Identifier { get; set; }
+        public int Index => 0;
+        public bool IsDefaultHidden => false;
+        public float? Max => null;
+        public float? Min => null;
+        public string Name { get; set; }
+        public IReadOnlyList<IParameter> Parameters => new List<IParameter>();
+        public LibreHardwareMonitor.Hardware.SensorType SensorType { get; set; }
+        public float? Value { get; set; }
+        public IEnumerable<SensorValue> Values => new List<SensorValue>();
+        public TimeSpan ValuesTimeWindow { get; set; }
+
+        public void ResetMin()
+        {
+        }
+
+        public void ResetMax()
+        {
+        }
+    }
+}

+ 27 - 0
OhmGraphite/SensorCollector.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using NLog;
 using LibreHardwareMonitor.Hardware;
+using LibreHardwareMonitor.Hardware.Storage;
 
 namespace OhmGraphite
 {
@@ -16,6 +17,9 @@ namespace OhmGraphite
         private readonly ConcurrentDictionary<Identifier, object> _ids =
             new ConcurrentDictionary<Identifier, object>();
 
+        private readonly ConcurrentDictionary<Identifier, OhmNvme> _nvmes =
+            new ConcurrentDictionary<Identifier, OhmNvme>();
+
         public SensorCollector(Computer computer, MetricConfig config)
         {
             _computer = computer;
@@ -64,6 +68,16 @@ namespace OhmGraphite
                 SensorAdded(sensor);
             }
 
+            if (hardware is NVMeGeneric nvme)
+            {
+                var ohmNvme = new OhmNvme(nvme);
+                _nvmes.TryAdd(hardware.Identifier, ohmNvme);
+                SensorAdded(ohmNvme.MediaErrors);
+                SensorAdded(ohmNvme.PowerCycles);
+                SensorAdded(ohmNvme.ErrorInfoLogEntryCount);
+                SensorAdded(ohmNvme.UnsafeShutdowns);
+            }
+
             foreach (var sub in hardware.SubHardware)
             {
                 HardwareAdded(sub);
@@ -81,6 +95,14 @@ namespace OhmGraphite
                 SensorRemoved(sensor);
             }
 
+            if (_nvmes.TryRemove(hardware.Identifier, out OhmNvme ohmNvme))
+            {
+                SensorRemoved(ohmNvme.MediaErrors);
+                SensorRemoved(ohmNvme.PowerCycles);
+                SensorRemoved(ohmNvme.ErrorInfoLogEntryCount);
+                SensorRemoved(ohmNvme.UnsafeShutdowns);
+            }
+
             foreach (var sub in hardware.SubHardware)
             {
                 HardwareRemoved(sub);
@@ -103,6 +125,11 @@ namespace OhmGraphite
         public IEnumerable<ReportedValue> ReadAllSensors()
         {
             _computer.Accept(_updateVisitor);
+            foreach (var nvme in _nvmes.Values)
+            {
+                nvme.Update();
+            }
+
             return _ids.Values.OfType<ISensor>().SelectMany(ReportedValues);
         }