logs enhancements (#20027)
* allow filtering on fields, without making them facets * show all values on histogram * histogram now has both ids and names for dimensions * added colors for PRIORITY on linux and LEVEL on windows * Revert "added colors for PRIORITY on linux and LEVEL on windows" This reverts commit f93ce7265d68889e3c25c66177c442eea45553fd.
Costa Tsaousis committed
Apr 1, 2025 at 22:42 UTC
60c00474b1b0b3675fa8326cdce96e8b551c428d
3 files changed
+72
-49
src/libnetdata/facets/facets.c
+69
-47
@@ -1067,7 +1067,7 @@ static inline void facets_key_value_transformed(FACETS *facets, FACET_KEY *k, FA
1067
buffer_strcat(dst, facets_key_value_cached(k, v, facets->report.used_hashes_registry));
1068
}
1069
1070
-static inline void facets_histogram_value_names(BUFFER *wb, FACETS *facets __maybe_unused, FACET_KEY *k, const char *key, const char *first_key) {
1070
+static inline void facets_histogram_value_ids(BUFFER *wb, FACETS *facets __maybe_unused, FACET_KEY *k, const char *key, const char *first_key) {
1071
CLEAN_BUFFER *tb = buffer_create(0, NULL);
1072
1073
buffer_json_member_add_array(wb, key);
@@ -1078,9 +1078,25 @@ static inline void facets_histogram_value_names(BUFFER *wb, FACETS *facets __may
1078
if(k && k->values.enabled) {
1079
FACET_VALUE *v;
1080
foreach_value_in_key(k, v) {
1081
- if (unlikely(!v->histogram))
1082
- continue;
1081
+ buffer_json_add_array_item_string(wb, facets_key_value_id(k ,v));
1082
+ }
1083
+ foreach_value_in_key_done(v);
1084
+ }
1085
+ }
1086
+ buffer_json_array_close(wb); // key
1087
+}
1088
+
1089
+static inline void facets_histogram_value_names(BUFFER *wb, FACETS *facets __maybe_unused, FACET_KEY *k, const char *key, const char *first_key) {
1090
+ CLEAN_BUFFER *tb = buffer_create(0, NULL);
1091
1092
+ buffer_json_member_add_array(wb, key);
1093
+ {
1094
+ if(first_key)
1095
+ buffer_json_add_array_item_string(wb, first_key);
1096
+
1097
+ if(k && k->values.enabled) {
1098
+ FACET_VALUE *v;
1099
+ foreach_value_in_key(k, v) {
1100
facets_key_value_transformed(facets, k, v, tb, FACETS_TRANSFORM_HISTOGRAM);
1101
buffer_json_add_array_item_string(wb, buffer_tostring(tb));
1102
}
@@ -1096,9 +1112,6 @@ static inline void facets_histogram_value_colors(BUFFER *wb, FACETS *facets __ma
1112
if(k && k->values.enabled) {
1113
FACET_VALUE *v;
1114
foreach_value_in_key(k, v) {
1099
- if (unlikely(!v->histogram))
1100
- continue;
1101
-
1115
buffer_json_add_array_item_string(wb, v->color);
1116
}
1117
foreach_value_in_key_done(v);
@@ -1113,9 +1126,6 @@ static inline void facets_histogram_value_units(BUFFER *wb, FACETS *facets __may
1126
if(k && k->values.enabled) {
1127
FACET_VALUE *v;
1128
foreach_value_in_key(k, v) {
1116
- if (unlikely(!v->histogram))
1117
- continue;
1118
-
1129
buffer_json_add_array_item_string(wb, "events");
1130
}
1131
foreach_value_in_key_done(v);
@@ -1130,9 +1140,6 @@ static inline void facets_histogram_value_min(BUFFER *wb, FACETS *facets __maybe
1140
if(k && k->values.enabled) {
1141
FACET_VALUE *v;
1142
foreach_value_in_key(k, v) {
1133
- if (unlikely(!v->histogram))
1134
- continue;
1135
-
1143
buffer_json_add_array_item_uint64(wb, v->min);
1144
}
1145
foreach_value_in_key_done(v);
@@ -1147,9 +1154,6 @@ static inline void facets_histogram_value_max(BUFFER *wb, FACETS *facets __maybe
1154
if(k && k->values.enabled) {
1155
FACET_VALUE *v;
1156
foreach_value_in_key(k, v) {
1150
- if (unlikely(!v->histogram))
1151
- continue;
1152
-
1157
buffer_json_add_array_item_uint64(wb, v->max);
1158
}
1159
foreach_value_in_key_done(v);
@@ -1164,9 +1168,6 @@ static inline void facets_histogram_value_avg(BUFFER *wb, FACETS *facets __maybe
1168
if(k && k->values.enabled) {
1169
FACET_VALUE *v;
1170
foreach_value_in_key(k, v) {
1167
- if (unlikely(!v->histogram))
1168
- continue;
1169
-
1171
buffer_json_add_array_item_double(wb, (double) v->sum / (double) facets->histogram.slots);
1172
}
1173
foreach_value_in_key_done(v);
@@ -1181,9 +1182,6 @@ static inline void facets_histogram_value_arp(BUFFER *wb, FACETS *facets __maybe
1182
if(k && k->values.enabled) {
1183
FACET_VALUE *v;
1184
foreach_value_in_key(k, v) {
1184
- if (unlikely(!v->histogram))
1185
- continue;
1186
-
1185
buffer_json_add_array_item_uint64(wb, 0);
1186
}
1187
foreach_value_in_key_done(v);
@@ -1198,10 +1196,10 @@ static inline void facets_histogram_value_con(BUFFER *wb, FACETS *facets __maybe
1196
if(k && k->values.enabled) {
1197
FACET_VALUE *v;
1198
foreach_value_in_key(k, v) {
1201
- if (unlikely(!v->histogram))
1202
- continue;
1203
-
1204
- buffer_json_add_array_item_double(wb, (double) v->sum * 100.0 / (double) sum);
1199
+ if(sum)
1200
+ buffer_json_add_array_item_double(wb, (double) v->sum * 100.0 / (double) sum);
1201
+ else
1202
+ buffer_json_add_array_item_double(wb, 0.0);
1203
}
1204
foreach_value_in_key_done(v);
1205
}
@@ -1218,8 +1216,10 @@ static void facets_histogram_generate(FACETS *facets, FACET_KEY *k, BUFFER *wb)
1216
if(k && k->values.enabled) {
1217
FACET_VALUE *v;
1218
foreach_value_in_key(k, v) {
1221
- if (unlikely(!v->histogram))
1219
+ if (unlikely(!v->histogram)) {
1220
+ v->min = v->max = v->sum = 0;
1221
continue;
1222
+ }
1223
1224
dimensions++;
1225
@@ -1377,25 +1377,41 @@ static void facets_histogram_generate(FACETS *facets, FACET_KEY *k, BUFFER *wb)
1377
FACET_VALUE *v;
1378
1379
foreach_value_in_key(k, v) {
1380
- if(unlikely(!v->histogram))
1381
- continue;
1380
+ uint64_t d_sl, d_qr;
1381
+ uint64_t d_min, d_max;
1382
+ double d_avg, d_con;
1383
+
1384
+ if(likely(v->histogram)) {
1385
+ d_sl = d_qr = 1;
1386
+ d_min = v->min;
1387
+ d_max = v->max;
1388
+ d_avg = (double) v->sum / (double) facets->histogram.slots;
1389
+ d_con = (double) v->sum * 100.0 / (double) sum;
1390
+ }
1391
+ else {
1392
+ d_sl = d_qr = 0;
1393
+ d_min = d_max = 0;
1394
+ d_avg = d_con = 0.0;
1395
+ }
1396
1397
buffer_json_add_array_item_object(wb); // dimension
1398
{
1399
+ buffer_json_member_add_string(wb, "id", facets_key_value_id(k, v));
1400
+
1401
facets_key_value_transformed(facets, k, v, tmp, FACETS_TRANSFORM_HISTOGRAM);
1386
- buffer_json_member_add_string(wb, "id", buffer_tostring(tmp));
1402
+ buffer_json_member_add_string(wb, "nm", buffer_tostring(tmp));
1403
buffer_json_member_add_object(wb, "ds");
1404
{
1389
- buffer_json_member_add_uint64(wb, "sl", 1);
1390
- buffer_json_member_add_uint64(wb, "qr", 1);
1405
+ buffer_json_member_add_uint64(wb, "sl", d_sl);
1406
+ buffer_json_member_add_uint64(wb, "qr", d_qr);
1407
}
1408
buffer_json_object_close(wb); // ds
1409
buffer_json_member_add_object(wb, "sts");
1410
{
1395
- buffer_json_member_add_uint64(wb, "min", v->min);
1396
- buffer_json_member_add_uint64(wb, "max", v->max);
1397
- buffer_json_member_add_double(wb, "avg", (double)v->sum / (double)facets->histogram.slots);
1398
- buffer_json_member_add_double(wb, "con", (double)v->sum * 100.0 / (double)sum);
1411
+ buffer_json_member_add_uint64(wb, "min", d_min);
1412
+ buffer_json_member_add_uint64(wb, "max", d_max);
1413
+ buffer_json_member_add_double(wb, "avg", d_avg);
1414
+ buffer_json_member_add_double(wb, "con", d_con);
1415
}
1416
buffer_json_object_close(wb); // sts
1417
buffer_json_member_add_uint64(wb, "pri", pri++);
@@ -1469,12 +1485,13 @@ static void facets_histogram_generate(FACETS *facets, FACET_KEY *k, BUFFER *wb)
1485
1486
FACET_VALUE *v;
1487
foreach_value_in_key(k, v) {
1472
- if (unlikely(!v->histogram))
1473
- continue;
1474
-
1488
buffer_json_add_array_item_array(wb); // point
1489
1477
- buffer_json_add_array_item_uint64(wb, v->histogram[i]);
1490
+ if(v->histogram)
1491
+ buffer_json_add_array_item_uint64(wb, v->histogram[i]);
1492
+ else
1493
+ buffer_json_add_array_item_double(wb, NAN);
1494
+
1495
buffer_json_add_array_item_uint64(wb, 0); // arp - anomaly rate
1496
buffer_json_add_array_item_uint64(wb, 0); // pa - point annotation
1497
@@ -1501,7 +1518,8 @@ static void facets_histogram_generate(FACETS *facets, FACET_KEY *k, BUFFER *wb)
1518
buffer_json_member_add_string(wb, "units", "events");
1519
buffer_json_member_add_object(wb, "dimensions");
1520
{
1504
- facets_histogram_value_names(wb, facets, k, "ids", NULL);
1521
+ facets_histogram_value_ids(wb, facets, k, "ids", NULL);
1522
+ facets_histogram_value_names(wb, facets, k, "names", NULL);
1523
facets_histogram_value_units(wb, facets, k, "units");
1524
1525
buffer_json_member_add_object(wb, "sts");
@@ -1555,7 +1573,7 @@ static void facets_histogram_generate(FACETS *facets, FACET_KEY *k, BUFFER *wb)
1573
}
1574
buffer_json_array_close(wb); // grouped_by
1575
1558
- facets_histogram_value_names(wb, facets, k, "ids", NULL);
1576
+ facets_histogram_value_ids(wb, facets, k, "ids", NULL);
1577
facets_histogram_value_names(wb, facets, k, "names", NULL);
1578
facets_histogram_value_colors(wb, facets, k, "colors");
1579
facets_histogram_value_units(wb, facets, k, "units");
@@ -1840,17 +1858,21 @@ inline FACET_KEY *facets_register_facet_id(FACETS *facets, const char *key_id, F
1858
1859
void facets_register_facet_filter_id(FACETS *facets, const char *key_id, const char *value_id, FACET_KEY_OPTIONS options) {
1860
FACET_KEY *k = facets_register_facet_id(facets, key_id, options);
1843
- if(k) {
1844
- if(is_valid_string_hash(value_id)) {
1845
- k->default_selected_for_values = false;
1846
- FACET_VALUE_ADD_OR_UPDATE_SELECTED(k, NULL, str_to_facets_hash(value_id));
1847
- }
1861
+ if(k && is_valid_string_hash(value_id)) {
1862
+ if(!(k->options & FACET_KEY_OPTION_FACET))
1863
+ k->options |= FACET_KEY_OPTION_FILTER_ONLY;
1864
+
1865
+ k->default_selected_for_values = false;
1866
+ FACET_VALUE_ADD_OR_UPDATE_SELECTED(k, NULL, str_to_facets_hash(value_id));
1867
}
1868
}
1869
1870
void facets_register_facet_filter(FACETS *facets, const char *key, const char *value, FACET_KEY_OPTIONS options) {
1871
FACET_KEY *k = facets_register_facet(facets, key, options);
1872
if(k) {
1873
+ if(!(k->options & FACET_KEY_OPTION_FACET))
1874
+ k->options |= FACET_KEY_OPTION_FILTER_ONLY;
1875
+
1876
FACETS_HASH hash = FACETS_HASH_FUNCTION(value, strlen(value));
1877
k->default_selected_for_values = false;
1878
FACET_VALUE_ADD_OR_UPDATE_SELECTED(k, value, hash);
@@ -2591,7 +2613,7 @@ void facets_report(FACETS *facets, BUFFER *wb, DICTIONARY *used_hashes_registry)
2613
CLEAN_BUFFER *tb = buffer_create(0, NULL);
2614
FACET_KEY *k;
2615
foreach_key_in_facets(facets, k) {
2594
- if(!k->values.enabled || k->options & FACET_KEY_OPTION_HIDDEN)
2616
+ if(!k->values.enabled || k->options & (FACET_KEY_OPTION_HIDDEN|FACET_KEY_OPTION_FILTER_ONLY))
2617
continue;
2618
2619
facets_sort_and_reorder_values(k);
src/libnetdata/facets/facets.h
+1
@@ -38,6 +38,7 @@ typedef enum __attribute__((packed)) {
38
FACET_KEY_OPTION_EXPANDED_FILTER = (1 << 11), // the presentation should have this filter expanded by default
39
FACET_KEY_OPTION_PRETTY_XML = (1 << 12), // instruct the UI to parse this as an XML document
40
FACET_KEY_OPTION_HIDDEN = (1 << 13), // do not include this field in the response
41
+ FACET_KEY_OPTION_FILTER_ONLY = (1 << 14), // the key is filterable, but not to be exposed as facet
42
} FACET_KEY_OPTIONS;
43
44
typedef enum __attribute__((packed)) {
src/libnetdata/facets/logs_query_status.h
+2
-2
@@ -442,7 +442,7 @@ static inline bool lqs_request_parse_json_payload(json_object *jobj, void *data,
442
else {
443
// Call facets_register_facet_id_filter for each value
444
facets_register_facet_filter(
445
- facets, key, value, FACET_KEY_OPTION_FACET | FACET_KEY_OPTION_FTS | FACET_KEY_OPTION_REORDER);
445
+ facets, key, value, FACET_KEY_OPTION_FTS | FACET_KEY_OPTION_REORDER);
446
447
rq->filters++;
448
}
@@ -643,7 +643,7 @@ static inline bool lqs_request_parse_GET(LOGS_QUERY_STATUS *lqs, BUFFER *wb, cha
643
644
facets_register_facet_filter_id(
645
facets, keyword, value,
646
- FACET_KEY_OPTION_FACET | FACET_KEY_OPTION_FTS | FACET_KEY_OPTION_REORDER);
646
+ FACET_KEY_OPTION_FTS | FACET_KEY_OPTION_REORDER);
647
648
buffer_json_add_array_item_string(wb, value);
649
rq->filters++;