ml.cc 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "Config.h"
  3. #include "Dimension.h"
  4. #include "Chart.h"
  5. #include "Host.h"
  6. #include <random>
  7. using namespace ml;
  8. bool ml_capable() {
  9. return true;
  10. }
  11. bool ml_enabled(RRDHOST *RH) {
  12. if (!Cfg.EnableAnomalyDetection)
  13. return false;
  14. if (simple_pattern_matches(Cfg.SP_HostsToSkip, rrdhost_hostname(RH)))
  15. return false;
  16. return true;
  17. }
  18. /*
  19. * Assumptions:
  20. * 1) hosts outlive their sets, and sets outlive their dimensions,
  21. * 2) dimensions always have a set that has a host.
  22. */
  23. void ml_init(void) {
  24. // Read config values
  25. Cfg.readMLConfig();
  26. if (!Cfg.EnableAnomalyDetection)
  27. return;
  28. // Generate random numbers to efficiently sample the features we need
  29. // for KMeans clustering.
  30. std::random_device RD;
  31. std::mt19937 Gen(RD());
  32. Cfg.RandomNums.reserve(Cfg.MaxTrainSamples);
  33. for (size_t Idx = 0; Idx != Cfg.MaxTrainSamples; Idx++)
  34. Cfg.RandomNums.push_back(Gen());
  35. }
  36. void ml_host_new(RRDHOST *RH) {
  37. if (!ml_enabled(RH))
  38. return;
  39. Host *H = new Host(RH);
  40. RH->ml_host = reinterpret_cast<ml_host_t *>(H);
  41. }
  42. void ml_host_delete(RRDHOST *RH) {
  43. Host *H = reinterpret_cast<Host *>(RH->ml_host);
  44. if (!H)
  45. return;
  46. delete H;
  47. RH->ml_host = nullptr;
  48. }
  49. void ml_chart_new(RRDSET *RS) {
  50. Host *H = reinterpret_cast<Host *>(RS->rrdhost->ml_host);
  51. if (!H)
  52. return;
  53. Chart *C = new Chart(RS);
  54. RS->ml_chart = reinterpret_cast<ml_chart_t *>(C);
  55. H->addChart(C);
  56. }
  57. void ml_chart_delete(RRDSET *RS) {
  58. Host *H = reinterpret_cast<Host *>(RS->rrdhost->ml_host);
  59. if (!H)
  60. return;
  61. Chart *C = reinterpret_cast<Chart *>(RS->ml_chart);
  62. H->removeChart(C);
  63. delete C;
  64. RS->ml_chart = nullptr;
  65. }
  66. void ml_dimension_new(RRDDIM *RD) {
  67. Chart *C = reinterpret_cast<Chart *>(RD->rrdset->ml_chart);
  68. if (!C)
  69. return;
  70. Dimension *D = new Dimension(RD);
  71. RD->ml_dimension = reinterpret_cast<ml_dimension_t *>(D);
  72. C->addDimension(D);
  73. }
  74. void ml_dimension_delete(RRDDIM *RD) {
  75. Dimension *D = reinterpret_cast<Dimension *>(RD->ml_dimension);
  76. if (!D)
  77. return;
  78. Chart *C = reinterpret_cast<Chart *>(RD->rrdset->ml_chart);
  79. C->removeDimension(D);
  80. delete D;
  81. RD->ml_dimension = nullptr;
  82. }
  83. char *ml_get_host_info(RRDHOST *RH) {
  84. nlohmann::json ConfigJson;
  85. if (RH && RH->ml_host) {
  86. Host *H = reinterpret_cast<Host *>(RH->ml_host);
  87. H->getConfigAsJson(ConfigJson);
  88. } else {
  89. ConfigJson["enabled"] = false;
  90. }
  91. return strdupz(ConfigJson.dump(2, '\t').c_str());
  92. }
  93. char *ml_get_host_runtime_info(RRDHOST *RH) {
  94. nlohmann::json ConfigJson;
  95. if (RH && RH->ml_host) {
  96. Host *H = reinterpret_cast<Host *>(RH->ml_host);
  97. H->getDetectionInfoAsJson(ConfigJson);
  98. } else {
  99. return nullptr;
  100. }
  101. return strdup(ConfigJson.dump(1, '\t').c_str());
  102. }
  103. char *ml_get_host_models(RRDHOST *RH) {
  104. nlohmann::json ModelsJson;
  105. if (RH && RH->ml_host) {
  106. Host *H = reinterpret_cast<Host *>(RH->ml_host);
  107. H->getModelsAsJson(ModelsJson);
  108. return strdup(ModelsJson.dump(2, '\t').c_str());
  109. }
  110. return nullptr;
  111. }
  112. void ml_start_anomaly_detection_threads(RRDHOST *RH) {
  113. if (RH && RH->ml_host) {
  114. Host *H = reinterpret_cast<Host *>(RH->ml_host);
  115. H->startAnomalyDetectionThreads();
  116. }
  117. }
  118. void ml_stop_anomaly_detection_threads(RRDHOST *RH) {
  119. if (RH && RH->ml_host) {
  120. Host *H = reinterpret_cast<Host *>(RH->ml_host);
  121. H->stopAnomalyDetectionThreads(true);
  122. }
  123. }
  124. void ml_cancel_anomaly_detection_threads(RRDHOST *RH) {
  125. if (RH && RH->ml_host) {
  126. Host *H = reinterpret_cast<Host *>(RH->ml_host);
  127. H->stopAnomalyDetectionThreads(false);
  128. }
  129. }
  130. void ml_chart_update_begin(RRDSET *RS) {
  131. Chart *C = reinterpret_cast<Chart *>(RS->ml_chart);
  132. if (!C)
  133. return;
  134. C->updateBegin();
  135. }
  136. void ml_chart_update_end(RRDSET *RS) {
  137. Chart *C = reinterpret_cast<Chart *>(RS->ml_chart);
  138. if (!C)
  139. return;
  140. C->updateEnd();
  141. }
  142. bool ml_is_anomalous(RRDDIM *RD, time_t CurrT, double Value, bool Exists) {
  143. Dimension *D = reinterpret_cast<Dimension *>(RD->ml_dimension);
  144. if (!D)
  145. return false;
  146. Chart *C = reinterpret_cast<Chart *>(RD->rrdset->ml_chart);
  147. bool IsAnomalous = D->predict(CurrT, Value, Exists);
  148. C->updateDimension(D, IsAnomalous);
  149. return IsAnomalous;
  150. }
  151. bool ml_streaming_enabled() {
  152. return Cfg.StreamADCharts;
  153. }
  154. #include "ml-private.h"