Add a chart that groups anomaly rate by chart type. (#15856)
* Add a chart that groups anomaly rate by chart type. * Use type_anomaly_rate for context.
vkalintiris committed
Aug 24, 2023 at 20:48 UTC
0717c779c3c0b21b2d3b6a87de5326affede8f34
4 files changed
+87
-2
collectors/all.h
+2
-1
@@ -403,7 +403,8 @@
403
// [ml] charts
404
#define ML_CHART_PRIO_DIMENSIONS 39181
405
#define ML_CHART_PRIO_ANOMALY_RATE 39182
406
-#define ML_CHART_PRIO_DETECTOR_EVENTS 39183
406
+#define ML_CHART_PRIO_TYPE_ANOMALY_RATE 39183
407
+#define ML_CHART_PRIO_DETECTOR_EVENTS 39184
408
409
// [netdata.ml] charts
410
#define NETDATA_ML_CHART_RUNNING 890001
ml/ad_charts.cc
+51
-1
@@ -222,7 +222,7 @@ void ml_update_dimensions_chart(ml_host_t *host, const ml_machine_learning_stats
222
223
void ml_update_host_and_detection_rate_charts(ml_host_t *host, collected_number AnomalyRate) {
224
/*
225
- * Anomaly rate
225
+ * Host anomaly rate
226
*/
227
{
228
if (!host->anomaly_rate_rs) {
@@ -258,6 +258,56 @@ void ml_update_host_and_detection_rate_charts(ml_host_t *host, collected_number
258
rrdset_done(host->anomaly_rate_rs);
259
}
260
261
+ /*
262
+ * Type anomaly rate
263
+ */
264
+ {
265
+ if (!host->type_anomaly_rate_rs) {
266
+ char id_buf[1024];
267
+ char name_buf[1024];
268
+
269
+ snprintfz(id_buf, 1024, "type_anomaly_rate_on_%s", localhost->machine_guid);
270
+ snprintfz(name_buf, 1024, "type_anomaly_rate_on_%s", rrdhost_hostname(localhost));
271
+
272
+ host->type_anomaly_rate_rs = rrdset_create(
273
+ host->rh,
274
+ "anomaly_detection", // type
275
+ id_buf, // id
276
+ name_buf, // name
277
+ "anomaly_rate", // family
278
+ "anomaly_detection.type_anomaly_rate", // ctx
279
+ "Percentage of anomalous dimensions by type", // title
280
+ "percentage", // units
281
+ NETDATA_ML_PLUGIN, // plugin
282
+ NETDATA_ML_MODULE_DETECTION, // module
283
+ ML_CHART_PRIO_TYPE_ANOMALY_RATE, // priority
284
+ localhost->rrd_update_every, // update_every
285
+ RRDSET_TYPE_LINE // chart_type
286
+ );
287
+
288
+ rrdset_flag_set(host->type_anomaly_rate_rs, RRDSET_FLAG_ANOMALY_DETECTION);
289
+ }
290
+
291
+ for (auto &entry : host->type_anomaly_rate) {
292
+ ml_type_anomaly_rate_t &type_anomaly_rate = entry.second;
293
+
294
+ if (!type_anomaly_rate.rd)
295
+ type_anomaly_rate.rd = rrddim_add(host->type_anomaly_rate_rs, string2str(entry.first), NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE);
296
+
297
+ double ar = 0.0;
298
+ size_t n = type_anomaly_rate.anomalous_dimensions + type_anomaly_rate.normal_dimensions;
299
+ if (n)
300
+ ar = static_cast<double>(type_anomaly_rate.anomalous_dimensions) / n;
301
+
302
+ rrddim_set_by_pointer(host->type_anomaly_rate_rs, type_anomaly_rate.rd, ar * 10000.0);
303
+
304
+ type_anomaly_rate.anomalous_dimensions = 0;
305
+ type_anomaly_rate.normal_dimensions = 0;
306
+ }
307
+
308
+ rrdset_done(host->type_anomaly_rate_rs);
309
+ }
310
+
311
/*
312
* Detector Events
313
*/
ml/ml-private.h
+10
@@ -8,6 +8,7 @@
8
9
#include <vector>
10
#include <queue>
11
+#include <unordered_map>
12
13
typedef double calculated_number_t;
14
typedef dlib::matrix<calculated_number_t, 6, 1> DSample;
@@ -210,6 +211,12 @@ typedef struct {
211
212
void ml_chart_update_dimension(ml_chart_t *chart, ml_dimension_t *dim, bool is_anomalous);
213
214
+typedef struct {
215
+ RRDDIM *rd;
216
+ size_t normal_dimensions;
217
+ size_t anomalous_dimensions;
218
+} ml_type_anomaly_rate_t;
219
+
220
typedef struct {
221
RRDHOST *rh;
222
@@ -255,6 +262,9 @@ typedef struct {
262
RRDSET *detector_events_rs;
263
RRDDIM *detector_events_above_threshold_rd;
264
RRDDIM *detector_events_new_anomaly_event_rd;
265
+
266
+ RRDSET *type_anomaly_rate_rs;
267
+ std::unordered_map<STRING *, ml_type_anomaly_rate_t> type_anomaly_rate;
268
} ml_host_t;
269
270
typedef struct {
ml/ml.cc
+24
@@ -1082,6 +1082,21 @@ ml_host_detect_once(ml_host_t *host)
1082
1083
host->mls.num_anomalous_dimensions += chart_mls.num_anomalous_dimensions;
1084
host->mls.num_normal_dimensions += chart_mls.num_normal_dimensions;
1085
+
1086
+ STRING *key = rs->parts.type;
1087
+ auto &um = host->type_anomaly_rate;
1088
+ auto it = um.find(key);
1089
+ if (it == um.end()) {
1090
+ um[key] = ml_type_anomaly_rate_t {
1091
+ .rd = NULL,
1092
+ .normal_dimensions = 0,
1093
+ .anomalous_dimensions = 0
1094
+ };
1095
+ it = um.find(key);
1096
+ }
1097
+
1098
+ it->second.anomalous_dimensions += chart_mls.num_anomalous_dimensions;
1099
+ it->second.normal_dimensions += chart_mls.num_normal_dimensions;
1100
}
1101
rrdset_foreach_done(rsp);
1102
@@ -1095,6 +1110,15 @@ ml_host_detect_once(ml_host_t *host)
1110
netdata_mutex_unlock(&host->mutex);
1111
} else {
1112
host->host_anomaly_rate = 0.0;
1113
+
1114
+ auto &um = host->type_anomaly_rate;
1115
+ for (auto &entry: um) {
1116
+ entry.second = ml_type_anomaly_rate_t {
1117
+ .rd = NULL,
1118
+ .normal_dimensions = 0,
1119
+ .anomalous_dimensions = 0
1120
+ };
1121
+ }
1122
}
1123
1124
worker_is_busy(WORKER_JOB_DETECTION_DIM_CHART);