@cryptotaxi247 / netdata-1 / commits / b194954ff

allow any field to be a facet (#15880)

Costa Tsaousis committed Aug 25, 2023 at 09:43 UTC b194954ff59488b1f86dbc81a08532817170048f
3 files changed +79 -52
collectors/systemd-journal.plugin/systemd-journal.c
+58 -39
@@ -29,6 +29,7 @@
29 #define JOURNAL_PARAMETER_ANCHOR "anchor"
30 #define JOURNAL_PARAMETER_LAST "last"
31 #define JOURNAL_PARAMETER_QUERY "query"
32 +#define JOURNAL_PARAMETER_FACETS "facets"
33 #define JOURNAL_PARAMETER_HISTOGRAM "histogram"
34
35 #define SYSTEMD_ALWAYS_VISIBLE_KEYS NULL
@@ -52,6 +53,8 @@
53 "|_SYSTEMD_USER_UNIT" \
54 "|USER_UNIT" \
55 "|UNIT" \
56 + "|CONTAINER_NAME" \
57 + "|IMAGE_NAME" \
58 ""
59
60 static netdata_mutex_t mutex = NETDATA_MUTEX_INITIALIZER;
@@ -232,8 +235,7 @@ static char *uid_to_username(uid_t uid, char *buffer, size_t buffer_size) {
235 if (getpwuid_r(uid, &pw, tmp, 1024, &result) != 0 || result == NULL)
236 return NULL;
237
235 - strncpy(buffer, pw.pw_name, buffer_size - 1);
236 - buffer[buffer_size - 1] = '\0'; // Null-terminate just in case
238 + snprintfz(buffer, buffer_size - 1, "%u (%s)", uid, pw.pw_name);
239 return buffer;
240 }
241
@@ -244,8 +246,7 @@ static char *gid_to_groupname(gid_t gid, char* buffer, size_t buffer_size) {
246 if (getgrgid_r(gid, &grp, tmp, 1024, &result) != 0 || result == NULL)
247 return NULL;
248
247 - strncpy(buffer, grp.gr_name, buffer_size - 1);
248 - buffer[buffer_size - 1] = '\0'; // Null-terminate just in case
249 + snprintfz(buffer, buffer_size - 1, "%u (%s)", gid, grp.gr_name);
250 return buffer;
251 }
252
@@ -336,9 +337,6 @@ static void systemd_journal_dynamic_row_id(FACETS *facets __maybe_unused, BUFFER
337 }
338
339 static void function_systemd_journal(const char *transaction, char *function, char *line_buffer __maybe_unused, int line_max __maybe_unused, int timeout __maybe_unused) {
339 - char *words[SYSTEMD_JOURNAL_MAX_PARAMS] = { NULL };
340 - size_t num_words = quoted_strings_splitter_pluginsd(function, words, SYSTEMD_JOURNAL_MAX_PARAMS);
341 -
340 BUFFER *wb = buffer_create(0, NULL);
341 buffer_flush(wb);
342 buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_NEWLINE_ON_ARRAY_ITEMS);
@@ -353,31 +351,34 @@ static void function_systemd_journal(const char *transaction, char *function, ch
351 facets_accepted_param(facets, JOURNAL_PARAMETER_ANCHOR);
352 facets_accepted_param(facets, JOURNAL_PARAMETER_LAST);
353 facets_accepted_param(facets, JOURNAL_PARAMETER_QUERY);
354 + facets_accepted_param(facets, JOURNAL_PARAMETER_FACETS);
355 facets_accepted_param(facets, JOURNAL_PARAMETER_HISTOGRAM);
356
357 // register the fields in the order you want them on the dashboard
358
360 - facets_register_dynamic_key(facets, "ND_JOURNAL_PROCESS", FACET_KEY_OPTION_NO_FACET|FACET_KEY_OPTION_VISIBLE|FACET_KEY_OPTION_FTS,
361 - systemd_journal_dynamic_row_id, NULL);
359 + facets_register_dynamic_key_name(facets, "ND_JOURNAL_PROCESS",
360 + FACET_KEY_OPTION_NO_FACET | FACET_KEY_OPTION_VISIBLE | FACET_KEY_OPTION_FTS,
361 + systemd_journal_dynamic_row_id, NULL);
362
363 - facets_register_key(facets, "MESSAGE",
364 - FACET_KEY_OPTION_NO_FACET|FACET_KEY_OPTION_MAIN_TEXT|FACET_KEY_OPTION_VISIBLE|FACET_KEY_OPTION_FTS);
363 + facets_register_key_name(facets, "MESSAGE",
364 + FACET_KEY_OPTION_NO_FACET | FACET_KEY_OPTION_MAIN_TEXT | FACET_KEY_OPTION_VISIBLE |
365 + FACET_KEY_OPTION_FTS);
366
366 - facets_register_key_transformation(facets, "PRIORITY", FACET_KEY_OPTION_FACET|FACET_KEY_OPTION_FTS,
367 - systemd_journal_transform_priority, NULL);
367 + facets_register_key_name_transformation(facets, "PRIORITY", FACET_KEY_OPTION_FACET | FACET_KEY_OPTION_FTS,
368 + systemd_journal_transform_priority, NULL);
369
369 - facets_register_key_transformation(facets, "SYSLOG_FACILITY", FACET_KEY_OPTION_FACET|FACET_KEY_OPTION_FTS,
370 - systemd_journal_transform_syslog_facility, NULL);
370 + facets_register_key_name_transformation(facets, "SYSLOG_FACILITY", FACET_KEY_OPTION_FACET | FACET_KEY_OPTION_FTS,
371 + systemd_journal_transform_syslog_facility, NULL);
372
372 - facets_register_key(facets, "SYSLOG_IDENTIFIER", FACET_KEY_OPTION_FACET|FACET_KEY_OPTION_FTS);
373 - facets_register_key(facets, "UNIT", FACET_KEY_OPTION_FACET|FACET_KEY_OPTION_FTS);
374 - facets_register_key(facets, "USER_UNIT", FACET_KEY_OPTION_FACET|FACET_KEY_OPTION_FTS);
373 + facets_register_key_name(facets, "SYSLOG_IDENTIFIER", FACET_KEY_OPTION_FACET | FACET_KEY_OPTION_FTS);
374 + facets_register_key_name(facets, "UNIT", FACET_KEY_OPTION_FACET | FACET_KEY_OPTION_FTS);
375 + facets_register_key_name(facets, "USER_UNIT", FACET_KEY_OPTION_FACET | FACET_KEY_OPTION_FTS);
376
376 - facets_register_key_transformation(facets, "_UID", FACET_KEY_OPTION_FACET|FACET_KEY_OPTION_FTS,
377 - systemd_journal_transform_uid, uids);
377 + facets_register_key_name_transformation(facets, "_UID", FACET_KEY_OPTION_FACET | FACET_KEY_OPTION_FTS,
378 + systemd_journal_transform_uid, uids);
379
379 - facets_register_key_transformation(facets, "_GID", FACET_KEY_OPTION_FACET|FACET_KEY_OPTION_FTS,
380 - systemd_journal_transform_gid, gids);
380 + facets_register_key_name_transformation(facets, "_GID", FACET_KEY_OPTION_FACET | FACET_KEY_OPTION_FTS,
381 + systemd_journal_transform_gid, gids);
382
383 time_t after_s = 0, before_s = 0;
384 usec_t anchor = 0;
@@ -386,33 +387,53 @@ static void function_systemd_journal(const char *transaction, char *function, ch
387 const char *chart = NULL;
388
389 buffer_json_member_add_object(wb, "request");
389 - buffer_json_member_add_object(wb, "filters");
390
391 + char *words[SYSTEMD_JOURNAL_MAX_PARAMS] = { NULL };
392 + size_t num_words = quoted_strings_splitter_pluginsd(function, words, SYSTEMD_JOURNAL_MAX_PARAMS);
393 for(int i = 1; i < SYSTEMD_JOURNAL_MAX_PARAMS ;i++) {
392 - const char *keyword = get_word(words, num_words, i);
394 + char *keyword = get_word(words, num_words, i);
395 if(!keyword) break;
396
397 if(strcmp(keyword, JOURNAL_PARAMETER_HELP) == 0) {
398 systemd_journal_function_help(transaction);
399 goto cleanup;
400 }
399 - else if(strncmp(keyword, JOURNAL_PARAMETER_AFTER ":", strlen(JOURNAL_PARAMETER_AFTER ":")) == 0) {
400 - after_s = str2l(&keyword[strlen(JOURNAL_PARAMETER_AFTER ":")]);
401 + else if(strncmp(keyword, JOURNAL_PARAMETER_AFTER ":", sizeof(JOURNAL_PARAMETER_AFTER ":") - 1) == 0) {
402 + after_s = str2l(&keyword[sizeof(JOURNAL_PARAMETER_AFTER ":") - 1]);
403 }
402 - else if(strncmp(keyword, JOURNAL_PARAMETER_BEFORE ":", strlen(JOURNAL_PARAMETER_BEFORE ":")) == 0) {
403 - before_s = str2l(&keyword[strlen(JOURNAL_PARAMETER_BEFORE ":")]);
404 + else if(strncmp(keyword, JOURNAL_PARAMETER_BEFORE ":", sizeof(JOURNAL_PARAMETER_BEFORE ":") - 1) == 0) {
405 + before_s = str2l(&keyword[sizeof(JOURNAL_PARAMETER_BEFORE ":") - 1]);
406 }
405 - else if(strncmp(keyword, JOURNAL_PARAMETER_ANCHOR ":", strlen(JOURNAL_PARAMETER_ANCHOR ":")) == 0) {
406 - anchor = str2ull(&keyword[strlen(JOURNAL_PARAMETER_ANCHOR ":")], NULL);
407 + else if(strncmp(keyword, JOURNAL_PARAMETER_ANCHOR ":", sizeof(JOURNAL_PARAMETER_ANCHOR ":") - 1) == 0) {
408 + anchor = str2ull(&keyword[sizeof(JOURNAL_PARAMETER_ANCHOR ":") - 1], NULL);
409 }
408 - else if(strncmp(keyword, JOURNAL_PARAMETER_LAST ":", strlen(JOURNAL_PARAMETER_LAST ":")) == 0) {
409 - last = str2ul(&keyword[strlen(JOURNAL_PARAMETER_LAST ":")]);
410 + else if(strncmp(keyword, JOURNAL_PARAMETER_LAST ":", sizeof(JOURNAL_PARAMETER_LAST ":") - 1) == 0) {
411 + last = str2ul(&keyword[sizeof(JOURNAL_PARAMETER_LAST ":") - 1]);
412 }
411 - else if(strncmp(keyword, JOURNAL_PARAMETER_QUERY ":", strlen(JOURNAL_PARAMETER_QUERY ":")) == 0) {
412 - query= &keyword[strlen(JOURNAL_PARAMETER_QUERY ":")];
413 + else if(strncmp(keyword, JOURNAL_PARAMETER_QUERY ":", sizeof(JOURNAL_PARAMETER_QUERY ":") - 1) == 0) {
414 + query= &keyword[sizeof(JOURNAL_PARAMETER_QUERY ":") - 1];
415 }
414 - else if(strncmp(keyword, JOURNAL_PARAMETER_HISTOGRAM ":", strlen(JOURNAL_PARAMETER_HISTOGRAM ":")) == 0) {
415 - chart = &keyword[strlen(JOURNAL_PARAMETER_HISTOGRAM ":")];
416 + else if(strncmp(keyword, JOURNAL_PARAMETER_HISTOGRAM ":", sizeof(JOURNAL_PARAMETER_HISTOGRAM ":") - 1) == 0) {
417 + chart = &keyword[sizeof(JOURNAL_PARAMETER_HISTOGRAM ":") - 1];
418 + }
419 + else if(strncmp(keyword, JOURNAL_PARAMETER_FACETS ":", sizeof(JOURNAL_PARAMETER_FACETS ":") - 1) == 0) {
420 + char *value = &keyword[sizeof(JOURNAL_PARAMETER_FACETS ":") - 1];
421 + if(*value) {
422 + buffer_json_member_add_array(wb, JOURNAL_PARAMETER_FACETS);
423 +
424 + while(value) {
425 + char *sep = strchr(value, ',');
426 + if(sep)
427 + *sep++ = '\0';
428 +
429 + facets_register_facet_id(facets, value, FACET_KEY_OPTION_FACET|FACET_KEY_OPTION_FTS|FACET_KEY_OPTION_REORDER);
430 + buffer_json_add_array_item_string(wb, value);
431 +
432 + value = sep;
433 + }
434 +
435 + buffer_json_array_close(wb); // JOURNAL_PARAMETER_FACETS
436 + }
437 }
438 else {
439 char *value = strchr(keyword, ':');
@@ -426,7 +447,7 @@ static void function_systemd_journal(const char *transaction, char *function, ch
447 if(sep)
448 *sep++ = '\0';
449
429 - facets_register_facet_filter(facets, keyword, value, FACET_KEY_OPTION_REORDER);
450 + facets_register_facet_id_filter(facets, keyword, value, FACET_KEY_OPTION_FACET|FACET_KEY_OPTION_FTS|FACET_KEY_OPTION_REORDER);
451 buffer_json_add_array_item_string(wb, value);
452
453 value = sep;
@@ -437,8 +458,6 @@ static void function_systemd_journal(const char *transaction, char *function, ch
458 }
459 }
460
440 - buffer_json_object_close(wb); // filters
441 -
461 time_t expires = now_realtime_sec() + 1;
462 time_t now_s;
463
libnetdata/facets/facets.c
+16 -9
@@ -841,7 +841,7 @@ void facets_accepted_param(FACETS *facets, const char *param) {
841 dictionary_set(facets->accepted_params, param, NULL, 0);
842 }
843
844 -inline FACET_KEY *facets_register_key(FACETS *facets, const char *key, FACET_KEY_OPTIONS options) {
844 +inline FACET_KEY *facets_register_key_name(FACETS *facets, const char *key, FACET_KEY_OPTIONS options) {
845 FACET_KEY tk = {
846 .name = key,
847 .options = options,
@@ -852,15 +852,15 @@ inline FACET_KEY *facets_register_key(FACETS *facets, const char *key, FACET_KEY
852 return dictionary_set(facets->keys, hash, &tk, sizeof(tk));
853 }
854
855 -inline FACET_KEY *facets_register_key_transformation(FACETS *facets, const char *key, FACET_KEY_OPTIONS options, facets_key_transformer_t cb, void *data) {
856 - FACET_KEY *k = facets_register_key(facets, key, options);
855 +inline FACET_KEY *facets_register_key_name_transformation(FACETS *facets, const char *key, FACET_KEY_OPTIONS options, facets_key_transformer_t cb, void *data) {
856 + FACET_KEY *k = facets_register_key_name(facets, key, options);
857 k->transform.cb = cb;
858 k->transform.data = data;
859 return k;
860 }
861
862 -inline FACET_KEY *facets_register_dynamic_key(FACETS *facets, const char *key, FACET_KEY_OPTIONS options, facet_dynamic_row_t cb, void *data) {
863 - FACET_KEY *k = facets_register_key(facets, key, options);
862 +inline FACET_KEY *facets_register_dynamic_key_name(FACETS *facets, const char *key, FACET_KEY_OPTIONS options, facet_dynamic_row_t cb, void *data) {
863 + FACET_KEY *k = facets_register_key_name(facets, key, options);
864 k->dynamic.cb = cb;
865 k->dynamic.data = data;
866 return k;
@@ -881,17 +881,24 @@ void facets_set_anchor(FACETS *facets, usec_t anchor) {
881 facets->anchor = anchor;
882 }
883
884 -void facets_register_facet_filter(FACETS *facets, const char *key_id, char *value_ids, FACET_KEY_OPTIONS options) {
884 +inline FACET_KEY *facets_register_facet_id(FACETS *facets, const char *key_id, FACET_KEY_OPTIONS options) {
885 FACET_KEY tk = {
886 .options = options,
887 + .default_selected_for_values = true,
888 };
889 FACET_KEY *k = dictionary_set(facets->keys, key_id, &tk, sizeof(tk));
890
890 - k->default_selected_for_values = false;
891 k->options |= FACET_KEY_OPTION_FACET;
892 k->options &= ~FACET_KEY_OPTION_NO_FACET;
893 facet_key_late_init(facets, k);
894
895 + return k;
896 +}
897 +
898 +void facets_register_facet_id_filter(FACETS *facets, const char *key_id, char *value_ids, FACET_KEY_OPTIONS options) {
899 + FACET_KEY *k = facets_register_facet_id(facets, key_id, options);
900 + k->default_selected_for_values = false;
901 +
902 FACET_VALUE tv = {
903 .selected = true,
904 };
@@ -935,7 +942,7 @@ static inline void facets_check_value(FACETS *facets __maybe_unused, FACET_KEY *
942 }
943
944 void facets_add_key_value(FACETS *facets, const char *key, const char *value) {
938 - FACET_KEY *k = facets_register_key(facets, key, 0);
945 + FACET_KEY *k = facets_register_key_name(facets, key, 0);
946 buffer_flush(k->current_value.b);
947 buffer_strcat(k->current_value.b, value);
948 k->current_value.updated = true;
@@ -944,7 +951,7 @@ void facets_add_key_value(FACETS *facets, const char *key, const char *value) {
951 }
952
953 void facets_add_key_value_length(FACETS *facets, const char *key, const char *value, size_t value_len) {
947 - FACET_KEY *k = facets_register_key(facets, key, 0);
954 + FACET_KEY *k = facets_register_key_name(facets, key, 0);
955 buffer_flush(k->current_value.b);
956 buffer_strncat(k->current_value.b, value, value_len);
957 k->current_value.updated = true;
libnetdata/facets/facets.h
+5 -4
@@ -34,8 +34,8 @@ void facets_string_hash(const char *src, size_t len, char *out);
34
35 typedef void (*facets_key_transformer_t)(FACETS *facets __maybe_unused, BUFFER *wb, void *data);
36 typedef void (*facet_dynamic_row_t)(FACETS *facets, BUFFER *json_array, FACET_ROW_KEY_VALUE *rkv, FACET_ROW *row, void *data);
37 -FACET_KEY *facets_register_dynamic_key(FACETS *facets, const char *key, FACET_KEY_OPTIONS options, facet_dynamic_row_t cb, void *data);
38 -FACET_KEY *facets_register_key_transformation(FACETS *facets, const char *key, FACET_KEY_OPTIONS options, facets_key_transformer_t cb, void *data);
37 +FACET_KEY *facets_register_dynamic_key_name(FACETS *facets, const char *key, FACET_KEY_OPTIONS options, facet_dynamic_row_t cb, void *data);
38 +FACET_KEY *facets_register_key_name_transformation(FACETS *facets, const char *key, FACET_KEY_OPTIONS options, facets_key_transformer_t cb, void *data);
39
40 typedef enum __attribute__((packed)) {
41 FACETS_OPTION_ALL_FACETS_VISIBLE = (1 << 0), // all facets, should be visible by default in the table
@@ -50,11 +50,12 @@ void facets_accepted_param(FACETS *facets, const char *param);
50 void facets_rows_begin(FACETS *facets);
51 void facets_row_finished(FACETS *facets, usec_t usec);
52
53 -FACET_KEY *facets_register_key(FACETS *facets, const char *param, FACET_KEY_OPTIONS options);
53 +FACET_KEY *facets_register_key_name(FACETS *facets, const char *key, FACET_KEY_OPTIONS options);
54 void facets_set_query(FACETS *facets, const char *query);
55 void facets_set_items(FACETS *facets, uint32_t items);
56 void facets_set_anchor(FACETS *facets, usec_t anchor);
57 -void facets_register_facet_filter(FACETS *facets, const char *key_id, char *value_ids, FACET_KEY_OPTIONS options);
57 +FACET_KEY *facets_register_facet_id(FACETS *facets, const char *key_id, FACET_KEY_OPTIONS options);
58 +void facets_register_facet_id_filter(FACETS *facets, const char *key_id, char *value_ids, FACET_KEY_OPTIONS options);
59 void facets_set_histogram(FACETS *facets, const char *chart, usec_t after_ut, usec_t before_ut);
60
61 void facets_add_key_value(FACETS *facets, const char *key, const char *value);