1
0

PrometheusCollection.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. using System;
  2. using System.Text.RegularExpressions;
  3. using NLog;
  4. using Prometheus;
  5. namespace OhmGraphite
  6. {
  7. public class PrometheusCollection
  8. {
  9. private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
  10. private static readonly Regex Rx = new Regex("[^a-zA-Z0-9_:]", RegexOptions.Compiled);
  11. private readonly IGiveSensors _collector;
  12. private readonly MetricFactory _metrics;
  13. public PrometheusCollection(IGiveSensors collector, MetricFactory metrics)
  14. {
  15. _collector = collector;
  16. _metrics = metrics;
  17. }
  18. public static CollectorRegistry SetupDefault(IGiveSensors collector)
  19. {
  20. var registry = Metrics.DefaultRegistry;
  21. var metrics = Metrics.WithCustomRegistry(registry);
  22. var prometheusCollection = new PrometheusCollection(collector, metrics);
  23. registry.AddBeforeCollectCallback(() => prometheusCollection.UpdateMetrics());
  24. return registry;
  25. }
  26. public void UpdateMetrics()
  27. {
  28. Logger.LogAction("prometheus update metrics", PollSensors);
  29. }
  30. private static (string, double) BaseReport(ReportedValue report)
  31. {
  32. // Convert reported value into a base value by converting MB and GB into bytes, etc.
  33. // Flow rate is still liters per hour, even though liters per second may seem more
  34. // "base-unity", as grafana contained the former but not the latter. Fan speed remains
  35. // revolutions per minute, as I'm unaware of any manufacturer reporting fan speed as
  36. // revolutions per second.
  37. double BaseValue()
  38. {
  39. double value = report.Value;
  40. switch (report.SensorType)
  41. {
  42. case SensorType.Data: // GB = 2^30 Bytes
  43. return value * (1L << 30);
  44. case SensorType.SmallData: // MB = 2^20 Bytes
  45. return value * (1L << 20);
  46. case SensorType.Clock: // MHz
  47. return value * 1000000;
  48. default:
  49. return value;
  50. }
  51. }
  52. string BaseUnit()
  53. {
  54. switch (report.SensorType)
  55. {
  56. case SensorType.Voltage: // V
  57. return "volts";
  58. case SensorType.Frequency: // Hz
  59. case SensorType.Clock: // MHz
  60. return "hertz";
  61. case SensorType.Temperature: // °C
  62. return "celsius";
  63. case SensorType.Power: // W
  64. return "watts";
  65. case SensorType.Data: // GB = 2^30 Bytes
  66. case SensorType.SmallData: // MB = 2^20 Bytes
  67. return "bytes";
  68. case SensorType.Throughput: // B/s
  69. return "bytes_per_second";
  70. case SensorType.Load: // %
  71. return "load_percent";
  72. case SensorType.Control: // %
  73. return "control_percent";
  74. case SensorType.Level: // %
  75. return "level_percent";
  76. case SensorType.Fan: // RPM
  77. return "revolutions_per_minute";
  78. case SensorType.Flow: // L/h
  79. return "liters_per_hour";
  80. case SensorType.Factor: // 1
  81. default:
  82. return report.SensorType.ToString().ToLowerInvariant();
  83. }
  84. }
  85. return (BaseUnit(), BaseValue());
  86. }
  87. private void PollSensors()
  88. {
  89. foreach (var sensor in _collector.ReadAllSensors())
  90. {
  91. var (unit, value) = BaseReport(sensor);
  92. var hw = Enum.GetName(typeof(HardwareType), sensor.HardwareType)?.ToLowerInvariant();
  93. var name = Rx.Replace($"ohm_{hw}_{unit}", "_");
  94. _metrics.CreateGauge(name, "Metric reported by open hardware sensor", "hardware", "sensor", "hw_instance")
  95. .WithLabels(sensor.Hardware, sensor.Sensor, sensor.HardwareInstance)
  96. .Set(value);
  97. }
  98. }
  99. }
  100. }