Journal updates (#16189)
* add column ND_JOURNAL_FILE showing the file each log line belongs to * ensure log timestamps are unique
Costa Tsaousis committed
Oct 13, 2023 at 23:54 UTC
7a9f4282e611be17c4976491a067daeab5604179
1 file changed
+39
-8
collectors/systemd-journal.plugin/systemd-journal.c
+39
-8
@@ -129,6 +129,9 @@ int fstat64(int fd, struct stat64 *buf) {
129
#define JOURNAL_PARAMETER_DELTA "delta"
130
#define JOURNAL_PARAMETER_TAIL "tail"
131
132
+#define JOURNAL_KEY_ND_JOURNAL_FILE "ND_JOURNAL_FILE"
133
+#define JOURNAL_KEY_ND_JOURNAL_PROCESS "ND_JOURNAL_PROCESS"
134
+
135
#define JOURNAL_DEFAULT_SLICE_MODE true
136
#define JOURNAL_DEFAULT_DIRECTION FACETS_ANCHOR_DIRECTION_BACKWARD
137
@@ -313,6 +316,8 @@ typedef struct function_query_status {
316
} FUNCTION_QUERY_STATUS;
317
318
struct journal_file {
319
+ const char *filename;
320
+ size_t filename_len;
321
STRING *source;
322
SD_JOURNAL_FILE_SOURCE_TYPE source_type;
323
usec_t file_last_modified_ut;
@@ -377,6 +382,8 @@ static inline size_t netdata_systemd_journal_process_row(sd_journal *j, FACETS *
382
const void *data;
383
size_t length, bytes = 0;
384
385
+ facets_add_key_value_length(facets, JOURNAL_KEY_ND_JOURNAL_FILE, sizeof(JOURNAL_KEY_ND_JOURNAL_FILE) - 1, jf->filename, jf->filename_len);
386
+
387
SD_JOURNAL_FOREACH_DATA(j, data, length) {
388
const char *key, *value;
389
size_t key_length, value_length;
@@ -455,6 +462,9 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_backward(
462
size_t row_counter = 0, last_row_counter = 0, rows_useful = 0;
463
size_t bytes = 0, last_bytes = 0;
464
465
+ usec_t last_usec_from = 0;
466
+ usec_t last_usec_to = 0;
467
+
468
ND_SD_JOURNAL_STATUS status = ND_SD_JOURNAL_OK;
469
470
facets_rows_begin(facets);
@@ -475,6 +485,13 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_backward(
485
break;
486
487
bytes += netdata_systemd_journal_process_row(j, facets, jf, &msg_ut);
488
+
489
+ // make sure each line gets a unique timestamp
490
+ if(unlikely(msg_ut >= last_usec_from && msg_ut <= last_usec_to))
491
+ msg_ut = --last_usec_from;
492
+ else
493
+ last_usec_from = last_usec_to = msg_ut;
494
+
495
if(facets_row_finished(facets, msg_ut))
496
rows_useful++;
497
@@ -531,6 +548,9 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_forward(
548
size_t row_counter = 0, last_row_counter = 0, rows_useful = 0;
549
size_t bytes = 0, last_bytes = 0;
550
551
+ usec_t last_usec_from = 0;
552
+ usec_t last_usec_to = 0;
553
+
554
ND_SD_JOURNAL_STATUS status = ND_SD_JOURNAL_OK;
555
556
facets_rows_begin(facets);
@@ -551,6 +571,13 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_forward(
571
break;
572
573
bytes += netdata_systemd_journal_process_row(j, facets, jf, &msg_ut);
574
+
575
+ // make sure each line gets a unique timestamp
576
+ if(unlikely(msg_ut >= last_usec_from && msg_ut <= last_usec_to))
577
+ msg_ut = ++last_usec_to;
578
+ else
579
+ last_usec_from = last_usec_to = msg_ut;
580
+
581
if(facets_row_finished(facets, msg_ut))
582
rows_useful++;
583
@@ -826,20 +853,21 @@ static STRING *string_strdupz_source(const char *s, const char *e, size_t max_le
853
854
static void files_registry_insert_cb(const DICTIONARY_ITEM *item, void *value, void *data __maybe_unused) {
855
struct journal_file *jf = value;
829
- const char *filename = dictionary_acquired_item_name(item);
856
+ jf->filename = dictionary_acquired_item_name(item);
857
+ jf->filename_len = strlen(jf->filename);
858
859
// based on the filename
860
// decide the source to show to the user
833
- const char *s = strrchr(filename, '/');
861
+ const char *s = strrchr(jf->filename, '/');
862
if(s) {
835
- if(strstr(filename, "/remote/"))
863
+ if(strstr(jf->filename, "/remote/"))
864
jf->source_type = SDJF_REMOTE;
865
else {
866
const char *t = s - 1;
839
- while(t >= filename && *t != '.' && *t != '/')
867
+ while(t >= jf->filename && *t != '.' && *t != '/')
868
t--;
869
842
- if(t >= filename && *t == '.') {
870
+ if(t >= jf->filename && *t == '.') {
871
jf->source_type = SDJF_NAMESPACE;
872
jf->source = string_strdupz_source(t + 1, s, SYSTEMD_JOURNAL_MAX_SOURCE_LEN, "namespace-");
873
}
@@ -890,13 +918,13 @@ static void files_registry_insert_cb(const DICTIONARY_ITEM *item, void *value, v
918
else
919
jf->source_type = SDJF_LOCAL | SDJF_OTHER;
920
893
- journal_file_update_msg_ut(filename, jf);
921
+ journal_file_update_msg_ut(jf->filename, jf);
922
923
internal_error(true,
924
"found journal file '%s', type %d, source '%s', "
925
"file modified: %"PRIu64", "
926
"msg {first: %"PRIu64", last: %"PRIu64"}",
899
- filename, jf->source_type, jf->source ? string2str(jf->source) : "<unset>",
927
+ jf->filename, jf->source_type, jf->source ? string2str(jf->source) : "<unset>",
928
jf->file_last_modified_ut,
929
jf->msg_first_ut, jf->msg_last_ut);
930
}
@@ -2165,7 +2193,7 @@ static void function_systemd_journal(const char *transaction, char *function, in
2193
facets_register_key_name(facets, "_HOSTNAME",
2194
FACET_KEY_OPTION_FACET | FACET_KEY_OPTION_VISIBLE | FACET_KEY_OPTION_FTS);
2195
2168
- facets_register_dynamic_key_name(facets, "ND_JOURNAL_PROCESS",
2196
+ facets_register_dynamic_key_name(facets, JOURNAL_KEY_ND_JOURNAL_PROCESS,
2197
FACET_KEY_OPTION_NEVER_FACET | FACET_KEY_OPTION_VISIBLE | FACET_KEY_OPTION_FTS,
2198
netdata_systemd_journal_dynamic_row_id, NULL);
2199
@@ -2190,6 +2218,9 @@ static void function_systemd_journal(const char *transaction, char *function, in
2218
FACET_KEY_OPTION_FACET | FACET_KEY_OPTION_FTS | FACET_KEY_OPTION_TRANSFORM_VIEW,
2219
netdata_systemd_journal_transform_errno, NULL);
2220
2221
+ facets_register_key_name(facets, JOURNAL_KEY_ND_JOURNAL_FILE,
2222
+ FACET_KEY_OPTION_NEVER_FACET);
2223
+
2224
facets_register_key_name(facets, "SYSLOG_IDENTIFIER",
2225
FACET_KEY_OPTION_FACET | FACET_KEY_OPTION_FTS);
2226