@cryptotaxi247 / netdata-1 / commits / 48120b1b6

Series of NFCs to make the code more maintainable. (#20022)

* Use non systemd prefix for owned types. ``` $ find . -type f -iname '*.[ch]' -exec sed -i -e 's/SYSTEMD_JOURNAL/ND_SD_JOURNAL/g' {} \; ``` * Use non systemd prefix for owned types. ``` $ find . -type f -iname '*.[ch]' -exec sed -i -e 's/SYSTEMD_UNITS/ND_SD_UNITS/g' {} \; ``` * Use consistent name prefix for journal functionality. netdata_systemd_journal_* becomes nd_sd_journal_* * Rename journal_file struct to nd_journal_file. * Use non systemd prefix for owned types. ``` $ find . -type f -iname '*.[ch]' -exec sed -i -e 's/SDJF_/ND_SD_JF_/g' {} \; ``` * Use nd_journal_* prefix for function names instead of journal_* * Use njf instead of jf. * Remove commented code and prefix with `nd_*` left-over functions * Format code. NFC. * Add unused attribute because not all functions might be used. * Add proper prefix to journal_files_registry

vkalintiris committed Apr 1, 2025 at 21:01 UTC 48120b1b6addcdf4546f16637258cd306334002a
11 files changed +2444 -2084
src/collectors/systemd-journal.plugin/systemd-internals.h
+82 -54
@@ -10,16 +10,16 @@
10 #include <systemd/sd-journal.h>
11 #include <syslog.h>
12
13 -#define SYSTEMD_JOURNAL_FUNCTION_DESCRIPTION "View, search and analyze systemd journal entries."
14 -#define SYSTEMD_JOURNAL_FUNCTION_NAME "systemd-journal"
15 -#define SYSTEMD_JOURNAL_DEFAULT_TIMEOUT 60
16 -#define SYSTEMD_JOURNAL_ENABLE_ESTIMATIONS_FILE_PERCENTAGE 0.01
17 -#define SYSTEMD_JOURNAL_EXECUTE_WATCHER_PENDING_EVERY_MS 250
18 -#define SYSTEMD_JOURNAL_ALL_FILES_SCAN_EVERY_USEC (5 * 60 * USEC_PER_SEC)
13 +#define ND_SD_JOURNAL_FUNCTION_DESCRIPTION "View, search and analyze systemd journal entries."
14 +#define ND_SD_JOURNAL_FUNCTION_NAME "systemd-journal"
15 +#define ND_SD_JOURNAL_DEFAULT_TIMEOUT 60
16 +#define ND_SD_JOURNAL_ENABLE_ESTIMATIONS_FILE_PERCENTAGE 0.01
17 +#define ND_SD_JOURNAL_EXECUTE_WATCHER_PENDING_EVERY_MS 250
18 +#define ND_SD_JOURNAL_ALL_FILES_SCAN_EVERY_USEC (5 * 60 * USEC_PER_SEC)
19
20 -#define SYSTEMD_UNITS_FUNCTION_DESCRIPTION "View the status of systemd units"
21 -#define SYSTEMD_UNITS_FUNCTION_NAME "systemd-list-units"
22 -#define SYSTEMD_UNITS_DEFAULT_TIMEOUT 30
20 +#define ND_SD_UNITS_FUNCTION_DESCRIPTION "View the status of systemd units"
21 +#define ND_SD_UNITS_FUNCTION_NAME "systemd-list-units"
22 +#define ND_SD_UNITS_DEFAULT_TIMEOUT 30
23
24 extern __thread size_t fstat_thread_calls;
25 extern __thread size_t fstat_thread_cached_responses;
@@ -39,17 +39,17 @@ typedef enum {
39 } ND_SD_JOURNAL_STATUS;
40
41 typedef enum {
42 - SDJF_NONE = 0,
43 - SDJF_ALL = (1 << 0),
44 - SDJF_LOCAL_ALL = (1 << 1),
45 - SDJF_REMOTE_ALL = (1 << 2),
46 - SDJF_LOCAL_SYSTEM = (1 << 3),
47 - SDJF_LOCAL_USER = (1 << 4),
48 - SDJF_LOCAL_NAMESPACE = (1 << 5),
49 - SDJF_LOCAL_OTHER = (1 << 6),
42 + ND_SD_JF_NONE = 0,
43 + ND_SD_JF_ALL = (1 << 0),
44 + ND_SD_JF_LOCAL_ALL = (1 << 1),
45 + ND_SD_JF_REMOTE_ALL = (1 << 2),
46 + ND_SD_JF_LOCAL_SYSTEM = (1 << 3),
47 + ND_SD_JF_LOCAL_USER = (1 << 4),
48 + ND_SD_JF_LOCAL_NAMESPACE = (1 << 5),
49 + ND_SD_JF_LOCAL_OTHER = (1 << 6),
50 } SD_JOURNAL_FILE_SOURCE_TYPE;
51
52 -struct journal_file {
52 +struct nd_journal_file {
53 const char *filename;
54 size_t filename_len;
55 STRING *source;
@@ -73,44 +73,49 @@ struct journal_file {
73 uint64_t messages_in_file;
74 };
75
76 -#define SDJF_SOURCE_ALL_NAME "all"
77 -#define SDJF_SOURCE_LOCAL_NAME "all-local-logs"
78 -#define SDJF_SOURCE_LOCAL_SYSTEM_NAME "all-local-system-logs"
79 -#define SDJF_SOURCE_LOCAL_USERS_NAME "all-local-user-logs"
80 -#define SDJF_SOURCE_LOCAL_OTHER_NAME "all-uncategorized"
81 -#define SDJF_SOURCE_NAMESPACES_NAME "all-local-namespaces"
82 -#define SDJF_SOURCE_REMOTES_NAME "all-remote-systems"
76 +#define ND_SD_JF_SOURCE_ALL_NAME "all"
77 +#define ND_SD_JF_SOURCE_LOCAL_NAME "all-local-logs"
78 +#define ND_SD_JF_SOURCE_LOCAL_SYSTEM_NAME "all-local-system-logs"
79 +#define ND_SD_JF_SOURCE_LOCAL_USERS_NAME "all-local-user-logs"
80 +#define ND_SD_JF_SOURCE_LOCAL_OTHER_NAME "all-uncategorized"
81 +#define ND_SD_JF_SOURCE_NAMESPACES_NAME "all-local-namespaces"
82 +#define ND_SD_JF_SOURCE_REMOTES_NAME "all-remote-systems"
83
84 #define ND_SD_JOURNAL_OPEN_FLAGS (0)
85
86 -#define JOURNAL_VS_REALTIME_DELTA_DEFAULT_UT (5 * USEC_PER_SEC) // assume a 5-seconds latency
86 +#define JOURNAL_VS_REALTIME_DELTA_DEFAULT_UT (5 * USEC_PER_SEC) // assume a 5-seconds latency
87 #define JOURNAL_VS_REALTIME_DELTA_MAX_UT (2 * 60 * USEC_PER_SEC) // up to 2-minutes latency
88
89 -extern DICTIONARY *journal_files_registry;
89 +extern DICTIONARY *nd_journal_files_registry;
90 extern DICTIONARY *used_hashes_registry;
91 extern DICTIONARY *boot_ids_to_first_ut;
92
93 -int journal_file_dict_items_backward_compar(const void *a, const void *b);
94 -int journal_file_dict_items_forward_compar(const void *a, const void *b);
93 +int nd_journal_file_dict_items_backward_compar(const void *a, const void *b);
94 +int nd_journal_file_dict_items_forward_compar(const void *a, const void *b);
95 void buffer_json_journal_versions(BUFFER *wb);
96 void available_journal_file_sources_to_json_array(BUFFER *wb);
97 -bool journal_files_completed_once(void);
98 -void journal_files_registry_update(void);
99 -void journal_directory_scan_recursively(DICTIONARY *files, DICTIONARY *dirs, const char *dirname, int depth);
97 +bool nd_journal_files_completed_once(void);
98 +void nd_journal_files_registry_update(void);
99 +void nd_journal_directory_scan_recursively(DICTIONARY *files, DICTIONARY *dirs, const char *dirname, int depth);
100
101 FACET_ROW_SEVERITY syslog_priority_to_facet_severity(FACETS *facets, FACET_ROW *row, void *data);
102
103 -void netdata_systemd_journal_dynamic_row_id(FACETS *facets, BUFFER *json_array, FACET_ROW_KEY_VALUE *rkv, FACET_ROW *row, void *data);
104 -void netdata_systemd_journal_transform_priority(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
105 -void netdata_systemd_journal_transform_syslog_facility(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
106 -void netdata_systemd_journal_transform_errno(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
107 -void netdata_systemd_journal_transform_boot_id(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
108 -void netdata_systemd_journal_transform_uid(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
109 -void netdata_systemd_journal_transform_gid(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
110 -void netdata_systemd_journal_transform_cap_effective(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
111 -void netdata_systemd_journal_transform_timestamp_usec(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
112 -
113 -usec_t journal_file_update_annotation_boot_id(sd_journal *j, struct journal_file *jf, const char *boot_id);
103 +void nd_sd_journal_dynamic_row_id(
104 + FACETS *facets,
105 + BUFFER *json_array,
106 + FACET_ROW_KEY_VALUE *rkv,
107 + FACET_ROW *row,
108 + void *data);
109 +void nd_sd_journal_transform_priority(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
110 +void nd_sd_journal_transform_syslog_facility(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
111 +void nd_sd_journal_transform_errno(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
112 +void nd_sd_journal_transform_boot_id(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
113 +void nd_sd_journal_transform_uid(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
114 +void nd_sd_journal_transform_gid(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
115 +void nd_sd_journal_transform_cap_effective(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
116 +void nd_sd_journal_transform_timestamp_usec(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
117 +
118 +usec_t nd_journal_file_update_annotation_boot_id(sd_journal *j, struct nd_journal_file *njf, const char *boot_id);
119
120 #define MAX_JOURNAL_DIRECTORIES 100
121 struct journal_directory {
@@ -118,24 +123,47 @@ struct journal_directory {
123 };
124 extern struct journal_directory journal_directories[MAX_JOURNAL_DIRECTORIES];
125
121 -void journal_init_files_and_directories(void);
122 -void function_systemd_journal(const char *transaction, char *function, usec_t *stop_monotonic_ut, bool *cancelled, BUFFER *payload, HTTP_ACCESS access __maybe_unused, const char *source, void *data);
123 -void journal_file_update_header(const char *filename, struct journal_file *jf);
126 +void nd_journal_init_files_and_directories(void);
127 +void function_systemd_journal(
128 + const char *transaction,
129 + char *function,
130 + usec_t *stop_monotonic_ut,
131 + bool *cancelled,
132 + BUFFER *payload,
133 + HTTP_ACCESS access __maybe_unused,
134 + const char *source,
135 + void *data);
136 +void nd_journal_file_update_header(const char *filename, struct nd_journal_file *njf);
137
125 -void netdata_systemd_journal_annotations_init(void);
126 -void netdata_systemd_journal_transform_message_id(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
138 +void nd_sd_journal_annotations_init(void);
139 +void nd_sd_journal_transform_message_id(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
140
128 -void *journal_watcher_main(void *arg);
129 -void journal_watcher_restart(void);
141 +void *nd_journal_watcher_main(void *arg);
142 +void nd_journal_watcher_restart(void);
143
144 #ifdef ENABLE_SYSTEMD_DBUS
132 -void function_systemd_units(const char *transaction, char *function, usec_t *stop_monotonic_ut, bool *cancelled, BUFFER *payload, HTTP_ACCESS access __maybe_unused, const char *source, void *data);
145 +void function_systemd_units(
146 + const char *transaction,
147 + char *function,
148 + usec_t *stop_monotonic_ut,
149 + bool *cancelled,
150 + BUFFER *payload,
151 + HTTP_ACCESS access __maybe_unused,
152 + const char *source,
153 + void *data);
154 #endif
155
135 -static inline bool parse_journal_field(const char *data, size_t data_length, const char **key, size_t *key_length, const char **value, size_t *value_length) {
156 +static inline bool parse_journal_field(
157 + const char *data,
158 + size_t data_length,
159 + const char **key,
160 + size_t *key_length,
161 + const char **value,
162 + size_t *value_length)
163 +{
164 const char *k = data;
165 const char *equal = strchr(k, '=');
138 - if(unlikely(!equal))
166 + if (unlikely(!equal))
167 return false;
168
169 size_t kl = equal - k;
@@ -151,7 +179,7 @@ static inline bool parse_journal_field(const char *data, size_t data_length, con
179 return true;
180 }
181
154 -void systemd_journal_dyncfg_init(struct functions_evloop_globals *wg);
182 +void nd_systemd_journal_dyncfg_init(struct functions_evloop_globals *wg);
183
184 bool is_journal_file(const char *filename, ssize_t len, const char **start_of_extension);
185
src/collectors/systemd-journal.plugin/systemd-journal-annotations.c
+361 -289
@@ -2,255 +2,292 @@
2
3 #include "systemd-internals.h"
4
5 -// ----------------------------------------------------------------------------
6 -
5 const char *errno_map[] = {
8 - [1] = "1 (EPERM)", // "Operation not permitted",
9 - [2] = "2 (ENOENT)", // "No such file or directory",
10 - [3] = "3 (ESRCH)", // "No such process",
11 - [4] = "4 (EINTR)", // "Interrupted system call",
12 - [5] = "5 (EIO)", // "Input/output error",
13 - [6] = "6 (ENXIO)", // "No such device or address",
14 - [7] = "7 (E2BIG)", // "Argument list too long",
15 - [8] = "8 (ENOEXEC)", // "Exec format error",
16 - [9] = "9 (EBADF)", // "Bad file descriptor",
17 - [10] = "10 (ECHILD)", // "No child processes",
18 - [11] = "11 (EAGAIN)", // "Resource temporarily unavailable",
19 - [12] = "12 (ENOMEM)", // "Cannot allocate memory",
20 - [13] = "13 (EACCES)", // "Permission denied",
21 - [14] = "14 (EFAULT)", // "Bad address",
22 - [15] = "15 (ENOTBLK)", // "Block device required",
23 - [16] = "16 (EBUSY)", // "Device or resource busy",
24 - [17] = "17 (EEXIST)", // "File exists",
25 - [18] = "18 (EXDEV)", // "Invalid cross-device link",
26 - [19] = "19 (ENODEV)", // "No such device",
27 - [20] = "20 (ENOTDIR)", // "Not a directory",
28 - [21] = "21 (EISDIR)", // "Is a directory",
29 - [22] = "22 (EINVAL)", // "Invalid argument",
30 - [23] = "23 (ENFILE)", // "Too many open files in system",
31 - [24] = "24 (EMFILE)", // "Too many open files",
32 - [25] = "25 (ENOTTY)", // "Inappropriate ioctl for device",
33 - [26] = "26 (ETXTBSY)", // "Text file busy",
34 - [27] = "27 (EFBIG)", // "File too large",
35 - [28] = "28 (ENOSPC)", // "No space left on device",
36 - [29] = "29 (ESPIPE)", // "Illegal seek",
37 - [30] = "30 (EROFS)", // "Read-only file system",
38 - [31] = "31 (EMLINK)", // "Too many links",
39 - [32] = "32 (EPIPE)", // "Broken pipe",
40 - [33] = "33 (EDOM)", // "Numerical argument out of domain",
41 - [34] = "34 (ERANGE)", // "Numerical result out of range",
42 - [35] = "35 (EDEADLK)", // "Resource deadlock avoided",
43 - [36] = "36 (ENAMETOOLONG)", // "File name too long",
44 - [37] = "37 (ENOLCK)", // "No locks available",
45 - [38] = "38 (ENOSYS)", // "Function not implemented",
46 - [39] = "39 (ENOTEMPTY)", // "Directory not empty",
47 - [40] = "40 (ELOOP)", // "Too many levels of symbolic links",
48 - [42] = "42 (ENOMSG)", // "No message of desired type",
49 - [43] = "43 (EIDRM)", // "Identifier removed",
50 - [44] = "44 (ECHRNG)", // "Channel number out of range",
51 - [45] = "45 (EL2NSYNC)", // "Level 2 not synchronized",
52 - [46] = "46 (EL3HLT)", // "Level 3 halted",
53 - [47] = "47 (EL3RST)", // "Level 3 reset",
54 - [48] = "48 (ELNRNG)", // "Link number out of range",
55 - [49] = "49 (EUNATCH)", // "Protocol driver not attached",
56 - [50] = "50 (ENOCSI)", // "No CSI structure available",
57 - [51] = "51 (EL2HLT)", // "Level 2 halted",
58 - [52] = "52 (EBADE)", // "Invalid exchange",
59 - [53] = "53 (EBADR)", // "Invalid request descriptor",
60 - [54] = "54 (EXFULL)", // "Exchange full",
61 - [55] = "55 (ENOANO)", // "No anode",
62 - [56] = "56 (EBADRQC)", // "Invalid request code",
63 - [57] = "57 (EBADSLT)", // "Invalid slot",
64 - [59] = "59 (EBFONT)", // "Bad font file format",
65 - [60] = "60 (ENOSTR)", // "Device not a stream",
66 - [61] = "61 (ENODATA)", // "No data available",
67 - [62] = "62 (ETIME)", // "Timer expired",
68 - [63] = "63 (ENOSR)", // "Out of streams resources",
69 - [64] = "64 (ENONET)", // "Machine is not on the network",
70 - [65] = "65 (ENOPKG)", // "Package not installed",
71 - [66] = "66 (EREMOTE)", // "Object is remote",
72 - [67] = "67 (ENOLINK)", // "Link has been severed",
73 - [68] = "68 (EADV)", // "Advertise error",
74 - [69] = "69 (ESRMNT)", // "Srmount error",
75 - [70] = "70 (ECOMM)", // "Communication error on send",
76 - [71] = "71 (EPROTO)", // "Protocol error",
77 - [72] = "72 (EMULTIHOP)", // "Multihop attempted",
78 - [73] = "73 (EDOTDOT)", // "RFS specific error",
79 - [74] = "74 (EBADMSG)", // "Bad message",
80 - [75] = "75 (EOVERFLOW)", // "Value too large for defined data type",
81 - [76] = "76 (ENOTUNIQ)", // "Name not unique on network",
82 - [77] = "77 (EBADFD)", // "File descriptor in bad state",
83 - [78] = "78 (EREMCHG)", // "Remote address changed",
84 - [79] = "79 (ELIBACC)", // "Can not access a needed shared library",
85 - [80] = "80 (ELIBBAD)", // "Accessing a corrupted shared library",
86 - [81] = "81 (ELIBSCN)", // ".lib section in a.out corrupted",
87 - [82] = "82 (ELIBMAX)", // "Attempting to link in too many shared libraries",
88 - [83] = "83 (ELIBEXEC)", // "Cannot exec a shared library directly",
89 - [84] = "84 (EILSEQ)", // "Invalid or incomplete multibyte or wide character",
90 - [85] = "85 (ERESTART)", // "Interrupted system call should be restarted",
91 - [86] = "86 (ESTRPIPE)", // "Streams pipe error",
92 - [87] = "87 (EUSERS)", // "Too many users",
93 - [88] = "88 (ENOTSOCK)", // "Socket operation on non-socket",
94 - [89] = "89 (EDESTADDRREQ)", // "Destination address required",
95 - [90] = "90 (EMSGSIZE)", // "Message too long",
96 - [91] = "91 (EPROTOTYPE)", // "Protocol wrong type for socket",
97 - [92] = "92 (ENOPROTOOPT)", // "Protocol not available",
98 - [93] = "93 (EPROTONOSUPPORT)", // "Protocol not supported",
99 - [94] = "94 (ESOCKTNOSUPPORT)", // "Socket type not supported",
100 - [95] = "95 (ENOTSUP)", // "Operation not supported",
101 - [96] = "96 (EPFNOSUPPORT)", // "Protocol family not supported",
102 - [97] = "97 (EAFNOSUPPORT)", // "Address family not supported by protocol",
103 - [98] = "98 (EADDRINUSE)", // "Address already in use",
104 - [99] = "99 (EADDRNOTAVAIL)", // "Cannot assign requested address",
105 - [100] = "100 (ENETDOWN)", // "Network is down",
106 - [101] = "101 (ENETUNREACH)", // "Network is unreachable",
107 - [102] = "102 (ENETRESET)", // "Network dropped connection on reset",
108 - [103] = "103 (ECONNABORTED)", // "Software caused connection abort",
109 - [104] = "104 (ECONNRESET)", // "Connection reset by peer",
110 - [105] = "105 (ENOBUFS)", // "No buffer space available",
111 - [106] = "106 (EISCONN)", // "Transport endpoint is already connected",
112 - [107] = "107 (ENOTCONN)", // "Transport endpoint is not connected",
113 - [108] = "108 (ESHUTDOWN)", // "Cannot send after transport endpoint shutdown",
114 - [109] = "109 (ETOOMANYREFS)", // "Too many references: cannot splice",
115 - [110] = "110 (ETIMEDOUT)", // "Connection timed out",
116 - [111] = "111 (ECONNREFUSED)", // "Connection refused",
117 - [112] = "112 (EHOSTDOWN)", // "Host is down",
118 - [113] = "113 (EHOSTUNREACH)", // "No route to host",
119 - [114] = "114 (EALREADY)", // "Operation already in progress",
120 - [115] = "115 (EINPROGRESS)", // "Operation now in progress",
121 - [116] = "116 (ESTALE)", // "Stale file handle",
122 - [117] = "117 (EUCLEAN)", // "Structure needs cleaning",
123 - [118] = "118 (ENOTNAM)", // "Not a XENIX named type file",
124 - [119] = "119 (ENAVAIL)", // "No XENIX semaphores available",
125 - [120] = "120 (EISNAM)", // "Is a named type file",
126 - [121] = "121 (EREMOTEIO)", // "Remote I/O error",
127 - [122] = "122 (EDQUOT)", // "Disk quota exceeded",
128 - [123] = "123 (ENOMEDIUM)", // "No medium found",
129 - [124] = "124 (EMEDIUMTYPE)", // "Wrong medium type",
130 - [125] = "125 (ECANCELED)", // "Operation canceled",
131 - [126] = "126 (ENOKEY)", // "Required key not available",
132 - [127] = "127 (EKEYEXPIRED)", // "Key has expired",
133 - [128] = "128 (EKEYREVOKED)", // "Key has been revoked",
134 - [129] = "129 (EKEYREJECTED)", // "Key was rejected by service",
135 - [130] = "130 (EOWNERDEAD)", // "Owner died",
136 - [131] = "131 (ENOTRECOVERABLE)", // "State not recoverable",
137 - [132] = "132 (ERFKILL)", // "Operation not possible due to RF-kill",
138 - [133] = "133 (EHWPOISON)", // "Memory page has hardware error",
6 + [1] = "1 (EPERM)", // "Operation not permitted",
7 + [2] = "2 (ENOENT)", // "No such file or directory",
8 + [3] = "3 (ESRCH)", // "No such process",
9 + [4] = "4 (EINTR)", // "Interrupted system call",
10 + [5] = "5 (EIO)", // "Input/output error",
11 + [6] = "6 (ENXIO)", // "No such device or address",
12 + [7] = "7 (E2BIG)", // "Argument list too long",
13 + [8] = "8 (ENOEXEC)", // "Exec format error",
14 + [9] = "9 (EBADF)", // "Bad file descriptor",
15 + [10] = "10 (ECHILD)", // "No child processes",
16 + [11] = "11 (EAGAIN)", // "Resource temporarily unavailable",
17 + [12] = "12 (ENOMEM)", // "Cannot allocate memory",
18 + [13] = "13 (EACCES)", // "Permission denied",
19 + [14] = "14 (EFAULT)", // "Bad address",
20 + [15] = "15 (ENOTBLK)", // "Block device required",
21 + [16] = "16 (EBUSY)", // "Device or resource busy",
22 + [17] = "17 (EEXIST)", // "File exists",
23 + [18] = "18 (EXDEV)", // "Invalid cross-device link",
24 + [19] = "19 (ENODEV)", // "No such device",
25 + [20] = "20 (ENOTDIR)", // "Not a directory",
26 + [21] = "21 (EISDIR)", // "Is a directory",
27 + [22] = "22 (EINVAL)", // "Invalid argument",
28 + [23] = "23 (ENFILE)", // "Too many open files in system",
29 + [24] = "24 (EMFILE)", // "Too many open files",
30 + [25] = "25 (ENOTTY)", // "Inappropriate ioctl for device",
31 + [26] = "26 (ETXTBSY)", // "Text file busy",
32 + [27] = "27 (EFBIG)", // "File too large",
33 + [28] = "28 (ENOSPC)", // "No space left on device",
34 + [29] = "29 (ESPIPE)", // "Illegal seek",
35 + [30] = "30 (EROFS)", // "Read-only file system",
36 + [31] = "31 (EMLINK)", // "Too many links",
37 + [32] = "32 (EPIPE)", // "Broken pipe",
38 + [33] = "33 (EDOM)", // "Numerical argument out of domain",
39 + [34] = "34 (ERANGE)", // "Numerical result out of range",
40 + [35] = "35 (EDEADLK)", // "Resource deadlock avoided",
41 + [36] = "36 (ENAMETOOLONG)", // "File name too long",
42 + [37] = "37 (ENOLCK)", // "No locks available",
43 + [38] = "38 (ENOSYS)", // "Function not implemented",
44 + [39] = "39 (ENOTEMPTY)", // "Directory not empty",
45 + [40] = "40 (ELOOP)", // "Too many levels of symbolic links",
46 + [42] = "42 (ENOMSG)", // "No message of desired type",
47 + [43] = "43 (EIDRM)", // "Identifier removed",
48 + [44] = "44 (ECHRNG)", // "Channel number out of range",
49 + [45] = "45 (EL2NSYNC)", // "Level 2 not synchronized",
50 + [46] = "46 (EL3HLT)", // "Level 3 halted",
51 + [47] = "47 (EL3RST)", // "Level 3 reset",
52 + [48] = "48 (ELNRNG)", // "Link number out of range",
53 + [49] = "49 (EUNATCH)", // "Protocol driver not attached",
54 + [50] = "50 (ENOCSI)", // "No CSI structure available",
55 + [51] = "51 (EL2HLT)", // "Level 2 halted",
56 + [52] = "52 (EBADE)", // "Invalid exchange",
57 + [53] = "53 (EBADR)", // "Invalid request descriptor",
58 + [54] = "54 (EXFULL)", // "Exchange full",
59 + [55] = "55 (ENOANO)", // "No anode",
60 + [56] = "56 (EBADRQC)", // "Invalid request code",
61 + [57] = "57 (EBADSLT)", // "Invalid slot",
62 + [59] = "59 (EBFONT)", // "Bad font file format",
63 + [60] = "60 (ENOSTR)", // "Device not a stream",
64 + [61] = "61 (ENODATA)", // "No data available",
65 + [62] = "62 (ETIME)", // "Timer expired",
66 + [63] = "63 (ENOSR)", // "Out of streams resources",
67 + [64] = "64 (ENONET)", // "Machine is not on the network",
68 + [65] = "65 (ENOPKG)", // "Package not installed",
69 + [66] = "66 (EREMOTE)", // "Object is remote",
70 + [67] = "67 (ENOLINK)", // "Link has been severed",
71 + [68] = "68 (EADV)", // "Advertise error",
72 + [69] = "69 (ESRMNT)", // "Srmount error",
73 + [70] = "70 (ECOMM)", // "Communication error on send",
74 + [71] = "71 (EPROTO)", // "Protocol error",
75 + [72] = "72 (EMULTIHOP)", // "Multihop attempted",
76 + [73] = "73 (EDOTDOT)", // "RFS specific error",
77 + [74] = "74 (EBADMSG)", // "Bad message",
78 + [75] = "75 (EOVERFLOW)", // "Value too large for defined data type",
79 + [76] = "76 (ENOTUNIQ)", // "Name not unique on network",
80 + [77] = "77 (EBADFD)", // "File descriptor in bad state",
81 + [78] = "78 (EREMCHG)", // "Remote address changed",
82 + [79] = "79 (ELIBACC)", // "Can not access a needed shared library",
83 + [80] = "80 (ELIBBAD)", // "Accessing a corrupted shared library",
84 + [81] = "81 (ELIBSCN)", // ".lib section in a.out corrupted",
85 + [82] = "82 (ELIBMAX)", // "Attempting to link in too many shared libraries",
86 + [83] = "83 (ELIBEXEC)", // "Cannot exec a shared library directly",
87 + [84] = "84 (EILSEQ)", // "Invalid or incomplete multibyte or wide character",
88 + [85] = "85 (ERESTART)", // "Interrupted system call should be restarted",
89 + [86] = "86 (ESTRPIPE)", // "Streams pipe error",
90 + [87] = "87 (EUSERS)", // "Too many users",
91 + [88] = "88 (ENOTSOCK)", // "Socket operation on non-socket",
92 + [89] = "89 (EDESTADDRREQ)", // "Destination address required",
93 + [90] = "90 (EMSGSIZE)", // "Message too long",
94 + [91] = "91 (EPROTOTYPE)", // "Protocol wrong type for socket",
95 + [92] = "92 (ENOPROTOOPT)", // "Protocol not available",
96 + [93] = "93 (EPROTONOSUPPORT)", // "Protocol not supported",
97 + [94] = "94 (ESOCKTNOSUPPORT)", // "Socket type not supported",
98 + [95] = "95 (ENOTSUP)", // "Operation not supported",
99 + [96] = "96 (EPFNOSUPPORT)", // "Protocol family not supported",
100 + [97] = "97 (EAFNOSUPPORT)", // "Address family not supported by protocol",
101 + [98] = "98 (EADDRINUSE)", // "Address already in use",
102 + [99] = "99 (EADDRNOTAVAIL)", // "Cannot assign requested address",
103 + [100] = "100 (ENETDOWN)", // "Network is down",
104 + [101] = "101 (ENETUNREACH)", // "Network is unreachable",
105 + [102] = "102 (ENETRESET)", // "Network dropped connection on reset",
106 + [103] = "103 (ECONNABORTED)", // "Software caused connection abort",
107 + [104] = "104 (ECONNRESET)", // "Connection reset by peer",
108 + [105] = "105 (ENOBUFS)", // "No buffer space available",
109 + [106] = "106 (EISCONN)", // "Transport endpoint is already connected",
110 + [107] = "107 (ENOTCONN)", // "Transport endpoint is not connected",
111 + [108] = "108 (ESHUTDOWN)", // "Cannot send after transport endpoint shutdown",
112 + [109] = "109 (ETOOMANYREFS)", // "Too many references: cannot splice",
113 + [110] = "110 (ETIMEDOUT)", // "Connection timed out",
114 + [111] = "111 (ECONNREFUSED)", // "Connection refused",
115 + [112] = "112 (EHOSTDOWN)", // "Host is down",
116 + [113] = "113 (EHOSTUNREACH)", // "No route to host",
117 + [114] = "114 (EALREADY)", // "Operation already in progress",
118 + [115] = "115 (EINPROGRESS)", // "Operation now in progress",
119 + [116] = "116 (ESTALE)", // "Stale file handle",
120 + [117] = "117 (EUCLEAN)", // "Structure needs cleaning",
121 + [118] = "118 (ENOTNAM)", // "Not a XENIX named type file",
122 + [119] = "119 (ENAVAIL)", // "No XENIX semaphores available",
123 + [120] = "120 (EISNAM)", // "Is a named type file",
124 + [121] = "121 (EREMOTEIO)", // "Remote I/O error",
125 + [122] = "122 (EDQUOT)", // "Disk quota exceeded",
126 + [123] = "123 (ENOMEDIUM)", // "No medium found",
127 + [124] = "124 (EMEDIUMTYPE)", // "Wrong medium type",
128 + [125] = "125 (ECANCELED)", // "Operation canceled",
129 + [126] = "126 (ENOKEY)", // "Required key not available",
130 + [127] = "127 (EKEYEXPIRED)", // "Key has expired",
131 + [128] = "128 (EKEYREVOKED)", // "Key has been revoked",
132 + [129] = "129 (EKEYREJECTED)", // "Key was rejected by service",
133 + [130] = "130 (EOWNERDEAD)", // "Owner died",
134 + [131] = "131 (ENOTRECOVERABLE)", // "State not recoverable",
135 + [132] = "132 (ERFKILL)", // "Operation not possible due to RF-kill",
136 + [133] = "133 (EHWPOISON)", // "Memory page has hardware error",
137 };
138
139 const char *linux_capabilities[] = {
142 - [CAP_CHOWN] = "CHOWN",
143 - [CAP_DAC_OVERRIDE] = "DAC_OVERRIDE",
144 - [CAP_DAC_READ_SEARCH] = "DAC_READ_SEARCH",
145 - [CAP_FOWNER] = "FOWNER",
146 - [CAP_FSETID] = "FSETID",
147 - [CAP_KILL] = "KILL",
148 - [CAP_SETGID] = "SETGID",
149 - [CAP_SETUID] = "SETUID",
150 - [CAP_SETPCAP] = "SETPCAP",
151 - [CAP_LINUX_IMMUTABLE] = "LINUX_IMMUTABLE",
152 - [CAP_NET_BIND_SERVICE] = "NET_BIND_SERVICE",
153 - [CAP_NET_BROADCAST] = "NET_BROADCAST",
154 - [CAP_NET_ADMIN] = "NET_ADMIN",
155 - [CAP_NET_RAW] = "NET_RAW",
156 - [CAP_IPC_LOCK] = "IPC_LOCK",
157 - [CAP_IPC_OWNER] = "IPC_OWNER",
158 - [CAP_SYS_MODULE] = "SYS_MODULE",
159 - [CAP_SYS_RAWIO] = "SYS_RAWIO",
160 - [CAP_SYS_CHROOT] = "SYS_CHROOT",
161 - [CAP_SYS_PTRACE] = "SYS_PTRACE",
162 - [CAP_SYS_PACCT] = "SYS_PACCT",
163 - [CAP_SYS_ADMIN] = "SYS_ADMIN",
164 - [CAP_SYS_BOOT] = "SYS_BOOT",
165 - [CAP_SYS_NICE] = "SYS_NICE",
166 - [CAP_SYS_RESOURCE] = "SYS_RESOURCE",
167 - [CAP_SYS_TIME] = "SYS_TIME",
168 - [CAP_SYS_TTY_CONFIG] = "SYS_TTY_CONFIG",
169 - [CAP_MKNOD] = "MKNOD",
170 - [CAP_LEASE] = "LEASE",
171 - [CAP_AUDIT_WRITE] = "AUDIT_WRITE",
172 - [CAP_AUDIT_CONTROL] = "AUDIT_CONTROL",
173 - [CAP_SETFCAP] = "SETFCAP",
174 - [CAP_MAC_OVERRIDE] = "MAC_OVERRIDE",
175 - [CAP_MAC_ADMIN] = "MAC_ADMIN",
176 - [CAP_SYSLOG] = "SYSLOG",
177 - [CAP_WAKE_ALARM] = "WAKE_ALARM",
178 - [CAP_BLOCK_SUSPEND] = "BLOCK_SUSPEND",
179 - [37 /*CAP_AUDIT_READ*/] = "AUDIT_READ",
180 - [38 /*CAP_PERFMON*/] = "PERFMON",
181 - [39 /*CAP_BPF*/] = "BPF",
182 - [40 /* CAP_CHECKPOINT_RESTORE */] = "CHECKPOINT_RESTORE",
140 + [CAP_CHOWN] = "CHOWN",
141 + [CAP_DAC_OVERRIDE] = "DAC_OVERRIDE",
142 + [CAP_DAC_READ_SEARCH] = "DAC_READ_SEARCH",
143 + [CAP_FOWNER] = "FOWNER",
144 + [CAP_FSETID] = "FSETID",
145 + [CAP_KILL] = "KILL",
146 + [CAP_SETGID] = "SETGID",
147 + [CAP_SETUID] = "SETUID",
148 + [CAP_SETPCAP] = "SETPCAP",
149 + [CAP_LINUX_IMMUTABLE] = "LINUX_IMMUTABLE",
150 + [CAP_NET_BIND_SERVICE] = "NET_BIND_SERVICE",
151 + [CAP_NET_BROADCAST] = "NET_BROADCAST",
152 + [CAP_NET_ADMIN] = "NET_ADMIN",
153 + [CAP_NET_RAW] = "NET_RAW",
154 + [CAP_IPC_LOCK] = "IPC_LOCK",
155 + [CAP_IPC_OWNER] = "IPC_OWNER",
156 + [CAP_SYS_MODULE] = "SYS_MODULE",
157 + [CAP_SYS_RAWIO] = "SYS_RAWIO",
158 + [CAP_SYS_CHROOT] = "SYS_CHROOT",
159 + [CAP_SYS_PTRACE] = "SYS_PTRACE",
160 + [CAP_SYS_PACCT] = "SYS_PACCT",
161 + [CAP_SYS_ADMIN] = "SYS_ADMIN",
162 + [CAP_SYS_BOOT] = "SYS_BOOT",
163 + [CAP_SYS_NICE] = "SYS_NICE",
164 + [CAP_SYS_RESOURCE] = "SYS_RESOURCE",
165 + [CAP_SYS_TIME] = "SYS_TIME",
166 + [CAP_SYS_TTY_CONFIG] = "SYS_TTY_CONFIG",
167 + [CAP_MKNOD] = "MKNOD",
168 + [CAP_LEASE] = "LEASE",
169 + [CAP_AUDIT_WRITE] = "AUDIT_WRITE",
170 + [CAP_AUDIT_CONTROL] = "AUDIT_CONTROL",
171 + [CAP_SETFCAP] = "SETFCAP",
172 + [CAP_MAC_OVERRIDE] = "MAC_OVERRIDE",
173 + [CAP_MAC_ADMIN] = "MAC_ADMIN",
174 + [CAP_SYSLOG] = "SYSLOG",
175 + [CAP_WAKE_ALARM] = "WAKE_ALARM",
176 + [CAP_BLOCK_SUSPEND] = "BLOCK_SUSPEND",
177 + [37 /*CAP_AUDIT_READ*/] = "AUDIT_READ",
178 + [38 /*CAP_PERFMON*/] = "PERFMON",
179 + [39 /*CAP_BPF*/] = "BPF",
180 + [40 /* CAP_CHECKPOINT_RESTORE */] = "CHECKPOINT_RESTORE",
181 };
182
185 -static const char *syslog_facility_to_name(int facility) {
183 +static const char *syslog_facility_to_name(int facility)
184 +{
185 switch (facility) {
187 - case LOG_FAC(LOG_KERN): return "kern";
188 - case LOG_FAC(LOG_USER): return "user";
189 - case LOG_FAC(LOG_MAIL): return "mail";
190 - case LOG_FAC(LOG_DAEMON): return "daemon";
191 - case LOG_FAC(LOG_AUTH): return "auth";
192 - case LOG_FAC(LOG_SYSLOG): return "syslog";
193 - case LOG_FAC(LOG_LPR): return "lpr";
194 - case LOG_FAC(LOG_NEWS): return "news";
195 - case LOG_FAC(LOG_UUCP): return "uucp";
196 - case LOG_FAC(LOG_CRON): return "cron";
197 - case LOG_FAC(LOG_AUTHPRIV): return "authpriv";
198 - case LOG_FAC(LOG_FTP): return "ftp";
199 - case LOG_FAC(LOG_LOCAL0): return "local0";
200 - case LOG_FAC(LOG_LOCAL1): return "local1";
201 - case LOG_FAC(LOG_LOCAL2): return "local2";
202 - case LOG_FAC(LOG_LOCAL3): return "local3";
203 - case LOG_FAC(LOG_LOCAL4): return "local4";
204 - case LOG_FAC(LOG_LOCAL5): return "local5";
205 - case LOG_FAC(LOG_LOCAL6): return "local6";
206 - case LOG_FAC(LOG_LOCAL7): return "local7";
207 - default: return NULL;
186 + case LOG_FAC(LOG_KERN):
187 + return "kern";
188 + case LOG_FAC(LOG_USER):
189 + return "user";
190 + case LOG_FAC(LOG_MAIL):
191 + return "mail";
192 + case LOG_FAC(LOG_DAEMON):
193 + return "daemon";
194 + case LOG_FAC(LOG_AUTH):
195 + return "auth";
196 + case LOG_FAC(LOG_SYSLOG):
197 + return "syslog";
198 + case LOG_FAC(LOG_LPR):
199 + return "lpr";
200 + case LOG_FAC(LOG_NEWS):
201 + return "news";
202 + case LOG_FAC(LOG_UUCP):
203 + return "uucp";
204 + case LOG_FAC(LOG_CRON):
205 + return "cron";
206 + case LOG_FAC(LOG_AUTHPRIV):
207 + return "authpriv";
208 + case LOG_FAC(LOG_FTP):
209 + return "ftp";
210 + case LOG_FAC(LOG_LOCAL0):
211 + return "local0";
212 + case LOG_FAC(LOG_LOCAL1):
213 + return "local1";
214 + case LOG_FAC(LOG_LOCAL2):
215 + return "local2";
216 + case LOG_FAC(LOG_LOCAL3):
217 + return "local3";
218 + case LOG_FAC(LOG_LOCAL4):
219 + return "local4";
220 + case LOG_FAC(LOG_LOCAL5):
221 + return "local5";
222 + case LOG_FAC(LOG_LOCAL6):
223 + return "local6";
224 + case LOG_FAC(LOG_LOCAL7):
225 + return "local7";
226 + default:
227 + return NULL;
228 }
229 }
230
211 -static const char *syslog_priority_to_name(int priority) {
231 +static const char *syslog_priority_to_name(int priority)
232 +{
233 switch (priority) {
213 - case LOG_ALERT: return "alert";
214 - case LOG_CRIT: return "critical";
215 - case LOG_DEBUG: return "debug";
216 - case LOG_EMERG: return "panic";
217 - case LOG_ERR: return "error";
218 - case LOG_INFO: return "info";
219 - case LOG_NOTICE: return "notice";
220 - case LOG_WARNING: return "warning";
221 - default: return NULL;
234 + case LOG_ALERT:
235 + return "alert";
236 + case LOG_CRIT:
237 + return "critical";
238 + case LOG_DEBUG:
239 + return "debug";
240 + case LOG_EMERG:
241 + return "panic";
242 + case LOG_ERR:
243 + return "error";
244 + case LOG_INFO:
245 + return "info";
246 + case LOG_NOTICE:
247 + return "notice";
248 + case LOG_WARNING:
249 + return "warning";
250 + default:
251 + return NULL;
252 }
253 }
254
225 -FACET_ROW_SEVERITY syslog_priority_to_facet_severity(FACETS *facets __maybe_unused, FACET_ROW *row, void *data __maybe_unused) {
255 +FACET_ROW_SEVERITY
256 +syslog_priority_to_facet_severity(FACETS *facets __maybe_unused, FACET_ROW *row, void *data __maybe_unused)
257 +{
258 // same to
259 // https://github.com/systemd/systemd/blob/aab9e4b2b86905a15944a1ac81e471b5b7075932/src/basic/terminal-util.c#L1501
260 // function get_log_colors()
261
262 FACET_ROW_KEY_VALUE *priority_rkv = dictionary_get(row->dict, "PRIORITY");
231 - if(!priority_rkv || priority_rkv->empty)
263 + if (!priority_rkv || priority_rkv->empty)
264 return FACET_ROW_SEVERITY_NORMAL;
265
266 int priority = str2i(buffer_tostring(priority_rkv->wb));
267
236 - if(priority <= LOG_ERR)
268 + if (priority <= LOG_ERR)
269 return FACET_ROW_SEVERITY_CRITICAL;
270
271 else if (priority <= LOG_WARNING)
272 return FACET_ROW_SEVERITY_WARNING;
273
242 - else if(priority <= LOG_NOTICE)
274 + else if (priority <= LOG_NOTICE)
275 return FACET_ROW_SEVERITY_NOTICE;
276
245 - else if(priority >= LOG_DEBUG)
277 + else if (priority >= LOG_DEBUG)
278 return FACET_ROW_SEVERITY_DEBUG;
279
280 return FACET_ROW_SEVERITY_NORMAL;
281 }
282
251 -void netdata_systemd_journal_transform_syslog_facility(FACETS *facets __maybe_unused, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, void *data __maybe_unused) {
283 +void nd_sd_journal_transform_syslog_facility(
284 + FACETS *facets __maybe_unused,
285 + BUFFER *wb,
286 + FACETS_TRANSFORMATION_SCOPE scope __maybe_unused,
287 + void *data __maybe_unused)
288 +{
289 const char *v = buffer_tostring(wb);
253 - if(*v && isdigit(*v)) {
290 + if (*v && isdigit(*v)) {
291 int facility = str2i(buffer_tostring(wb));
292 const char *name = syslog_facility_to_name(facility);
293 if (name) {
@@ -260,12 +297,17 @@ void netdata_systemd_journal_transform_syslog_facility(FACETS *facets __maybe_un
297 }
298 }
299
263 -void netdata_systemd_journal_transform_priority(FACETS *facets __maybe_unused, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, void *data __maybe_unused) {
264 - if(scope == FACETS_TRANSFORM_FACET_SORT)
300 +void nd_sd_journal_transform_priority(
301 + FACETS *facets __maybe_unused,
302 + BUFFER *wb,
303 + FACETS_TRANSFORMATION_SCOPE scope __maybe_unused,
304 + void *data __maybe_unused)
305 +{
306 + if (scope == FACETS_TRANSFORM_FACET_SORT)
307 return;
308
309 const char *v = buffer_tostring(wb);
268 - if(*v && isdigit(*v)) {
310 + if (*v && isdigit(*v)) {
311 int priority = str2i(buffer_tostring(wb));
312 const char *name = syslog_priority_to_name(priority);
313 if (name) {
@@ -275,16 +317,21 @@ void netdata_systemd_journal_transform_priority(FACETS *facets __maybe_unused, B
317 }
318 }
319
278 -void netdata_systemd_journal_transform_errno(FACETS *facets __maybe_unused, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, void *data __maybe_unused) {
279 - if(scope == FACETS_TRANSFORM_FACET_SORT)
320 +void nd_sd_journal_transform_errno(
321 + FACETS *facets __maybe_unused,
322 + BUFFER *wb,
323 + FACETS_TRANSFORMATION_SCOPE scope __maybe_unused,
324 + void *data __maybe_unused)
325 +{
326 + if (scope == FACETS_TRANSFORM_FACET_SORT)
327 return;
328
329 const char *v = buffer_tostring(wb);
283 - if(*v && isdigit(*v)) {
330 + if (*v && isdigit(*v)) {
331 unsigned err_no = str2u(buffer_tostring(wb));
285 - if(err_no > 0 && err_no < sizeof(errno_map) / sizeof(*errno_map)) {
332 + if (err_no > 0 && err_no < sizeof(errno_map) / sizeof(*errno_map)) {
333 const char *name = errno_map[err_no];
287 - if(name) {
334 + if (name) {
335 buffer_flush(wb);
336 buffer_strcat(wb, name);
337 }
@@ -292,47 +339,54 @@ void netdata_systemd_journal_transform_errno(FACETS *facets __maybe_unused, BUFF
339 }
340 }
341
295 -// ----------------------------------------------------------------------------
296 -
342 DICTIONARY *boot_ids_to_first_ut = NULL;
343
299 -void netdata_systemd_journal_transform_boot_id(FACETS *facets __maybe_unused, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, void *data __maybe_unused) {
344 +void nd_sd_journal_transform_boot_id(
345 + FACETS *facets __maybe_unused,
346 + BUFFER *wb,
347 + FACETS_TRANSFORMATION_SCOPE scope __maybe_unused,
348 + void *data __maybe_unused)
349 +{
350 const char *boot_id = buffer_tostring(wb);
301 - if(*boot_id && isxdigit(*boot_id)) {
351 + if (*boot_id && isxdigit(*boot_id)) {
352 usec_t ut = UINT64_MAX;
353 usec_t *p_ut = dictionary_get(boot_ids_to_first_ut, boot_id);
304 - if(!p_ut) {
354 + if (!p_ut) {
355 #ifndef HAVE_SD_JOURNAL_RESTART_FIELDS
306 - struct journal_file *jf;
307 - dfe_start_read(journal_files_registry, jf) {
356 + struct nd_journal_file *njf;
357 + dfe_start_read(nd_journal_files_registry, njf)
358 + {
359 const char *files[2] = {
309 - [0] = jf_dfe.name,
310 - [1] = NULL,
360 + [0] = njf_dfe.name,
361 + [1] = NULL,
362 };
363
364 sd_journal *j = NULL;
365 int r = sd_journal_open_files(&j, files, ND_SD_JOURNAL_OPEN_FLAGS);
315 - if(r < 0 || !j) {
316 - internal_error(true, "JOURNAL: while looking for the first timestamp of boot_id '%s', "
317 - "sd_journal_open_files('%s') returned %d",
318 - boot_id, jf_dfe.name, r);
366 + if (r < 0 || !j) {
367 + internal_error(
368 + true,
369 + "JOURNAL: while looking for the first timestamp of boot_id '%s', "
370 + "sd_journal_open_files('%s') returned %d",
371 + boot_id,
372 + jf_dfe.name,
373 + r);
374 continue;
375 }
376
322 - ut = journal_file_update_annotation_boot_id(j, jf, boot_id);
377 + ut = nd_journal_file_update_annotation_boot_id(j, njf, boot_id);
378 sd_journal_close(j);
379 }
325 - dfe_done(jf);
380 + dfe_done(njf);
381 #endif
327 - }
328 - else
382 + } else
383 ut = *p_ut;
384
331 - if(ut && ut != UINT64_MAX) {
385 + if (ut && ut != UINT64_MAX) {
386 char buffer[RFC3339_MAX_LENGTH];
387 rfc3339_datetime_ut(buffer, sizeof(buffer), ut, 0, true);
388
335 - switch(scope) {
389 + switch (scope) {
390 default:
391 case FACETS_TRANSFORM_DATA:
392 case FACETS_TRANSFORM_VALUE:
@@ -350,12 +404,17 @@ void netdata_systemd_journal_transform_boot_id(FACETS *facets __maybe_unused, BU
404 }
405 }
406
353 -void netdata_systemd_journal_transform_uid(FACETS *facets __maybe_unused, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, void *data __maybe_unused) {
354 - if(scope == FACETS_TRANSFORM_FACET_SORT)
407 +void nd_sd_journal_transform_uid(
408 + FACETS *facets __maybe_unused,
409 + BUFFER *wb,
410 + FACETS_TRANSFORMATION_SCOPE scope __maybe_unused,
411 + void *data __maybe_unused)
412 +{
413 + if (scope == FACETS_TRANSFORM_FACET_SORT)
414 return;
415
416 const char *v = buffer_tostring(wb);
358 - if(*v && isdigit(*v)) {
417 + if (*v && isdigit(*v)) {
418 uid_t uid = str2i(buffer_tostring(wb));
419 CACHED_USERNAME cu = cached_username_get_by_uid(uid);
420 buffer_contents_replace(wb, string2str(cu.username), string_strlen(cu.username));
@@ -363,12 +422,17 @@ void netdata_systemd_journal_transform_uid(FACETS *facets __maybe_unused, BUFFER
422 }
423 }
424
366 -void netdata_systemd_journal_transform_gid(FACETS *facets __maybe_unused, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, void *data __maybe_unused) {
367 - if(scope == FACETS_TRANSFORM_FACET_SORT)
425 +void nd_sd_journal_transform_gid(
426 + FACETS *facets __maybe_unused,
427 + BUFFER *wb,
428 + FACETS_TRANSFORMATION_SCOPE scope __maybe_unused,
429 + void *data __maybe_unused)
430 +{
431 + if (scope == FACETS_TRANSFORM_FACET_SORT)
432 return;
433
434 const char *v = buffer_tostring(wb);
371 - if(*v && isdigit(*v)) {
435 + if (*v && isdigit(*v)) {
436 gid_t gid = str2i(buffer_tostring(wb));
437 CACHED_GROUPNAME cg = cached_groupname_get_by_gid(gid);
438 buffer_contents_replace(wb, string2str(cg.groupname), string_strlen(cg.groupname));
@@ -376,18 +440,22 @@ void netdata_systemd_journal_transform_gid(FACETS *facets __maybe_unused, BUFFER
440 }
441 }
442
379 -void netdata_systemd_journal_transform_cap_effective(FACETS *facets __maybe_unused, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, void *data __maybe_unused) {
380 - if(scope == FACETS_TRANSFORM_FACET_SORT)
443 +void nd_sd_journal_transform_cap_effective(
444 + FACETS *facets __maybe_unused,
445 + BUFFER *wb,
446 + FACETS_TRANSFORMATION_SCOPE scope __maybe_unused,
447 + void *data __maybe_unused)
448 +{
449 + if (scope == FACETS_TRANSFORM_FACET_SORT)
450 return;
451
452 const char *v = buffer_tostring(wb);
384 - if(*v && isdigit(*v)) {
453 + if (*v && isdigit(*v)) {
454 uint64_t cap = strtoul(buffer_tostring(wb), NULL, 16);
386 - if(cap) {
455 + if (cap) {
456 buffer_fast_strcat(wb, " (", 2);
457 for (size_t i = 0, added = 0; i < sizeof(linux_capabilities) / sizeof(linux_capabilities[0]); i++) {
458 if (linux_capabilities[i] && (cap & (1ULL << i))) {
390 -
459 if (added)
460 buffer_fast_strcat(wb, " | ", 3);
461
@@ -400,14 +468,19 @@ void netdata_systemd_journal_transform_cap_effective(FACETS *facets __maybe_unus
468 }
469 }
470
403 -void netdata_systemd_journal_transform_timestamp_usec(FACETS *facets __maybe_unused, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, void *data __maybe_unused) {
404 - if(scope == FACETS_TRANSFORM_FACET_SORT)
471 +void nd_sd_journal_transform_timestamp_usec(
472 + FACETS *facets __maybe_unused,
473 + BUFFER *wb,
474 + FACETS_TRANSFORMATION_SCOPE scope __maybe_unused,
475 + void *data __maybe_unused)
476 +{
477 + if (scope == FACETS_TRANSFORM_FACET_SORT)
478 return;
479
480 const char *v = buffer_tostring(wb);
408 - if(*v && isdigit(*v)) {
481 + if (*v && isdigit(*v)) {
482 uint64_t ut = str2ull(buffer_tostring(wb), NULL);
410 - if(ut) {
483 + if (ut) {
484 char buffer[RFC3339_MAX_LENGTH];
485 rfc3339_datetime_ut(buffer, sizeof(buffer), ut, 6, true);
486 buffer_sprintf(wb, " (%s)", buffer);
@@ -415,34 +488,38 @@ void netdata_systemd_journal_transform_timestamp_usec(FACETS *facets __maybe_unu
488 }
489 }
490
418 -// ----------------------------------------------------------------------------
419 -
420 -void netdata_systemd_journal_dynamic_row_id(FACETS *facets __maybe_unused, BUFFER *json_array, FACET_ROW_KEY_VALUE *rkv, FACET_ROW *row, void *data __maybe_unused) {
491 +void nd_sd_journal_dynamic_row_id(
492 + FACETS *facets __maybe_unused,
493 + BUFFER *json_array,
494 + FACET_ROW_KEY_VALUE *rkv,
495 + FACET_ROW *row,
496 + void *data __maybe_unused)
497 +{
498 FACET_ROW_KEY_VALUE *pid_rkv = dictionary_get(row->dict, "_PID");
499 const char *pid = pid_rkv ? buffer_tostring(pid_rkv->wb) : FACET_VALUE_UNSET;
500
501 const char *identifier = NULL;
502 FACET_ROW_KEY_VALUE *container_name_rkv = dictionary_get(row->dict, "CONTAINER_NAME");
426 - if(container_name_rkv && !container_name_rkv->empty)
503 + if (container_name_rkv && !container_name_rkv->empty)
504 identifier = buffer_tostring(container_name_rkv->wb);
505
429 - if(!identifier) {
506 + if (!identifier) {
507 FACET_ROW_KEY_VALUE *syslog_identifier_rkv = dictionary_get(row->dict, "SYSLOG_IDENTIFIER");
431 - if(syslog_identifier_rkv && !syslog_identifier_rkv->empty)
508 + if (syslog_identifier_rkv && !syslog_identifier_rkv->empty)
509 identifier = buffer_tostring(syslog_identifier_rkv->wb);
510
434 - if(!identifier) {
511 + if (!identifier) {
512 FACET_ROW_KEY_VALUE *comm_rkv = dictionary_get(row->dict, "_COMM");
436 - if(comm_rkv && !comm_rkv->empty)
513 + if (comm_rkv && !comm_rkv->empty)
514 identifier = buffer_tostring(comm_rkv->wb);
515 }
516 }
517
518 buffer_flush(rkv->wb);
519
443 - if(!identifier || !*identifier)
520 + if (!identifier || !*identifier)
521 buffer_strcat(rkv->wb, FACET_VALUE_UNSET);
445 - else if(!pid || !*pid)
522 + else if (!pid || !*pid)
523 buffer_sprintf(rkv->wb, "%s", identifier);
524 else
525 buffer_sprintf(rkv->wb, "%s[%s]", identifier, pid);
@@ -450,23 +527,22 @@ void netdata_systemd_journal_dynamic_row_id(FACETS *facets __maybe_unused, BUFFE
527 buffer_json_add_array_item_string(json_array, buffer_tostring(rkv->wb));
528 }
529
453 -
454 -// ----------------------------------------------------------------------------
455 -
530 struct message_id_info {
531 const char *msg;
532 };
533
534 static DICTIONARY *known_journal_messages_ids = NULL;
535
462 -#define msgid_into_dict(uuid, message) do { \
463 - i.msg = message; \
464 - dictionary_set(known_journal_messages_ids, uuid, &i, sizeof(i)); \
465 - } while(0)
536 +#define msgid_into_dict(uuid, message) \
537 + do { \
538 + i.msg = message; \
539 + dictionary_set(known_journal_messages_ids, uuid, &i, sizeof(i)); \
540 + } while (0)
541
467 -static void netdata_systemd_journal_message_ids_init(void) {
542 +static void nd_sd_journal_message_ids_init(void)
543 +{
544 known_journal_messages_ids = dictionary_create(DICT_OPTION_DONT_OVERWRITE_VALUE);
469 - struct message_id_info i = { 0 };
545 + struct message_id_info i = {0};
546
547 // systemd
548 // https://github.com/systemd/systemd/blob/main/catalog/systemd.catalog.in
@@ -623,14 +699,19 @@ static void netdata_systemd_journal_message_ids_init(void) {
699 msgid_into_dict("4fdf40816c124623a032b7fe73beacb8", "Netdata dynamic configuration");
700 }
701
626 -void netdata_systemd_journal_transform_message_id(FACETS *facets __maybe_unused, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, void *data __maybe_unused) {
702 +void nd_sd_journal_transform_message_id(
703 + FACETS *facets __maybe_unused,
704 + BUFFER *wb,
705 + FACETS_TRANSFORMATION_SCOPE scope __maybe_unused,
706 + void *data __maybe_unused)
707 +{
708 const char *message_id = buffer_tostring(wb);
709 struct message_id_info *i = dictionary_get(known_journal_messages_ids, message_id);
710
630 - if(!i)
711 + if (!i)
712 return;
713
633 - switch(scope) {
714 + switch (scope) {
715 default:
716 case FACETS_TRANSFORM_DATA:
717 case FACETS_TRANSFORM_VALUE:
@@ -646,20 +727,11 @@ void netdata_systemd_journal_transform_message_id(FACETS *facets __maybe_unused,
727 }
728 }
729
649 -// ----------------------------------------------------------------------------
650 -
651 -void netdata_systemd_journal_annotations_init(void) {
730 +void nd_sd_journal_annotations_init(void)
731 +{
732 cached_usernames_init();
733 cached_groupnames_init();
734 update_cached_host_users();
735 update_cached_host_groups();
656 - netdata_systemd_journal_message_ids_init();
736 + nd_sd_journal_message_ids_init();
737 }
658 -
659 -// ----------------------------------------------------------------------------
660 -
661 -//static void netdata_systemd_journal_rich_message(FACETS *facets __maybe_unused, BUFFER *json_array, FACET_ROW_KEY_VALUE *rkv, FACET_ROW *row __maybe_unused, void *data __maybe_unused) {
662 -// buffer_json_add_array_item_object(json_array);
663 -// buffer_json_member_add_string(json_array, "value", buffer_tostring(rkv->wb));
664 -// buffer_json_object_close(json_array);
665 -//}
src/collectors/systemd-journal.plugin/systemd-journal-dyncfg.c
+61 -51
@@ -4,7 +4,8 @@
4
5 #define JOURNAL_DIRECTORIES_JSON_NODE "journalDirectories"
6
7 -static bool is_directory(const char *dir) {
7 +static bool is_directory(const char *dir)
8 +{
9 struct stat statbuf;
10 if (stat(dir, &statbuf) != 0) {
11 // Error in stat() means the path probably doesn't exist or can't be accessed.
@@ -14,103 +15,106 @@ static bool is_directory(const char *dir) {
15 return S_ISDIR(statbuf.st_mode) ? true : false;
16 }
17
17 -static const char *is_valid_dir(const char *dir) {
18 - if(strcmp(dir, "/") == 0)
18 +static const char *is_valid_dir(const char *dir)
19 +{
20 + if (strcmp(dir, "/") == 0)
21 return "/ is not acceptable";
22
21 - if(!strstartswith(dir, "/"))
23 + if (!strstartswith(dir, "/"))
24 return "only directories starting with / are accepted";
25
24 - if(strstr(dir, "/./"))
26 + if (strstr(dir, "/./"))
27 return "directory contains /./";
28
27 - if(strstr(dir, "/../") || strendswith(dir, "/.."))
29 + if (strstr(dir, "/../") || strendswith(dir, "/.."))
30 return "directory contains /../";
31
30 - if(strstartswith(dir, "/dev/") || strcmp(dir, "/dev") == 0)
32 + if (strstartswith(dir, "/dev/") || strcmp(dir, "/dev") == 0)
33 return "directory contains /dev";
34
33 - if(strstartswith(dir, "/proc/") || strcmp(dir, "/proc") == 0)
35 + if (strstartswith(dir, "/proc/") || strcmp(dir, "/proc") == 0)
36 return "directory contains /proc";
37
36 - if(strstartswith(dir, "/sys/") || strcmp(dir, "/sys") == 0)
38 + if (strstartswith(dir, "/sys/") || strcmp(dir, "/sys") == 0)
39 return "directory contains /sys";
40
39 - if(strstartswith(dir, "/etc/") || strcmp(dir, "/etc") == 0)
41 + if (strstartswith(dir, "/etc/") || strcmp(dir, "/etc") == 0)
42 return "directory contains /etc";
43
42 - if(strstartswith(dir, "/lib/") || strcmp(dir, "/lib") == 0
43 - || strstartswith(dir, "/lib32/") || strcmp(dir, "/lib32") == 0
44 - || strstartswith(dir, "/lib64/") || strcmp(dir, "/lib64") == 0)
44 + if (strstartswith(dir, "/lib/") || strcmp(dir, "/lib") == 0 || strstartswith(dir, "/lib32/") ||
45 + strcmp(dir, "/lib32") == 0 || strstartswith(dir, "/lib64/") || strcmp(dir, "/lib64") == 0)
46 return "directory contains /lib";
47
48 return NULL;
49 }
50
50 -static int systemd_journal_directories_dyncfg_update(BUFFER *result, BUFFER *payload) {
51 - if(!payload || !buffer_strlen(payload))
51 +static int systemd_journal_directories_dyncfg_update(BUFFER *result, BUFFER *payload)
52 +{
53 + if (!payload || !buffer_strlen(payload))
54 return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, "empty payload received");
55
56 CLEAN_JSON_OBJECT *jobj = json_tokener_parse(buffer_tostring(payload));
55 - if(!jobj)
57 + if (!jobj)
58 return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, "cannot parse json payload");
59
60 struct json_object *journalDirectories;
61 json_object_object_get_ex(jobj, JOURNAL_DIRECTORIES_JSON_NODE, &journalDirectories);
62
63 if (json_object_get_type(journalDirectories) != json_type_array)
62 - return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST,
63 - "member " JOURNAL_DIRECTORIES_JSON_NODE " is not an array");
64 + return dyncfg_default_response(
65 + result, HTTP_RESP_BAD_REQUEST, "member " JOURNAL_DIRECTORIES_JSON_NODE " is not an array");
66
67 size_t n_directories = json_object_array_length(journalDirectories);
66 - if(n_directories > MAX_JOURNAL_DIRECTORIES)
68 + if (n_directories > MAX_JOURNAL_DIRECTORIES)
69 return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, "too many directories configured");
70
71 // validate the directories
70 - for(size_t i = 0; i < n_directories; i++) {
72 + for (size_t i = 0; i < n_directories; i++) {
73 struct json_object *dir = json_object_array_get_idx(journalDirectories, i);
74 const char *s = json_object_get_string(dir);
73 - if(s && *s) {
75 + if (s && *s) {
76 const char *msg = is_valid_dir(s);
75 - if(msg)
77 + if (msg)
78 return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, msg);
79 }
80 }
81
82 size_t added = 0, not_found = 0;
81 - for(size_t i = 0; i < n_directories; i++) {
83 + for (size_t i = 0; i < n_directories; i++) {
84 struct json_object *dir = json_object_array_get_idx(journalDirectories, i);
85 const char *s = json_object_get_string(dir);
84 - if(s && *s) {
86 + if (s && *s) {
87 string_freez(journal_directories[added].path);
88 journal_directories[added++].path = string_strdupz(s);
89
88 - if(!is_directory(s))
90 + if (!is_directory(s))
91 not_found++;
92 }
93 }
94
93 - if(!added)
95 + if (!added)
96 return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, "no directories in the payload");
97 else {
96 - for(size_t i = added; i < MAX_JOURNAL_DIRECTORIES; i++) {
98 + for (size_t i = added; i < MAX_JOURNAL_DIRECTORIES; i++) {
99 string_freez(journal_directories[i].path);
100 journal_directories[i].path = NULL;
101 }
102 }
103
102 - journal_watcher_restart();
104 + nd_journal_watcher_restart();
105
104 - return dyncfg_default_response(result, HTTP_RESP_OK, not_found ? "added, but some directories are not found in the filesystem" : "");
106 + return dyncfg_default_response(
107 + result, HTTP_RESP_OK, not_found ? "added, but some directories are not found in the filesystem" : "");
108 }
109
107 -static int systemd_journal_directories_dyncfg_get(BUFFER *wb) {
110 +static int systemd_journal_directories_dyncfg_get(BUFFER *wb)
111 +{
112 buffer_flush(wb);
113 buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_MINIFY);
114
115 buffer_json_member_add_array(wb, JOURNAL_DIRECTORIES_JSON_NODE);
112 - for(size_t i = 0; i < MAX_JOURNAL_DIRECTORIES ;i++) {
113 - if(!journal_directories[i].path)
116 + for (size_t i = 0; i < MAX_JOURNAL_DIRECTORIES; i++) {
117 + if (!journal_directories[i].path)
118 break;
119
120 buffer_json_add_array_item_string(wb, string2str(journal_directories[i].path));
@@ -121,36 +125,42 @@ static int systemd_journal_directories_dyncfg_get(BUFFER *wb) {
125 return HTTP_RESP_OK;
126 }
127
124 -static int systemd_journal_directories_dyncfg_cb(const char *transaction,
125 - const char *id,
126 - DYNCFG_CMDS cmd,
127 - const char *add_name __maybe_unused,
128 - BUFFER *payload,
129 - usec_t *stop_monotonic_ut __maybe_unused,
130 - bool *cancelled __maybe_unused,
131 - BUFFER *result,
132 - HTTP_ACCESS access __maybe_unused,
133 - const char *source __maybe_unused,
134 - void *data __maybe_unused) {
128 +static int systemd_journal_directories_dyncfg_cb(
129 + const char *transaction,
130 + const char *id,
131 + DYNCFG_CMDS cmd,
132 + const char *add_name __maybe_unused,
133 + BUFFER *payload,
134 + usec_t *stop_monotonic_ut __maybe_unused,
135 + bool *cancelled __maybe_unused,
136 + BUFFER *result,
137 + HTTP_ACCESS access __maybe_unused,
138 + const char *source __maybe_unused,
139 + void *data __maybe_unused)
140 +{
141 CLEAN_BUFFER *action = buffer_create(100, NULL);
142 dyncfg_cmds2buffer(cmd, action);
143
138 - if(cmd == DYNCFG_CMD_GET)
144 + if (cmd == DYNCFG_CMD_GET)
145 return systemd_journal_directories_dyncfg_get(result);
146
141 - if(cmd == DYNCFG_CMD_UPDATE)
147 + if (cmd == DYNCFG_CMD_UPDATE)
148 return systemd_journal_directories_dyncfg_update(result, payload);
149
144 - nd_log(NDLS_COLLECTORS, NDLP_ERR,
145 - "DYNCFG: unhandled transaction '%s', id '%s' cmd '%s', payload: %s",
146 - transaction, id, buffer_tostring(action), payload ? buffer_tostring(payload) : "");
150 + nd_log(
151 + NDLS_COLLECTORS,
152 + NDLP_ERR,
153 + "DYNCFG: unhandled transaction '%s', id '%s' cmd '%s', payload: %s",
154 + transaction,
155 + id,
156 + buffer_tostring(action),
157 + payload ? buffer_tostring(payload) : "");
158
159 return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, "the command is not handled by this plugin");
160 }
161
151 -// ----------------------------------------------------------------------------
152 -
153 -void systemd_journal_dyncfg_init(struct functions_evloop_globals *wg) {
162 +void nd_systemd_journal_dyncfg_init(struct functions_evloop_globals *wg)
163 +{
164 functions_evloop_dyncfg_add(
165 wg,
166 "systemd-journal:monitored-directories",
src/collectors/systemd-journal.plugin/systemd-journal-files.c
+356 -362
@@ -2,35 +2,37 @@
2
3 #include "systemd-internals.h"
4
5 -#define SYSTEMD_JOURNAL_MAX_SOURCE_LEN 64
5 +#define ND_SD_JOURNAL_MAX_SOURCE_LEN 64
6 #define VAR_LOG_JOURNAL_MAX_DEPTH 10
7
8 -struct journal_directory journal_directories[MAX_JOURNAL_DIRECTORIES] = { 0 };
9 -DICTIONARY *journal_files_registry = NULL;
8 +struct journal_directory journal_directories[MAX_JOURNAL_DIRECTORIES] = {0};
9 +DICTIONARY *nd_journal_files_registry = NULL;
10 DICTIONARY *used_hashes_registry = NULL;
11
12 static usec_t systemd_journal_session = 0;
13
14 -void buffer_json_journal_versions(BUFFER *wb) {
14 +void buffer_json_journal_versions(BUFFER *wb)
15 +{
16 buffer_json_member_add_object(wb, "versions");
17 {
17 - buffer_json_member_add_uint64(wb, "sources",
18 - systemd_journal_session + dictionary_version(journal_files_registry));
18 + buffer_json_member_add_uint64(
19 + wb, "sources", systemd_journal_session + dictionary_version(nd_journal_files_registry));
20 }
21 buffer_json_object_close(wb);
22 }
23
23 -static bool journal_sd_id128_parse(const char *in, sd_id128_t *ret) {
24 - while(isspace(*in))
24 +static bool journal_sd_id128_parse(const char *in, sd_id128_t *ret)
25 +{
26 + while (isspace(*in))
27 in++;
28
29 char uuid[33];
30 strncpyz(uuid, in, 32);
31 uuid[32] = '\0';
32
31 - if(strlen(uuid) == 32) {
33 + if (strlen(uuid) == 32) {
34 sd_id128_t read;
33 - if(sd_id128_from_string(uuid, &read) == 0) {
35 + if (sd_id128_from_string(uuid, &read) == 0) {
36 *ret = read;
37 return true;
38 }
@@ -39,74 +41,9 @@ static bool journal_sd_id128_parse(const char *in, sd_id128_t *ret) {
41 return false;
42 }
43
42 -//static void journal_file_get_header_from_journalctl(const char *filename, struct journal_file *jf) {
43 -// // unfortunately, our capabilities are not inheritted by journalctl
44 -// // so, it fails to give us the information we need.
45 -//
46 -// bool read_writer = false, read_head = false, read_tail = false;
47 -//
48 -// char cmd[FILENAME_MAX * 2];
49 -// snprintfz(cmd, sizeof(cmd), "journalctl --header --file '%s'", filename);
50 -// CLEAN_BUFFER *wb = run_command_and_get_output_to_buffer(cmd, 1024);
51 -// if(wb) {
52 -// const char *s = buffer_tostring(wb);
53 -//
54 -// const char *sequential_id_header = "Sequential Number ID:";
55 -// const char *sequential_id_data = strcasestr(s, sequential_id_header);
56 -// if(sequential_id_data) {
57 -// sequential_id_data += strlen(sequential_id_header);
58 -// if(journal_sd_id128_parse(sequential_id_data, &jf->first_writer_id))
59 -// read_writer = true;
60 -// }
61 -//
62 -// const char *head_sequential_number_header = "Head sequential number:";
63 -// const char *head_sequential_number_data = strcasestr(s, head_sequential_number_header);
64 -// if(head_sequential_number_data) {
65 -// head_sequential_number_data += strlen(head_sequential_number_header);
66 -//
67 -// while(isspace(*head_sequential_number_data))
68 -// head_sequential_number_data++;
69 -//
70 -// if(isdigit(*head_sequential_number_data)) {
71 -// jf->first_seqnum = strtoul(head_sequential_number_data, NULL, 10);
72 -// if(jf->first_seqnum)
73 -// read_head = true;
74 -// }
75 -// }
76 -//
77 -// const char *tail_sequential_number_header = "Tail sequential number:";
78 -// const char *tail_sequential_number_data = strcasestr(s, tail_sequential_number_header);
79 -// if(tail_sequential_number_data) {
80 -// tail_sequential_number_data += strlen(tail_sequential_number_header);
81 -//
82 -// while(isspace(*tail_sequential_number_data))
83 -// tail_sequential_number_data++;
84 -//
85 -// if(isdigit(*tail_sequential_number_data)) {
86 -// jf->last_seqnum = strtoul(tail_sequential_number_data, NULL, 10);
87 -// if(jf->last_seqnum)
88 -// read_tail = true;
89 -// }
90 -// }
91 -//
92 -// if(read_head && read_tail && jf->last_seqnum > jf->first_seqnum)
93 -// jf->messages_in_file = jf->last_seqnum - jf->first_seqnum;
94 -// }
95 -//
96 -// if(!jf->logged_journalctl_failure && (!read_head || !read_tail)) {
97 -//
98 -// nd_log(NDLS_COLLECTORS, NDLP_NOTICE,
99 -// "Failed to read %s%s%s from journalctl's output on filename '%s', using the command: %s",
100 -// read_writer?"":"writer id,",
101 -// read_head?"":"head id,",
102 -// read_tail?"":"tail id,",
103 -// filename, cmd);
104 -//
105 -// jf->logged_journalctl_failure = true;
106 -// }
107 -//}
108 -
109 -usec_t journal_file_update_annotation_boot_id(sd_journal *j, struct journal_file *jf __maybe_unused, const char *boot_id) {
44 +usec_t
45 +nd_journal_file_update_annotation_boot_id(sd_journal *j, struct nd_journal_file *njf __maybe_unused, const char *boot_id)
46 +{
47 usec_t ut = UINT64_MAX;
48 int r;
49
@@ -116,46 +53,59 @@ usec_t journal_file_update_annotation_boot_id(sd_journal *j, struct journal_file
53 sd_journal_flush_matches(j);
54
55 r = sd_journal_add_match(j, m, len);
119 - if(r < 0) {
56 + if (r < 0) {
57 errno = -r;
121 - internal_error(true,
122 - "JOURNAL: while looking for the first timestamp of boot_id '%s', "
123 - "sd_journal_add_match('%s') on file '%s' returned %d",
124 - boot_id, m, jf->filename, r);
58 + internal_error(
59 + true,
60 + "JOURNAL: while looking for the first timestamp of boot_id '%s', "
61 + "sd_journal_add_match('%s') on file '%s' returned %d",
62 + boot_id,
63 + m,
64 + njf->filename,
65 + r);
66 return UINT64_MAX;
67 }
68
69 r = sd_journal_seek_head(j);
129 - if(r < 0) {
70 + if (r < 0) {
71 errno = -r;
131 - internal_error(true,
132 - "JOURNAL: while looking for the first timestamp of boot_id '%s', "
133 - "sd_journal_seek_head() on file '%s' returned %d",
134 - boot_id, jf->filename, r);
72 + internal_error(
73 + true,
74 + "JOURNAL: while looking for the first timestamp of boot_id '%s', "
75 + "sd_journal_seek_head() on file '%s' returned %d",
76 + boot_id,
77 + njf->filename,
78 + r);
79 return UINT64_MAX;
80 }
81
82 r = sd_journal_next(j);
139 - if(r < 0) {
83 + if (r < 0) {
84 errno = -r;
141 - internal_error(true,
142 - "JOURNAL: while looking for the first timestamp of boot_id '%s', "
143 - "sd_journal_next() on file '%s' returned %d",
144 - boot_id, jf->filename, r);
85 + internal_error(
86 + true,
87 + "JOURNAL: while looking for the first timestamp of boot_id '%s', "
88 + "sd_journal_next() on file '%s' returned %d",
89 + boot_id,
90 + njf->filename,
91 + r);
92 return UINT64_MAX;
93 }
94
95 r = sd_journal_get_realtime_usec(j, &ut);
149 - if(r < 0 || !ut || ut == UINT64_MAX) {
96 + if (r < 0 || !ut || ut == UINT64_MAX) {
97 errno = -r;
151 - internal_error(r != -EADDRNOTAVAIL,
152 - "JOURNAL: while looking for the first timestamp of boot_id '%s', "
153 - "sd_journal_get_realtime_usec() on file '%s' returned %d",
154 - boot_id, jf->filename, r);
98 + internal_error(
99 + r != -EADDRNOTAVAIL,
100 + "JOURNAL: while looking for the first timestamp of boot_id '%s', "
101 + "sd_journal_get_realtime_usec() on file '%s' returned %d",
102 + boot_id,
103 + njf->filename,
104 + r);
105 return UINT64_MAX;
106 }
107
158 - if(ut && ut != UINT64_MAX) {
108 + if (ut && ut != UINT64_MAX) {
109 dictionary_set(boot_ids_to_first_ut, boot_id, &ut, sizeof(ut));
110 return ut;
111 }
@@ -163,17 +113,21 @@ usec_t journal_file_update_annotation_boot_id(sd_journal *j, struct journal_file
113 return UINT64_MAX;
114 }
115
166 -static void journal_file_get_boot_id_annotations(sd_journal *j __maybe_unused, struct journal_file *jf __maybe_unused) {
116 +static void
117 +nd_journal_file_get_boot_id_annotations(sd_journal *j __maybe_unused, struct nd_journal_file *njf __maybe_unused)
118 +{
119 #ifdef HAVE_SD_JOURNAL_RESTART_FIELDS
120 sd_journal_flush_matches(j);
121
122 int r = sd_journal_query_unique(j, "_BOOT_ID");
123 if (r < 0) {
124 errno = -r;
173 - internal_error(true,
174 - "JOURNAL: while querying for the unique _BOOT_ID values, "
175 - "sd_journal_query_unique() on file '%s' returned %d",
176 - jf->filename, r);
125 + internal_error(
126 + true,
127 + "JOURNAL: while querying for the unique _BOOT_ID values, "
128 + "sd_journal_query_unique() on file '%s' returned %d",
129 + njf->filename,
130 + r);
131 errno = -r;
132 return;
133 }
@@ -183,14 +137,15 @@ static void journal_file_get_boot_id_annotations(sd_journal *j __maybe_unused, s
137
138 DICTIONARY *dict = dictionary_create(DICT_OPTION_SINGLE_THREADED);
139
186 - SD_JOURNAL_FOREACH_UNIQUE(j, data, data_length) {
140 + SD_JOURNAL_FOREACH_UNIQUE(j, data, data_length)
141 + {
142 const char *key, *value;
143 size_t key_length, value_length;
144
190 - if(!parse_journal_field(data, data_length, &key, &key_length, &value, &value_length))
145 + if (!parse_journal_field(data, data_length, &key, &key_length, &value, &value_length))
146 continue;
147
193 - if(value_length != 32)
148 + if (value_length != 32)
149 continue;
150
151 char buf[33];
@@ -201,8 +156,9 @@ static void journal_file_get_boot_id_annotations(sd_journal *j __maybe_unused, s
156 }
157
158 void *nothing;
204 - dfe_start_read(dict, nothing){
205 - journal_file_update_annotation_boot_id(j, jf, nothing_dfe.name);
159 + dfe_start_read(dict, nothing)
160 + {
161 + nd_journal_file_update_annotation_boot_id(j, njf, nothing_dfe.name);
162 }
163 dfe_done(nothing);
164
@@ -210,30 +166,32 @@ static void journal_file_get_boot_id_annotations(sd_journal *j __maybe_unused, s
166 #endif
167 }
168
213 -void journal_file_update_header(const char *filename, struct journal_file *jf) {
214 - if(jf->last_scan_header_vs_last_modified_ut == jf->file_last_modified_ut)
169 +void nd_journal_file_update_header(const char *filename, struct nd_journal_file *njf)
170 +{
171 + if (njf->last_scan_header_vs_last_modified_ut == njf->file_last_modified_ut)
172 return;
173
174 fstat_cache_enable_on_thread();
175
176 const char *files[2] = {
220 - [0] = filename,
221 - [1] = NULL,
177 + [0] = filename,
178 + [1] = NULL,
179 };
180
181 sd_journal *j = NULL;
225 - if(sd_journal_open_files(&j, files, ND_SD_JOURNAL_OPEN_FLAGS) < 0 || !j) {
182 + if (sd_journal_open_files(&j, files, ND_SD_JOURNAL_OPEN_FLAGS) < 0 || !j) {
183 netdata_log_error("JOURNAL: cannot open file '%s' to update msg_ut", filename);
184 fstat_cache_disable_on_thread();
185
229 - if(!jf->logged_failure) {
230 - netdata_log_error("cannot open journal file '%s', using file timestamps to understand time-frame.", filename);
231 - jf->logged_failure = true;
186 + if (!njf->logged_failure) {
187 + netdata_log_error(
188 + "cannot open journal file '%s', using file timestamps to understand time-frame.", filename);
189 + njf->logged_failure = true;
190 }
191
234 - jf->msg_first_ut = 0;
235 - jf->msg_last_ut = jf->file_last_modified_ut;
236 - jf->last_scan_header_vs_last_modified_ut = jf->file_last_modified_ut;
192 + njf->msg_first_ut = 0;
193 + njf->msg_last_ut = njf->file_last_modified_ut;
194 + njf->last_scan_header_vs_last_modified_ut = njf->file_last_modified_ut;
195 return;
196 }
197
@@ -241,13 +199,14 @@ void journal_file_update_header(const char *filename, struct journal_file *jf) {
199 uint64_t first_seqnum = 0, last_seqnum = 0;
200 sd_id128_t first_writer_id = SD_ID128_NULL, last_writer_id = SD_ID128_NULL;
201
244 - if(sd_journal_seek_head(j) < 0 || sd_journal_next(j) < 0 || sd_journal_get_realtime_usec(j, &first_ut) < 0 || !first_ut) {
202 + if (sd_journal_seek_head(j) < 0 || sd_journal_next(j) < 0 || sd_journal_get_realtime_usec(j, &first_ut) < 0 ||
203 + !first_ut) {
204 internal_error(true, "cannot find the timestamp of the first message in '%s'", filename);
205 first_ut = 0;
206 }
207 #ifdef HAVE_SD_JOURNAL_GET_SEQNUM
208 else {
250 - if(sd_journal_get_seqnum(j, &first_seqnum, &first_writer_id) < 0 || !first_seqnum) {
209 + if (sd_journal_get_seqnum(j, &first_seqnum, &first_writer_id) < 0 || !first_seqnum) {
210 internal_error(true, "cannot find the first seqnums of the first message in '%s'", filename);
211 first_seqnum = 0;
212 memset(&first_writer_id, 0, sizeof(first_writer_id));
@@ -255,13 +214,14 @@ void journal_file_update_header(const char *filename, struct journal_file *jf) {
214 }
215 #endif
216
258 - if(sd_journal_seek_tail(j) < 0 || sd_journal_previous(j) < 0 || sd_journal_get_realtime_usec(j, &last_ut) < 0 || !last_ut) {
217 + if (sd_journal_seek_tail(j) < 0 || sd_journal_previous(j) < 0 || sd_journal_get_realtime_usec(j, &last_ut) < 0 ||
218 + !last_ut) {
219 internal_error(true, "cannot find the timestamp of the last message in '%s'", filename);
260 - last_ut = jf->file_last_modified_ut;
220 + last_ut = njf->file_last_modified_ut;
221 }
222 #ifdef HAVE_SD_JOURNAL_GET_SEQNUM
223 else {
264 - if(sd_journal_get_seqnum(j, &last_seqnum, &last_writer_id) < 0 || !last_seqnum) {
224 + if (sd_journal_get_seqnum(j, &last_seqnum, &last_writer_id) < 0 || !last_seqnum) {
225 internal_error(true, "cannot find the last seqnums of the first message in '%s'", filename);
226 last_seqnum = 0;
227 memset(&last_writer_id, 0, sizeof(last_writer_id));
@@ -269,34 +229,33 @@ void journal_file_update_header(const char *filename, struct journal_file *jf) {
229 }
230 #endif
231
272 - if(first_ut > last_ut) {
232 + if (first_ut > last_ut) {
233 internal_error(true, "timestamps are flipped in file '%s'", filename);
234 usec_t t = first_ut;
235 first_ut = last_ut;
236 last_ut = t;
237 }
238
279 - if(!first_seqnum || !first_ut) {
239 + if (!first_seqnum || !first_ut) {
240 // extract these from the filename - if possible
241
242 const char *at = strchr(filename, '@');
283 - if(at) {
243 + if (at) {
244 const char *dash_seqnum = strchr(at + 1, '-');
285 - if(dash_seqnum) {
245 + if (dash_seqnum) {
246 const char *dash_first_msg_ut = strchr(dash_seqnum + 1, '-');
287 - if(dash_first_msg_ut) {
247 + if (dash_first_msg_ut) {
248 const char *dot_journal = NULL;
289 - if(is_journal_file(filename, -1, &dot_journal) && dot_journal && dot_journal > dash_first_msg_ut) {
290 - if(dash_seqnum - at - 1 == 32 &&
291 - dash_first_msg_ut - dash_seqnum - 1 == 16 &&
249 + if (is_journal_file(filename, -1, &dot_journal) && dot_journal && dot_journal > dash_first_msg_ut) {
250 + if (dash_seqnum - at - 1 == 32 && dash_first_msg_ut - dash_seqnum - 1 == 16 &&
251 dot_journal - dash_first_msg_ut - 1 == 16) {
252 sd_id128_t writer;
294 - if(journal_sd_id128_parse(at + 1, &writer)) {
253 + if (journal_sd_id128_parse(at + 1, &writer)) {
254 char *endptr = NULL;
255 uint64_t seqnum = strtoul(dash_seqnum + 1, &endptr, 16);
297 - if(endptr == dash_first_msg_ut) {
256 + if (endptr == dash_first_msg_ut) {
257 uint64_t ts = strtoul(dash_first_msg_ut + 1, &endptr, 16);
299 - if(endptr == dot_journal) {
258 + if (endptr == dot_journal) {
259 first_seqnum = seqnum;
260 first_writer_id = writer;
261 first_ut = ts;
@@ -310,51 +269,45 @@ void journal_file_update_header(const char *filename, struct journal_file *jf) {
269 }
270 }
271
313 - jf->first_seqnum = first_seqnum;
314 - jf->last_seqnum = last_seqnum;
315 -
316 - jf->first_writer_id = first_writer_id;
317 - jf->last_writer_id = last_writer_id;
272 + njf->first_seqnum = first_seqnum;
273 + njf->last_seqnum = last_seqnum;
274
319 - jf->msg_first_ut = first_ut;
320 - jf->msg_last_ut = last_ut;
275 + njf->first_writer_id = first_writer_id;
276 + njf->last_writer_id = last_writer_id;
277
322 - if(!jf->msg_last_ut)
323 - jf->msg_last_ut = jf->file_last_modified_ut;
278 + njf->msg_first_ut = first_ut;
279 + njf->msg_last_ut = last_ut;
280
325 - if(last_seqnum > first_seqnum) {
326 - if(!sd_id128_equal(first_writer_id, last_writer_id)) {
327 - jf->messages_in_file = 0;
328 - nd_log(NDLS_COLLECTORS, NDLP_NOTICE,
329 - "The writers of the first and the last message in file '%s' differ."
330 - , filename);
331 - }
332 - else
333 - jf->messages_in_file = last_seqnum - first_seqnum + 1;
334 - }
335 - else
336 - jf->messages_in_file = 0;
281 + if (!njf->msg_last_ut)
282 + njf->msg_last_ut = njf->file_last_modified_ut;
283
338 -// if(!jf->messages_in_file)
339 -// journal_file_get_header_from_journalctl(filename, jf);
284 + if (last_seqnum > first_seqnum) {
285 + if (!sd_id128_equal(first_writer_id, last_writer_id)) {
286 + njf->messages_in_file = 0;
287 + nd_log(
288 + NDLS_COLLECTORS,
289 + NDLP_NOTICE,
290 + "The writers of the first and the last message in file '%s' differ.",
291 + filename);
292 + } else
293 + njf->messages_in_file = last_seqnum - first_seqnum + 1;
294 + } else
295 + njf->messages_in_file = 0;
296
341 - journal_file_get_boot_id_annotations(j, jf);
297 + nd_journal_file_get_boot_id_annotations(j, njf);
298 sd_journal_close(j);
299 fstat_cache_disable_on_thread();
300
345 - jf->last_scan_header_vs_last_modified_ut = jf->file_last_modified_ut;
346 -
347 -// nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
348 -// "Journal file header updated '%s'",
349 -// jf->filename);
301 + njf->last_scan_header_vs_last_modified_ut = njf->file_last_modified_ut;
302 }
303
352 -static STRING *string_strdupz_source(const char *s, const char *e, size_t max_len, const char *prefix) {
304 +static STRING *string_strdupz_source(const char *s, const char *e, size_t max_len, const char *prefix)
305 +{
306 char buf[max_len];
307 size_t len;
308 char *dst = buf;
309
357 - if(prefix) {
310 + if (prefix) {
311 len = strlen(prefix);
312 memcpy(buf, prefix, len);
313 dst = &buf[len];
@@ -362,130 +315,138 @@ static STRING *string_strdupz_source(const char *s, const char *e, size_t max_le
315 }
316
317 len = e - s;
365 - if(len >= max_len)
318 + if (len >= max_len)
319 len = max_len - 1;
320 memcpy(dst, s, len);
321 dst[len] = '\0';
322 buf[max_len - 1] = '\0';
323
371 - for(size_t i = 0; buf[i] ;i++)
372 - if(!is_netdata_api_valid_character(buf[i])) buf[i] = '_';
324 + for (size_t i = 0; buf[i]; i++)
325 + if (!is_netdata_api_valid_character(buf[i]))
326 + buf[i] = '_';
327
328 return string_strdupz(buf);
329 }
330
377 -static void files_registry_insert_cb(const DICTIONARY_ITEM *item, void *value, void *data __maybe_unused) {
378 - struct journal_file *jf = value;
379 - jf->filename = dictionary_acquired_item_name(item);
380 - jf->filename_len = strlen(jf->filename);
381 - jf->source_type = SDJF_ALL;
331 +static void files_registry_insert_cb(const DICTIONARY_ITEM *item, void *value, void *data __maybe_unused)
332 +{
333 + struct nd_journal_file *njf = value;
334 + njf->filename = dictionary_acquired_item_name(item);
335 + njf->filename_len = strlen(njf->filename);
336 + njf->source_type = ND_SD_JF_ALL;
337
338 // based on the filename
339 // decide the source to show to the user
385 - const char *s = strrchr(jf->filename, '/');
386 - if(s) {
387 - if(strstr(jf->filename, "/remote/")) {
388 - jf->source_type |= SDJF_REMOTE_ALL;
340 + const char *s = strrchr(njf->filename, '/');
341 + if (s) {
342 + if (strstr(njf->filename, "/remote/")) {
343 + njf->source_type |= ND_SD_JF_REMOTE_ALL;
344
390 - if(strncmp(s, "/remote-", 8) == 0) {
345 + if (strncmp(s, "/remote-", 8) == 0) {
346 s = &s[8]; // skip "/remote-"
347
348 char *e = strchr(s, '@');
394 - if(!e)
349 + if (!e)
350 is_journal_file(s, -1, (const char **)&e);
351
397 - if(e) {
352 + if (e) {
353 const char *d = s;
399 - for(; d < e && (isdigit(*d) || *d == '.' || *d == ':') ; d++) ;
400 - if(d == e) {
354 + for (; d < e && (isdigit(*d) || *d == '.' || *d == ':'); d++)
355 + ;
356 + if (d == e) {
357 // a valid IP address
358 char ip[e - s + 1];
359 memcpy(ip, s, e - s);
360 ip[e - s] = '\0';
405 - char buf[SYSTEMD_JOURNAL_MAX_SOURCE_LEN];
406 - if(ip_to_hostname(ip, buf, sizeof(buf)))
407 - jf->source = string_strdupz_source(buf, &buf[strlen(buf)], SYSTEMD_JOURNAL_MAX_SOURCE_LEN, "remote-");
361 + char buf[ND_SD_JOURNAL_MAX_SOURCE_LEN];
362 + if (ip_to_hostname(ip, buf, sizeof(buf)))
363 + njf->source =
364 + string_strdupz_source(buf, &buf[strlen(buf)], ND_SD_JOURNAL_MAX_SOURCE_LEN, "remote-");
365 else {
366 internal_error(true, "Cannot find the hostname for IP '%s'", ip);
410 - jf->source = string_strdupz_source(s, e, SYSTEMD_JOURNAL_MAX_SOURCE_LEN, "remote-");
367 + njf->source = string_strdupz_source(s, e, ND_SD_JOURNAL_MAX_SOURCE_LEN, "remote-");
368 }
412 - }
413 - else
414 - jf->source = string_strdupz_source(s, e, SYSTEMD_JOURNAL_MAX_SOURCE_LEN, "remote-");
369 + } else
370 + njf->source = string_strdupz_source(s, e, ND_SD_JOURNAL_MAX_SOURCE_LEN, "remote-");
371 }
372 }
417 - }
418 - else {
419 - jf->source_type |= SDJF_LOCAL_ALL;
373 + } else {
374 + njf->source_type |= ND_SD_JF_LOCAL_ALL;
375
376 const char *t = s - 1;
422 - while(t >= jf->filename && *t != '.' && *t != '/')
377 + while (t >= njf->filename && *t != '.' && *t != '/')
378 t--;
379
425 - if(t >= jf->filename && *t == '.') {
426 - jf->source_type |= SDJF_LOCAL_NAMESPACE;
427 - jf->source = string_strdupz_source(t + 1, s, SYSTEMD_JOURNAL_MAX_SOURCE_LEN, "namespace-");
428 - }
429 - else if(strncmp(s, "/system", 7) == 0)
430 - jf->source_type |= SDJF_LOCAL_SYSTEM;
380 + if (t >= njf->filename && *t == '.') {
381 + njf->source_type |= ND_SD_JF_LOCAL_NAMESPACE;
382 + njf->source = string_strdupz_source(t + 1, s, ND_SD_JOURNAL_MAX_SOURCE_LEN, "namespace-");
383 + } else if (strncmp(s, "/system", 7) == 0)
384 + njf->source_type |= ND_SD_JF_LOCAL_SYSTEM;
385
432 - else if(strncmp(s, "/user", 5) == 0)
433 - jf->source_type |= SDJF_LOCAL_USER;
386 + else if (strncmp(s, "/user", 5) == 0)
387 + njf->source_type |= ND_SD_JF_LOCAL_USER;
388
389 else
436 - jf->source_type |= SDJF_LOCAL_OTHER;
390 + njf->source_type |= ND_SD_JF_LOCAL_OTHER;
391 }
438 - }
439 - else
440 - jf->source_type |= SDJF_LOCAL_ALL | SDJF_LOCAL_OTHER;
392 + } else
393 + njf->source_type |= ND_SD_JF_LOCAL_ALL | ND_SD_JF_LOCAL_OTHER;
394
442 - jf->msg_last_ut = jf->file_last_modified_ut;
395 + njf->msg_last_ut = njf->file_last_modified_ut;
396
444 - nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
445 - "Journal file added to the journal files registry: '%s'",
446 - jf->filename);
397 + nd_log(NDLS_COLLECTORS, NDLP_DEBUG, "Journal file added to the journal files registry: '%s'", njf->filename);
398 }
399
449 -static bool files_registry_conflict_cb(const DICTIONARY_ITEM *item __maybe_unused, void *old_value, void *new_value, void *data __maybe_unused) {
450 - struct journal_file *jf = old_value;
451 - struct journal_file *njf = new_value;
452 -
453 - if(njf->last_scan_monotonic_ut > jf->last_scan_monotonic_ut)
454 - jf->last_scan_monotonic_ut = njf->last_scan_monotonic_ut;
400 +static bool files_registry_conflict_cb(
401 + const DICTIONARY_ITEM *item __maybe_unused,
402 + void *old_value,
403 + void *new_value,
404 + void *data __maybe_unused)
405 +{
406 + struct nd_journal_file *njf_old = old_value;
407 + struct nd_journal_file *njf_new = new_value;
408
456 - if(njf->file_last_modified_ut > jf->file_last_modified_ut) {
457 - jf->file_last_modified_ut = njf->file_last_modified_ut;
458 - jf->size = njf->size;
409 + if (njf_new->last_scan_monotonic_ut > njf_old->last_scan_monotonic_ut)
410 + njf_old->last_scan_monotonic_ut = njf_new->last_scan_monotonic_ut;
411
460 - jf->msg_last_ut = jf->file_last_modified_ut;
412 + if (njf_new->file_last_modified_ut > njf_old->file_last_modified_ut) {
413 + njf_old->file_last_modified_ut = njf_new->file_last_modified_ut;
414 + njf_old->size = njf_new->size;
415
462 -// nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
463 -// "Journal file updated to the journal files registry '%s'",
464 -// jf->filename);
416 + njf_old->msg_last_ut = njf_old->file_last_modified_ut;
417 }
418
419 return false;
420 }
421
470 -struct journal_file_source {
422 +struct nd_journal_file_source {
423 usec_t first_ut;
424 usec_t last_ut;
425 size_t count;
426 uint64_t size;
427 };
428
477 -#define print_duration(dst, dst_len, pos, remaining, duration, one, many, printed) do { \
478 - if((remaining) > (duration)) { \
479 - uint64_t _count = (remaining) / (duration); \
480 - uint64_t _rem = (remaining) - (_count * (duration)); \
481 - (pos) += snprintfz(&(dst)[pos], (dst_len) - (pos), "%s%s%"PRIu64" %s", (printed) ? ", " : "", _rem ? "" : "and ", _count, _count > 1 ? (many) : (one)); \
482 - (remaining) = _rem; \
483 - (printed) = true; \
484 - } \
485 -} while(0)
486 -
487 -static int journal_file_to_json_array_cb(const DICTIONARY_ITEM *item, void *entry, void *data) {
488 - struct journal_file_source *jfs = entry;
429 +#define print_duration(dst, dst_len, pos, remaining, duration, one, many, printed) \
430 + do { \
431 + if ((remaining) > (duration)) { \
432 + uint64_t _count = (remaining) / (duration); \
433 + uint64_t _rem = (remaining) - (_count * (duration)); \
434 + (pos) += snprintfz( \
435 + &(dst)[pos], \
436 + (dst_len) - (pos), \
437 + "%s%s%" PRIu64 " %s", \
438 + (printed) ? ", " : "", \
439 + _rem ? "" : "and ", \
440 + _count, \
441 + _count > 1 ? (many) : (one)); \
442 + (remaining) = _rem; \
443 + (printed) = true; \
444 + } \
445 + } while (0)
446 +
447 +static int nd_journal_file_to_json_array_cb(const DICTIONARY_ITEM *item, void *entry, void *data)
448 +{
449 + struct nd_journal_file_source *nd_jfs = entry;
450 BUFFER *wb = data;
451
452 const char *name = dictionary_acquired_item_name(item);
@@ -493,15 +454,24 @@ static int journal_file_to_json_array_cb(const DICTIONARY_ITEM *item, void *entr
454 buffer_json_add_array_item_object(wb);
455 {
456 char size_for_humans[128];
496 - size_snprintf(size_for_humans, sizeof(size_for_humans), jfs->size, "B", false);
457 + size_snprintf(size_for_humans, sizeof(size_for_humans), nd_jfs->size, "B", false);
458
459 char duration_for_humans[128];
499 - duration_snprintf(duration_for_humans, sizeof(duration_for_humans),
500 - (time_t)((jfs->last_ut - jfs->first_ut) / USEC_PER_SEC), "s", true);
460 + duration_snprintf(
461 + duration_for_humans,
462 + sizeof(duration_for_humans),
463 + (time_t)((nd_jfs->last_ut - nd_jfs->first_ut) / USEC_PER_SEC),
464 + "s",
465 + true);
466
467 char info[1024];
503 - snprintfz(info, sizeof(info), "%zu files, with a total size of %s, covering %s",
504 - jfs->count, size_for_humans, duration_for_humans);
468 + snprintfz(
469 + info,
470 + sizeof(info),
471 + "%zu files, with a total size of %s, covering %s",
472 + nd_jfs->count,
473 + size_for_humans,
474 + duration_for_humans);
475
476 buffer_json_member_add_string(wb, "id", name);
477 buffer_json_member_add_string(wb, "name", name);
@@ -513,63 +483,73 @@ static int journal_file_to_json_array_cb(const DICTIONARY_ITEM *item, void *entr
483 return 1;
484 }
485
516 -static bool journal_file_merge_sizes(const DICTIONARY_ITEM *item __maybe_unused, void *old_value, void *new_value , void *data __maybe_unused) {
517 - struct journal_file_source *jfs = old_value, *njfs = new_value;
486 +static bool nd_journal_file_merge_sizes(
487 + const DICTIONARY_ITEM *item __maybe_unused,
488 + void *old_value,
489 + void *new_value,
490 + void *data __maybe_unused)
491 +{
492 + struct nd_journal_file_source *jfs = old_value, *njfs = new_value;
493 jfs->count += njfs->count;
494 jfs->size += njfs->size;
495
521 - if(njfs->first_ut && njfs->first_ut < jfs->first_ut)
496 + if (njfs->first_ut && njfs->first_ut < jfs->first_ut)
497 jfs->first_ut = njfs->first_ut;
498
524 - if(njfs->last_ut && njfs->last_ut > jfs->last_ut)
499 + if (njfs->last_ut && njfs->last_ut > jfs->last_ut)
500 jfs->last_ut = njfs->last_ut;
501
502 return false;
503 }
504
530 -void available_journal_file_sources_to_json_array(BUFFER *wb) {
531 - DICTIONARY *dict = dictionary_create(DICT_OPTION_SINGLE_THREADED|DICT_OPTION_NAME_LINK_DONT_CLONE|DICT_OPTION_DONT_OVERWRITE_VALUE);
532 - dictionary_register_conflict_callback(dict, journal_file_merge_sizes, NULL);
533 -
534 - struct journal_file_source t = { 0 };
535 -
536 - struct journal_file *jf;
537 - dfe_start_read(journal_files_registry, jf) {
538 - t.first_ut = jf->msg_first_ut;
539 - t.last_ut = jf->msg_last_ut;
540 - t.count = 1;
541 - t.size = jf->size;
542 -
543 - dictionary_set(dict, SDJF_SOURCE_ALL_NAME, &t, sizeof(t));
544 -
545 - if(jf->source_type & SDJF_LOCAL_ALL)
546 - dictionary_set(dict, SDJF_SOURCE_LOCAL_NAME, &t, sizeof(t));
547 - if(jf->source_type & SDJF_LOCAL_SYSTEM)
548 - dictionary_set(dict, SDJF_SOURCE_LOCAL_SYSTEM_NAME, &t, sizeof(t));
549 - if(jf->source_type & SDJF_LOCAL_USER)
550 - dictionary_set(dict, SDJF_SOURCE_LOCAL_USERS_NAME, &t, sizeof(t));
551 - if(jf->source_type & SDJF_LOCAL_OTHER)
552 - dictionary_set(dict, SDJF_SOURCE_LOCAL_OTHER_NAME, &t, sizeof(t));
553 - if(jf->source_type & SDJF_LOCAL_NAMESPACE)
554 - dictionary_set(dict, SDJF_SOURCE_NAMESPACES_NAME, &t, sizeof(t));
555 - if(jf->source_type & SDJF_REMOTE_ALL)
556 - dictionary_set(dict, SDJF_SOURCE_REMOTES_NAME, &t, sizeof(t));
557 - if(jf->source)
558 - dictionary_set(dict, string2str(jf->source), &t, sizeof(t));
505 +void available_journal_file_sources_to_json_array(BUFFER *wb)
506 +{
507 + DICTIONARY *dict = dictionary_create(
508 + DICT_OPTION_SINGLE_THREADED | DICT_OPTION_NAME_LINK_DONT_CLONE | DICT_OPTION_DONT_OVERWRITE_VALUE);
509 + dictionary_register_conflict_callback(dict, nd_journal_file_merge_sizes, NULL);
510 +
511 + struct nd_journal_file_source njfs_tmp = {0};
512 +
513 + struct nd_journal_file *njf;
514 + dfe_start_read(nd_journal_files_registry, njf)
515 + {
516 + njfs_tmp.first_ut = njf->msg_first_ut;
517 + njfs_tmp.last_ut = njf->msg_last_ut;
518 + njfs_tmp.count = 1;
519 + njfs_tmp.size = njf->size;
520 +
521 + dictionary_set(dict, ND_SD_JF_SOURCE_ALL_NAME, &njfs_tmp, sizeof(njfs_tmp));
522 +
523 + if (njf->source_type & ND_SD_JF_LOCAL_ALL)
524 + dictionary_set(dict, ND_SD_JF_SOURCE_LOCAL_NAME, &njfs_tmp, sizeof(njfs_tmp));
525 + if (njf->source_type & ND_SD_JF_LOCAL_SYSTEM)
526 + dictionary_set(dict, ND_SD_JF_SOURCE_LOCAL_SYSTEM_NAME, &njfs_tmp, sizeof(njfs_tmp));
527 + if (njf->source_type & ND_SD_JF_LOCAL_USER)
528 + dictionary_set(dict, ND_SD_JF_SOURCE_LOCAL_USERS_NAME, &njfs_tmp, sizeof(njfs_tmp));
529 + if (njf->source_type & ND_SD_JF_LOCAL_OTHER)
530 + dictionary_set(dict, ND_SD_JF_SOURCE_LOCAL_OTHER_NAME, &njfs_tmp, sizeof(njfs_tmp));
531 + if (njf->source_type & ND_SD_JF_LOCAL_NAMESPACE)
532 + dictionary_set(dict, ND_SD_JF_SOURCE_NAMESPACES_NAME, &njfs_tmp, sizeof(njfs_tmp));
533 + if (njf->source_type & ND_SD_JF_REMOTE_ALL)
534 + dictionary_set(dict, ND_SD_JF_SOURCE_REMOTES_NAME, &njfs_tmp, sizeof(njfs_tmp));
535 + if (njf->source)
536 + dictionary_set(dict, string2str(njf->source), &njfs_tmp, sizeof(njfs_tmp));
537 }
538 dfe_done(jf);
539
562 - dictionary_sorted_walkthrough_read(dict, journal_file_to_json_array_cb, wb);
540 + dictionary_sorted_walkthrough_read(dict, nd_journal_file_to_json_array_cb, wb);
541
542 dictionary_destroy(dict);
543 }
544
567 -static void files_registry_delete_cb(const DICTIONARY_ITEM *item, void *value, void *data __maybe_unused) {
568 - struct journal_file *jf = value; (void)jf;
569 - const char *filename = dictionary_acquired_item_name(item); (void)filename;
545 +static void files_registry_delete_cb(const DICTIONARY_ITEM *item, void *value, void *data __maybe_unused)
546 +{
547 + struct nd_journal_file *njf = value;
548 + const char *filename = dictionary_acquired_item_name(item);
549 + (void)filename;
550
551 internal_error(true, "removed journal file '%s'", filename);
572 - string_freez(jf->source);
552 + string_freez(njf->source);
553 }
554
555 #define EXT_DOT_JOURNAL ".journal"
@@ -579,32 +559,34 @@ static struct {
559 const char *ext;
560 ssize_t len;
561 } valid_journal_extension[] = {
582 - { .ext = EXT_DOT_JOURNAL, .len = sizeof(EXT_DOT_JOURNAL) - 1 },
583 - { .ext = EXT_DOT_JOURNAL_TILDA, .len = sizeof(EXT_DOT_JOURNAL_TILDA) - 1 },
562 + {.ext = EXT_DOT_JOURNAL, .len = sizeof(EXT_DOT_JOURNAL) - 1},
563 + {.ext = EXT_DOT_JOURNAL_TILDA, .len = sizeof(EXT_DOT_JOURNAL_TILDA) - 1},
564 };
565
586 -bool is_journal_file(const char *filename, ssize_t len, const char **start_of_extension) {
587 - if(len < 0)
566 +bool is_journal_file(const char *filename, ssize_t len, const char **start_of_extension)
567 +{
568 + if (len < 0)
569 len = (ssize_t)strlen(filename);
570
590 - for(size_t i = 0; i < _countof(valid_journal_extension) ;i++) {
571 + for (size_t i = 0; i < _countof(valid_journal_extension); i++) {
572 const char *ext = valid_journal_extension[i].ext;
573 ssize_t elen = valid_journal_extension[i].len;
574
594 - if(len > elen && strcmp(filename + len - elen, ext) == 0) {
595 - if(start_of_extension)
575 + if (len > elen && strcmp(filename + len - elen, ext) == 0) {
576 + if (start_of_extension)
577 *start_of_extension = filename + len - elen;
578 return true;
579 }
580 }
581
601 - if(start_of_extension)
582 + if (start_of_extension)
583 *start_of_extension = NULL;
584
585 return false;
586 }
587
607 -void journal_directory_scan_recursively(DICTIONARY *files, DICTIONARY *dirs, const char *dirname, int depth) {
588 +void nd_journal_directory_scan_recursively(DICTIONARY *files, DICTIONARY *dirs, const char *dirname, int depth)
589 +{
590 if (depth > VAR_LOG_JOURNAL_MAX_DEPTH)
591 return;
592
@@ -614,14 +596,15 @@ void journal_directory_scan_recursively(DICTIONARY *files, DICTIONARY *dirs, con
596
597 // Open the directory.
598 if ((dir = opendir(dirname)) == NULL) {
617 - if(errno != ENOENT && errno != ENOTDIR)
599 + if (errno != ENOENT && errno != ENOTDIR)
600 netdata_log_error("Cannot opendir() '%s'", dirname);
601 return;
602 }
603
604 bool existing = false;
605 bool *found = dictionary_set(dirs, dirname, &existing, sizeof(existing));
624 - if(*found) return;
606 + if (*found)
607 + return;
608 *found = true;
609
610 // Read each entry in the directory.
@@ -632,15 +615,13 @@ void journal_directory_scan_recursively(DICTIONARY *files, DICTIONARY *dirs, con
615 ssize_t len = snprintfz(full_path, sizeof(full_path), "%s/%s", dirname, entry->d_name);
616
617 if (entry->d_type == DT_DIR) {
635 - journal_directory_scan_recursively(files, dirs, full_path, depth++);
636 - }
637 - else if (entry->d_type == DT_REG && is_journal_file(full_path, len, NULL)) {
638 - if(files)
618 + nd_journal_directory_scan_recursively(files, dirs, full_path, depth++);
619 + } else if (entry->d_type == DT_REG && is_journal_file(full_path, len, NULL)) {
620 + if (files)
621 dictionary_set(files, full_path, NULL, 0);
622
623 send_newline_and_flush(&stdout_mutex);
642 - }
643 - else if (entry->d_type == DT_LNK) {
624 + } else if (entry->d_type == DT_LNK) {
625 struct stat info;
626 if (stat(full_path, &info) == -1)
627 continue;
@@ -649,11 +630,10 @@ void journal_directory_scan_recursively(DICTIONARY *files, DICTIONARY *dirs, con
630 // The symbolic link points to a directory
631 char resolved_path[FILENAME_MAX + 1];
632 if (realpath(full_path, resolved_path) != NULL) {
652 - journal_directory_scan_recursively(files, dirs, resolved_path, depth++);
633 + nd_journal_directory_scan_recursively(files, dirs, resolved_path, depth++);
634 }
654 - }
655 - else if(S_ISREG(info.st_mode) && is_journal_file(full_path, len, NULL)) {
656 - if(files)
635 + } else if (S_ISREG(info.st_mode) && is_journal_file(full_path, len, NULL)) {
636 + if (files)
637 dictionary_set(files, full_path, NULL, 0);
638
639 send_newline_and_flush(&stdout_mutex);
@@ -664,148 +644,164 @@ void journal_directory_scan_recursively(DICTIONARY *files, DICTIONARY *dirs, con
644 closedir(dir);
645 }
646
667 -static size_t journal_files_scans = 0;
668 -bool journal_files_completed_once(void) {
669 - return journal_files_scans > 0;
647 +static size_t nd_journal_files_scans = 0;
648 +bool nd_journal_files_completed_once(void)
649 +{
650 + return nd_journal_files_scans > 0;
651 }
652
672 -int filenames_compar(const void *a, const void *b) {
653 +int filenames_compar(const void *a, const void *b)
654 +{
655 const char *p1 = *(const char **)a;
656 const char *p2 = *(const char **)b;
657
658 const char *at1 = strchr(p1, '@');
659 const char *at2 = strchr(p2, '@');
660
679 - if(!at1 && at2)
661 + if (!at1 && at2)
662 return -1;
663
682 - if(at1 && !at2)
664 + if (at1 && !at2)
665 return 1;
666
685 - if(!at1 && !at2)
667 + if (!at1 && !at2)
668 return strcmp(p1, p2);
669
670 const char *dash1 = strrchr(at1, '-');
671 const char *dash2 = strrchr(at2, '-');
672
691 - if(!dash1 || !dash2)
673 + if (!dash1 || !dash2)
674 return strcmp(p1, p2);
675
676 uint64_t ts1 = strtoul(dash1 + 1, NULL, 16);
677 uint64_t ts2 = strtoul(dash2 + 1, NULL, 16);
678
697 - if(ts1 > ts2)
679 + if (ts1 > ts2)
680 return -1;
681
700 - if(ts1 < ts2)
682 + if (ts1 < ts2)
683 return 1;
684
685 return -strcmp(p1, p2);
686 }
687
706 -void journal_files_registry_update(void) {
688 +void nd_journal_files_registry_update(void)
689 +{
690 static SPINLOCK spinlock = SPINLOCK_INITIALIZER;
691
709 - if(spinlock_trylock(&spinlock)) {
692 + if (spinlock_trylock(&spinlock)) {
693 usec_t scan_monotonic_ut = now_monotonic_usec();
694
695 DICTIONARY *files = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
713 - DICTIONARY *dirs = dictionary_create(DICT_OPTION_SINGLE_THREADED|DICT_OPTION_DONT_OVERWRITE_VALUE);
696 + DICTIONARY *dirs = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
697
715 - for(unsigned i = 0; i < MAX_JOURNAL_DIRECTORIES; i++) {
716 - if(!journal_directories[i].path) break;
717 - journal_directory_scan_recursively(files, dirs, string2str(journal_directories[i].path), 0);
698 + for (unsigned i = 0; i < MAX_JOURNAL_DIRECTORIES; i++) {
699 + if (!journal_directories[i].path)
700 + break;
701 + nd_journal_directory_scan_recursively(files, dirs, string2str(journal_directories[i].path), 0);
702 }
703
704 const char **array = mallocz(sizeof(const char *) * dictionary_entries(files));
705 size_t used = 0;
706
707 void *x;
724 - dfe_start_read(files, x) {
725 - if(used >= dictionary_entries(files)) continue;
708 + dfe_start_read(files, x)
709 + {
710 + if (used >= dictionary_entries(files))
711 + continue;
712 array[used++] = x_dfe.name;
713 }
714 dfe_done(x);
715
716 qsort(array, used, sizeof(const char *), filenames_compar);
717
732 - for(size_t i = 0; i < used ;i++) {
718 + for (size_t i = 0; i < used; i++) {
719 const char *full_path = array[i];
720
721 struct stat info;
722 if (stat(full_path, &info) == -1)
723 continue;
724
739 - struct journal_file t = {
740 - .file_last_modified_ut = info.st_mtim.tv_sec * USEC_PER_SEC + info.st_mtim.tv_nsec / NSEC_PER_USEC,
741 - .last_scan_monotonic_ut = scan_monotonic_ut,
742 - .size = info.st_size,
743 - .max_journal_vs_realtime_delta_ut = JOURNAL_VS_REALTIME_DELTA_DEFAULT_UT,
725 + struct nd_journal_file njf_tmp = {
726 + .file_last_modified_ut = info.st_mtim.tv_sec * USEC_PER_SEC + info.st_mtim.tv_nsec / NSEC_PER_USEC,
727 + .last_scan_monotonic_ut = scan_monotonic_ut,
728 + .size = info.st_size,
729 + .max_journal_vs_realtime_delta_ut = JOURNAL_VS_REALTIME_DELTA_DEFAULT_UT,
730 };
745 - struct journal_file *jf = dictionary_set(journal_files_registry, full_path, &t, sizeof(t));
746 - journal_file_update_header(jf->filename, jf);
731 + struct nd_journal_file *njf =
732 + dictionary_set(nd_journal_files_registry, full_path, &njf_tmp, sizeof(njf_tmp));
733 + nd_journal_file_update_header(njf->filename, njf);
734 }
735 freez(array);
736 dictionary_destroy(files);
737 dictionary_destroy(dirs);
738
752 - struct journal_file *jf;
753 - dfe_start_write(journal_files_registry, jf){
754 - if(jf->last_scan_monotonic_ut < scan_monotonic_ut)
755 - dictionary_del(journal_files_registry, jf_dfe.name);
739 + struct nd_journal_file *njf;
740 + dfe_start_write(nd_journal_files_registry, njf)
741 + {
742 + if (njf->last_scan_monotonic_ut < scan_monotonic_ut)
743 + dictionary_del(nd_journal_files_registry, njf_dfe.name);
744 }
757 - dfe_done(jf);
758 - dictionary_garbage_collect(journal_files_registry);
745 + dfe_done(njf);
746 + dictionary_garbage_collect(nd_journal_files_registry);
747
760 - journal_files_scans++;
748 + nd_journal_files_scans++;
749 spinlock_unlock(&spinlock);
750
763 - internal_error(true,
764 - "Journal library scan completed in %.3f ms",
765 - (double)(now_monotonic_usec() - scan_monotonic_ut) / (double)USEC_PER_MS);
751 + internal_error(
752 + true,
753 + "Journal library scan completed in %.3f ms",
754 + (double)(now_monotonic_usec() - scan_monotonic_ut) / (double)USEC_PER_MS);
755 }
756 }
757
758 // ----------------------------------------------------------------------------
759
771 -int journal_file_dict_items_backward_compar(const void *a, const void *b) {
760 +int nd_journal_file_dict_items_backward_compar(const void *a, const void *b)
761 +{
762 const DICTIONARY_ITEM **ad = (const DICTIONARY_ITEM **)a, **bd = (const DICTIONARY_ITEM **)b;
773 - struct journal_file *jfa = dictionary_acquired_item_value(*ad);
774 - struct journal_file *jfb = dictionary_acquired_item_value(*bd);
763 + struct nd_journal_file *njf_lhs = dictionary_acquired_item_value(*ad);
764 + struct nd_journal_file *njf_rhs = dictionary_acquired_item_value(*bd);
765
766 // compare the last message timestamps
777 - if(jfa->msg_last_ut < jfb->msg_last_ut)
767 + if (njf_lhs->msg_last_ut < njf_rhs->msg_last_ut)
768 return 1;
769
780 - if(jfa->msg_last_ut > jfb->msg_last_ut)
770 + if (njf_lhs->msg_last_ut > njf_rhs->msg_last_ut)
771 return -1;
772
773 // compare the file last modification timestamps
784 - if(jfa->file_last_modified_ut < jfb->file_last_modified_ut)
774 + if (njf_lhs->file_last_modified_ut < njf_rhs->file_last_modified_ut)
775 return 1;
776
787 - if(jfa->file_last_modified_ut > jfb->file_last_modified_ut)
777 + if (njf_lhs->file_last_modified_ut > njf_rhs->file_last_modified_ut)
778 return -1;
779
780 // compare the first message timestamps
791 - if(jfa->msg_first_ut < jfb->msg_first_ut)
781 + if (njf_lhs->msg_first_ut < njf_rhs->msg_first_ut)
782 return 1;
783
794 - if(jfa->msg_first_ut > jfb->msg_first_ut)
784 + if (njf_lhs->msg_first_ut > njf_rhs->msg_first_ut)
785 return -1;
786
787 return 0;
788 }
789
800 -int journal_file_dict_items_forward_compar(const void *a, const void *b) {
801 - return -journal_file_dict_items_backward_compar(a, b);
790 +int nd_journal_file_dict_items_forward_compar(const void *a, const void *b)
791 +{
792 + return -nd_journal_file_dict_items_backward_compar(a, b);
793 }
794
804 -static bool boot_id_conflict_cb(const DICTIONARY_ITEM *item __maybe_unused, void *old_value, void *new_value, void *data __maybe_unused) {
795 +static bool boot_id_conflict_cb(
796 + const DICTIONARY_ITEM *item __maybe_unused,
797 + void *old_value,
798 + void *new_value,
799 + void *data __maybe_unused)
800 +{
801 usec_t *old_usec = old_value;
802 usec_t *new_usec = new_value;
803
808 - if(*new_usec < *old_usec) {
804 + if (*new_usec < *old_usec) {
805 *old_usec = *new_usec;
806 return true;
807 }
@@ -813,7 +809,8 @@ static bool boot_id_conflict_cb(const DICTIONARY_ITEM *item __maybe_unused, void
809 return false;
810 }
811
816 -void journal_init_files_and_directories(void) {
812 +void nd_journal_init_files_and_directories(void)
813 +{
814 unsigned d = 0;
815
816 // ------------------------------------------------------------------------
@@ -822,7 +819,7 @@ void journal_init_files_and_directories(void) {
819 journal_directories[d++].path = string_strdupz("/run/log/journal");
820 journal_directories[d++].path = string_strdupz("/var/log/journal");
821
825 - if(*netdata_configured_host_prefix) {
822 + if (*netdata_configured_host_prefix) {
823 char path[PATH_MAX];
824 snprintfz(path, sizeof(path), "%s/var/log/journal", netdata_configured_host_prefix);
825 journal_directories[d++].path = string_strdupz(path);
@@ -840,18 +837,15 @@ void journal_init_files_and_directories(void) {
837
838 systemd_journal_session = (now_realtime_usec() / USEC_PER_SEC) * USEC_PER_SEC;
839
843 - journal_files_registry = dictionary_create_advanced(
844 - DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE,
845 - NULL, sizeof(struct journal_file));
840 + nd_journal_files_registry = dictionary_create_advanced(
841 + DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct nd_journal_file));
842
847 - dictionary_register_insert_callback(journal_files_registry, files_registry_insert_cb, NULL);
848 - dictionary_register_delete_callback(journal_files_registry, files_registry_delete_cb, NULL);
849 - dictionary_register_conflict_callback(journal_files_registry, files_registry_conflict_cb, NULL);
843 + dictionary_register_insert_callback(nd_journal_files_registry, files_registry_insert_cb, NULL);
844 + dictionary_register_delete_callback(nd_journal_files_registry, files_registry_delete_cb, NULL);
845 + dictionary_register_conflict_callback(nd_journal_files_registry, files_registry_conflict_cb, NULL);
846
851 - boot_ids_to_first_ut = dictionary_create_advanced(
852 - DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE,
853 - NULL, sizeof(usec_t));
847 + boot_ids_to_first_ut =
848 + dictionary_create_advanced(DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(usec_t));
849
850 dictionary_register_conflict_callback(boot_ids_to_first_ut, boot_id_conflict_cb, NULL);
856 -
851 }
src/collectors/systemd-journal.plugin/systemd-journal-fstat.c
+13 -9
@@ -2,7 +2,6 @@
2
3 #include "systemd-internals.h"
4
5 -
5 // ----------------------------------------------------------------------------
6 // fstat64 overloading to speed up libsystemd
7 // https://github.com/systemd/systemd/pull/29261
@@ -21,38 +20,42 @@ struct fdstat64_cache_entry {
20 size_t session;
21 };
22
24 -struct fdstat64_cache_entry fstat64_cache[FSTAT_CACHE_MAX] = {0 };
23 +struct fdstat64_cache_entry fstat64_cache[FSTAT_CACHE_MAX] = {0};
24 __thread size_t fstat_thread_calls = 0;
25 __thread size_t fstat_thread_cached_responses = 0;
26 static __thread bool enable_thread_fstat = false;
27 static __thread size_t fstat_caching_thread_session = 0;
28 static size_t fstat_caching_global_session = 0;
29
31 -void fstat_cache_enable_on_thread(void) {
30 +void fstat_cache_enable_on_thread(void)
31 +{
32 fstat_caching_thread_session = __atomic_add_fetch(&fstat_caching_global_session, 1, __ATOMIC_ACQUIRE);
33 enable_thread_fstat = true;
34 }
35
36 -void fstat_cache_disable_on_thread(void) {
36 +void fstat_cache_disable_on_thread(void)
37 +{
38 fstat_caching_thread_session = __atomic_add_fetch(&fstat_caching_global_session, 1, __ATOMIC_RELEASE);
39 enable_thread_fstat = false;
40 }
41
41 -int fstat64(int fd, struct stat64 *buf) {
42 +int fstat64(int fd, struct stat64 *buf)
43 +{
44 static int (*real_fstat)(int, struct stat64 *) = NULL;
45 if (!real_fstat)
46 real_fstat = dlsym(RTLD_NEXT, "fstat64");
47
48 fstat_thread_calls++;
49
48 - if(fd >= 0 && fd < FSTAT_CACHE_MAX) {
49 - if(enable_thread_fstat && fstat64_cache[fd].session != fstat_caching_thread_session) {
50 + if (fd >= 0 && fd < FSTAT_CACHE_MAX) {
51 + if (enable_thread_fstat && fstat64_cache[fd].session != fstat_caching_thread_session) {
52 fstat64_cache[fd].session = fstat_caching_thread_session;
53 fstat64_cache[fd].enabled = true;
54 fstat64_cache[fd].updated = false;
55 }
56
55 - if(fstat64_cache[fd].enabled && fstat64_cache[fd].updated && fstat64_cache[fd].session == fstat_caching_thread_session) {
57 + if (fstat64_cache[fd].enabled && fstat64_cache[fd].updated &&
58 + fstat64_cache[fd].session == fstat_caching_thread_session) {
59 fstat_thread_cached_responses++;
60 errno = fstat64_cache[fd].err_no;
61 *buf = fstat64_cache[fd].stat;
@@ -63,7 +66,8 @@ int fstat64(int fd, struct stat64 *buf) {
66
67 int ret = real_fstat(fd, buf);
68
66 - if(fd >= 0 && fd < FSTAT_CACHE_MAX && fstat64_cache[fd].enabled && fstat64_cache[fd].session == fstat_caching_thread_session) {
69 + if (fd >= 0 && fd < FSTAT_CACHE_MAX && fstat64_cache[fd].enabled &&
70 + fstat64_cache[fd].session == fstat_caching_thread_session) {
71 fstat64_cache[fd].ret = ret;
72 fstat64_cache[fd].updated = true;
73 fstat64_cache[fd].err_no = errno;
src/collectors/systemd-journal.plugin/systemd-journal-sampling.h
+123 -86
@@ -1,30 +1,31 @@
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 -#ifndef NETDATA_SYSTEMD_JOURNAL_SAMPLING_H
4 -#define NETDATA_SYSTEMD_JOURNAL_SAMPLING_H
3 +#ifndef NETDATA_ND_SD_JOURNAL_SAMPLING_H
4 +#define NETDATA_ND_SD_JOURNAL_SAMPLING_H
5
6 // ----------------------------------------------------------------------------
7 // sampling support
8
9 -static inline void sampling_query_init(LOGS_QUERY_STATUS *lqs, FACETS *facets) {
10 - if(!lqs->rq.sampling)
9 +static inline void sampling_query_init(LOGS_QUERY_STATUS *lqs, FACETS *facets)
10 +{
11 + if (!lqs->rq.sampling)
12 return;
13
13 - if(!lqs->rq.slice) {
14 + if (!lqs->rq.slice) {
15 // the user is doing a full data query
16 // disable sampling
17 lqs->rq.sampling = 0;
18 return;
19 }
20
20 - if(lqs->rq.data_only) {
21 + if (lqs->rq.data_only) {
22 // the user is doing a data query
23 // disable sampling
24 lqs->rq.sampling = 0;
25 return;
26 }
27
27 - if(!lqs->c.files_matched) {
28 + if (!lqs->c.files_matched) {
29 // no files have been matched
30 // disable sampling
31 lqs->rq.sampling = 0;
@@ -32,12 +33,12 @@ static inline void sampling_query_init(LOGS_QUERY_STATUS *lqs, FACETS *facets) {
33 }
34
35 lqs->c.samples.slots = facets_histogram_slots(facets);
35 - if(lqs->c.samples.slots < 2)
36 + if (lqs->c.samples.slots < 2)
37 lqs->c.samples.slots = 2;
37 - if(lqs->c.samples.slots > SYSTEMD_JOURNAL_SAMPLING_SLOTS)
38 - lqs->c.samples.slots = SYSTEMD_JOURNAL_SAMPLING_SLOTS;
38 + if (lqs->c.samples.slots > ND_SD_JOURNAL_SAMPLING_SLOTS)
39 + lqs->c.samples.slots = ND_SD_JOURNAL_SAMPLING_SLOTS;
40
40 - if(!lqs->rq.after_ut || !lqs->rq.before_ut || lqs->rq.after_ut >= lqs->rq.before_ut) {
41 + if (!lqs->rq.after_ut || !lqs->rq.before_ut || lqs->rq.after_ut >= lqs->rq.before_ut) {
42 // we don't have enough information for sampling
43 lqs->rq.sampling = 0;
44 return;
@@ -45,7 +46,8 @@ static inline void sampling_query_init(LOGS_QUERY_STATUS *lqs, FACETS *facets) {
46
47 usec_t delta = lqs->rq.before_ut - lqs->rq.after_ut;
48 usec_t step = delta / facets_histogram_slots(facets) - 1;
48 - if(step < 1) step = 1;
49 + if (step < 1)
50 + step = 1;
51
52 lqs->c.samples_per_time_slot.start_ut = lqs->rq.after_ut;
53 lqs->c.samples_per_time_slot.end_ut = lqs->rq.before_ut;
@@ -55,21 +57,22 @@ static inline void sampling_query_init(LOGS_QUERY_STATUS *lqs, FACETS *facets) {
57 lqs->c.samples.enable_after_samples = lqs->rq.sampling / 2;
58
59 size_t files_matched = lqs->c.files_matched;
58 - if(!files_matched)
60 + if (!files_matched)
61 files_matched = 1;
62
63 // the minimum number of rows per file to enable sampling
64 lqs->c.samples_per_file.enable_after_samples = (lqs->rq.sampling / 4) / files_matched;
63 - if(lqs->c.samples_per_file.enable_after_samples < lqs->rq.entries)
65 + if (lqs->c.samples_per_file.enable_after_samples < lqs->rq.entries)
66 lqs->c.samples_per_file.enable_after_samples = lqs->rq.entries;
67
68 // the minimum number of rows per time slot to enable sampling
69 lqs->c.samples_per_time_slot.enable_after_samples = (lqs->rq.sampling / 4) / lqs->c.samples.slots;
68 - if(lqs->c.samples_per_time_slot.enable_after_samples < lqs->rq.entries)
70 + if (lqs->c.samples_per_time_slot.enable_after_samples < lqs->rq.entries)
71 lqs->c.samples_per_time_slot.enable_after_samples = lqs->rq.entries;
72 }
73
72 -static inline void sampling_file_init(LOGS_QUERY_STATUS *lqs, struct journal_file *jf __maybe_unused) {
74 +static inline void sampling_file_init(LOGS_QUERY_STATUS *lqs, struct nd_journal_file *jf __maybe_unused)
75 +{
76 lqs->c.samples_per_file.sampled = 0;
77 lqs->c.samples_per_file.unsampled = 0;
78 lqs->c.samples_per_file.estimated = 0;
@@ -78,46 +81,53 @@ static inline void sampling_file_init(LOGS_QUERY_STATUS *lqs, struct journal_fil
81 lqs->c.samples_per_file.recalibrate = 0;
82 }
83
81 -static inline size_t sampling_file_lines_scanned_so_far(LOGS_QUERY_STATUS *lqs) {
84 +static inline size_t sampling_file_lines_scanned_so_far(LOGS_QUERY_STATUS *lqs)
85 +{
86 size_t sampled = lqs->c.samples_per_file.sampled + lqs->c.samples_per_file.unsampled;
83 - if(!sampled) sampled = 1;
87 + if (!sampled)
88 + sampled = 1;
89 return sampled;
90 }
91
92 static inline void sampling_running_file_query_overlapping_timeframe_ut(
88 - LOGS_QUERY_STATUS *lqs, struct journal_file *jf, FACETS_ANCHOR_DIRECTION direction,
89 - usec_t msg_ut, usec_t *after_ut, usec_t *before_ut) {
90 -
93 + LOGS_QUERY_STATUS *lqs,
94 + struct nd_journal_file *jf,
95 + FACETS_ANCHOR_DIRECTION direction,
96 + usec_t msg_ut,
97 + usec_t *after_ut,
98 + usec_t *before_ut)
99 +{
100 // find the overlap of the query and file timeframes
101 // taking into account the first message we encountered
102
103 usec_t oldest_ut, newest_ut;
95 - if(direction == FACETS_ANCHOR_DIRECTION_FORWARD) {
104 + if (direction == FACETS_ANCHOR_DIRECTION_FORWARD) {
105 // the first message we know (oldest)
106 oldest_ut = lqs->c.query_file.first_msg_ut ? lqs->c.query_file.first_msg_ut : jf->msg_first_ut;
98 - if(!oldest_ut) oldest_ut = lqs->c.query_file.start_ut;
107 + if (!oldest_ut)
108 + oldest_ut = lqs->c.query_file.start_ut;
109
100 - if(jf->msg_last_ut)
110 + if (jf->msg_last_ut)
111 newest_ut = MIN(lqs->c.query_file.stop_ut, jf->msg_last_ut);
102 - else if(jf->file_last_modified_ut)
112 + else if (jf->file_last_modified_ut)
113 newest_ut = MIN(lqs->c.query_file.stop_ut, jf->file_last_modified_ut);
114 else
115 newest_ut = lqs->c.query_file.stop_ut;
116
107 - if(msg_ut < oldest_ut)
117 + if (msg_ut < oldest_ut)
118 oldest_ut = msg_ut - 1;
109 - }
110 - else /* BACKWARD */ {
119 + } else /* BACKWARD */ {
120 // the latest message we know (newest)
121 newest_ut = lqs->c.query_file.first_msg_ut ? lqs->c.query_file.first_msg_ut : jf->msg_last_ut;
113 - if(!newest_ut) newest_ut = lqs->c.query_file.start_ut;
122 + if (!newest_ut)
123 + newest_ut = lqs->c.query_file.start_ut;
124
115 - if(jf->msg_first_ut)
125 + if (jf->msg_first_ut)
126 oldest_ut = MAX(lqs->c.query_file.stop_ut, jf->msg_first_ut);
127 else
128 oldest_ut = lqs->c.query_file.stop_ut;
129
120 - if(newest_ut < msg_ut)
130 + if (newest_ut < msg_ut)
131 newest_ut = msg_ut + 1;
132 }
133
@@ -126,13 +136,15 @@ static inline void sampling_running_file_query_overlapping_timeframe_ut(
136 }
137
138 static inline double sampling_running_file_query_progress_by_time(
129 - LOGS_QUERY_STATUS *lqs, struct journal_file *jf,
130 - FACETS_ANCHOR_DIRECTION direction, usec_t msg_ut) {
131 -
139 + LOGS_QUERY_STATUS *lqs,
140 + struct nd_journal_file *jf,
141 + FACETS_ANCHOR_DIRECTION direction,
142 + usec_t msg_ut)
143 +{
144 usec_t after_ut, before_ut, elapsed_ut;
145 sampling_running_file_query_overlapping_timeframe_ut(lqs, jf, direction, msg_ut, &after_ut, &before_ut);
146
135 - if(direction == FACETS_ANCHOR_DIRECTION_FORWARD)
147 + if (direction == FACETS_ANCHOR_DIRECTION_FORWARD)
148 elapsed_ut = msg_ut - after_ut;
149 else
150 elapsed_ut = before_ut - msg_ut;
@@ -144,41 +156,44 @@ static inline double sampling_running_file_query_progress_by_time(
156 }
157
158 static inline usec_t sampling_running_file_query_remaining_time(
147 - LOGS_QUERY_STATUS *lqs, struct journal_file *jf,
148 - FACETS_ANCHOR_DIRECTION direction, usec_t msg_ut,
149 - usec_t *total_time_ut, usec_t *remaining_start_ut,
150 - usec_t *remaining_end_ut) {
159 + LOGS_QUERY_STATUS *lqs,
160 + struct nd_journal_file *jf,
161 + FACETS_ANCHOR_DIRECTION direction,
162 + usec_t msg_ut,
163 + usec_t *total_time_ut,
164 + usec_t *remaining_start_ut,
165 + usec_t *remaining_end_ut)
166 +{
167 usec_t after_ut, before_ut;
168 sampling_running_file_query_overlapping_timeframe_ut(lqs, jf, direction, msg_ut, &after_ut, &before_ut);
169
170 // since we have a timestamp in msg_ut
171 // this timestamp can extend the overlap
156 - if(msg_ut <= after_ut)
172 + if (msg_ut <= after_ut)
173 after_ut = msg_ut - 1;
174
159 - if(msg_ut >= before_ut)
175 + if (msg_ut >= before_ut)
176 before_ut = msg_ut + 1;
177
178 // return the remaining duration
179 usec_t remaining_from_ut, remaining_to_ut;
164 - if(direction == FACETS_ANCHOR_DIRECTION_FORWARD) {
180 + if (direction == FACETS_ANCHOR_DIRECTION_FORWARD) {
181 remaining_from_ut = msg_ut;
182 remaining_to_ut = before_ut;
167 - }
168 - else {
183 + } else {
184 remaining_from_ut = after_ut;
185 remaining_to_ut = msg_ut;
186 }
187
188 usec_t remaining_ut = remaining_to_ut - remaining_from_ut;
189
175 - if(total_time_ut)
190 + if (total_time_ut)
191 *total_time_ut = (before_ut > after_ut) ? before_ut - after_ut : 1;
192
178 - if(remaining_start_ut)
193 + if (remaining_start_ut)
194 *remaining_start_ut = remaining_from_ut;
195
181 - if(remaining_end_ut)
196 + if (remaining_end_ut)
197 *remaining_end_ut = remaining_to_ut;
198
199 return remaining_ut;
@@ -186,18 +201,20 @@ static inline usec_t sampling_running_file_query_remaining_time(
201
202 static inline size_t sampling_running_file_query_estimate_remaining_lines_by_time(
203 LOGS_QUERY_STATUS *lqs,
189 - struct journal_file *jf,
204 + struct nd_journal_file *jf,
205 FACETS_ANCHOR_DIRECTION direction,
191 - usec_t msg_ut) {
206 + usec_t msg_ut)
207 +{
208 size_t scanned_lines = sampling_file_lines_scanned_so_far(lqs);
209
210 // Calculate the proportion of time covered
211 usec_t total_time_ut, remaining_start_ut, remaining_end_ut;
212 usec_t remaining_time_ut = sampling_running_file_query_remaining_time(
213 lqs, jf, direction, msg_ut, &total_time_ut, &remaining_start_ut, &remaining_end_ut);
198 - if (total_time_ut == 0) total_time_ut = 1;
214 + if (total_time_ut == 0)
215 + total_time_ut = 1;
216
200 - double proportion_by_time = (double) (total_time_ut - remaining_time_ut) / (double) total_time_ut;
217 + double proportion_by_time = (double)(total_time_ut - remaining_time_ut) / (double)total_time_ut;
218
219 if (proportion_by_time == 0 || proportion_by_time > 1.0 || !isfinite(proportion_by_time))
220 proportion_by_time = 1.0;
@@ -205,12 +222,13 @@ static inline size_t sampling_running_file_query_estimate_remaining_lines_by_tim
222 // Estimate the total number of lines in the file
223 size_t expected_matching_logs_by_time = (size_t)((double)scanned_lines / proportion_by_time);
224
208 - if(jf->messages_in_file && expected_matching_logs_by_time > jf->messages_in_file)
225 + if (jf->messages_in_file && expected_matching_logs_by_time > jf->messages_in_file)
226 expected_matching_logs_by_time = jf->messages_in_file;
227
228 // Calculate the estimated number of remaining lines
229 size_t remaining_logs_by_time = expected_matching_logs_by_time - scanned_lines;
213 - if (remaining_logs_by_time < 1) remaining_logs_by_time = 1;
230 + if (remaining_logs_by_time < 1)
231 + remaining_logs_by_time = 1;
232
233 // nd_log(NDLS_COLLECTORS, NDLP_INFO,
234 // "JOURNAL ESTIMATION: '%s' "
@@ -237,8 +255,12 @@ static inline size_t sampling_running_file_query_estimate_remaining_lines_by_tim
255 }
256
257 static inline size_t sampling_running_file_query_estimate_remaining_lines(
240 - sd_journal *j __maybe_unused, LOGS_QUERY_STATUS *lqs, struct journal_file *jf,
241 - FACETS_ANCHOR_DIRECTION direction, usec_t msg_ut) {
258 + sd_journal *j __maybe_unused,
259 + LOGS_QUERY_STATUS *lqs,
260 + struct nd_journal_file *jf,
261 + FACETS_ANCHOR_DIRECTION direction,
262 + usec_t msg_ut)
263 +{
264 size_t remaining_logs_by_seqnum = 0;
265
266 #ifdef HAVE_SD_JOURNAL_GET_SEQNUM
@@ -246,20 +268,19 @@ static inline size_t sampling_running_file_query_estimate_remaining_lines(
268 double proportion_by_seqnum = 0.0;
269 uint64_t current_msg_seqnum;
270 sd_id128_t current_msg_writer;
249 - if(!lqs->c.query_file.first_msg_seqnum || sd_journal_get_seqnum(j, &current_msg_seqnum, &current_msg_writer) < 0) {
271 + if (!lqs->c.query_file.first_msg_seqnum || sd_journal_get_seqnum(j, &current_msg_seqnum, &current_msg_writer) < 0) {
272 lqs->c.query_file.first_msg_seqnum = 0;
273 lqs->c.query_file.first_msg_writer = SD_ID128_NULL;
252 - }
253 - else if(jf->messages_in_file) {
274 + } else if (jf->messages_in_file) {
275 size_t scanned_lines = sampling_file_lines_scanned_so_far(lqs);
276
277 double proportion_of_all_lines_so_far;
257 - if(direction == FACETS_ANCHOR_DIRECTION_FORWARD)
278 + if (direction == FACETS_ANCHOR_DIRECTION_FORWARD)
279 proportion_of_all_lines_so_far = (double)scanned_lines / (double)(current_msg_seqnum - jf->first_seqnum);
280 else
281 proportion_of_all_lines_so_far = (double)scanned_lines / (double)(jf->last_seqnum - current_msg_seqnum);
282
262 - if(proportion_of_all_lines_so_far > 1.0)
283 + if (proportion_of_all_lines_so_far > 1.0)
284 proportion_of_all_lines_so_far = 1.0;
285
286 expected_matching_logs_by_seqnum = (size_t)(proportion_of_all_lines_so_far * (double)jf->messages_in_file);
@@ -270,28 +291,36 @@ static inline size_t sampling_running_file_query_estimate_remaining_lines(
291 proportion_by_seqnum = 1.0;
292
293 remaining_logs_by_seqnum = expected_matching_logs_by_seqnum - scanned_lines;
273 - if(!remaining_logs_by_seqnum) remaining_logs_by_seqnum = 1;
294 + if (!remaining_logs_by_seqnum)
295 + remaining_logs_by_seqnum = 1;
296 }
297 #endif
298
277 - if(remaining_logs_by_seqnum)
299 + if (remaining_logs_by_seqnum)
300 return remaining_logs_by_seqnum;
301
302 return sampling_running_file_query_estimate_remaining_lines_by_time(lqs, jf, direction, msg_ut);
303 }
304
283 -static inline void sampling_decide_file_sampling_every(sd_journal *j,
284 - LOGS_QUERY_STATUS *lqs, struct journal_file *jf, FACETS_ANCHOR_DIRECTION direction, usec_t msg_ut) {
305 +static inline void sampling_decide_file_sampling_every(
306 + sd_journal *j,
307 + LOGS_QUERY_STATUS *lqs,
308 + struct nd_journal_file *jf,
309 + FACETS_ANCHOR_DIRECTION direction,
310 + usec_t msg_ut)
311 +{
312 size_t files_matched = lqs->c.files_matched;
286 - if(!files_matched) files_matched = 1;
313 + if (!files_matched)
314 + files_matched = 1;
315
316 size_t remaining_lines = sampling_running_file_query_estimate_remaining_lines(j, lqs, jf, direction, msg_ut);
317 size_t wanted_samples = (lqs->rq.sampling / 2) / files_matched;
290 - if(!wanted_samples) wanted_samples = 1;
318 + if (!wanted_samples)
319 + wanted_samples = 1;
320
321 lqs->c.samples_per_file.every = remaining_lines / wanted_samples;
322
294 - if(lqs->c.samples_per_file.every < 1)
323 + if (lqs->c.samples_per_file.every < 1)
324 lqs->c.samples_per_file.every = 1;
325 }
326
@@ -302,44 +331,47 @@ typedef enum {
331 } sampling_t;
332
333 static inline sampling_t is_row_in_sample(
305 - sd_journal *j, LOGS_QUERY_STATUS *lqs, struct journal_file *jf,
306 - usec_t msg_ut, FACETS_ANCHOR_DIRECTION direction, bool candidate_to_keep) {
307 - if(!lqs->rq.sampling || candidate_to_keep)
334 + sd_journal *j,
335 + LOGS_QUERY_STATUS *lqs,
336 + struct nd_journal_file *jf,
337 + usec_t msg_ut,
338 + FACETS_ANCHOR_DIRECTION direction,
339 + bool candidate_to_keep)
340 +{
341 + if (!lqs->rq.sampling || candidate_to_keep)
342 return SAMPLING_FULL;
343
310 - if(unlikely(msg_ut < lqs->c.samples_per_time_slot.start_ut))
344 + if (unlikely(msg_ut < lqs->c.samples_per_time_slot.start_ut))
345 msg_ut = lqs->c.samples_per_time_slot.start_ut;
312 - if(unlikely(msg_ut > lqs->c.samples_per_time_slot.end_ut))
346 + if (unlikely(msg_ut > lqs->c.samples_per_time_slot.end_ut))
347 msg_ut = lqs->c.samples_per_time_slot.end_ut;
348
349 size_t slot = (msg_ut - lqs->c.samples_per_time_slot.start_ut) / lqs->c.samples_per_time_slot.step_ut;
316 - if(slot >= lqs->c.samples.slots)
350 + if (slot >= lqs->c.samples.slots)
351 slot = lqs->c.samples.slots - 1;
352
353 bool should_sample = false;
354
321 - if(lqs->c.samples.sampled < lqs->c.samples.enable_after_samples ||
355 + if (lqs->c.samples.sampled < lqs->c.samples.enable_after_samples ||
356 lqs->c.samples_per_file.sampled < lqs->c.samples_per_file.enable_after_samples ||
357 lqs->c.samples_per_time_slot.sampled[slot] < lqs->c.samples_per_time_slot.enable_after_samples)
358 should_sample = true;
359
326 - else if(lqs->c.samples_per_file.recalibrate >= SYSTEMD_JOURNAL_SAMPLING_RECALIBRATE || !lqs->c.samples_per_file.every) {
360 + else if (lqs->c.samples_per_file.recalibrate >= ND_SD_JOURNAL_SAMPLING_RECALIBRATE || !lqs->c.samples_per_file.every) {
361 // this is the first to be unsampled for this file
362 sampling_decide_file_sampling_every(j, lqs, jf, direction, msg_ut);
363 lqs->c.samples_per_file.recalibrate = 0;
364 should_sample = true;
331 - }
332 - else {
365 + } else {
366 // we sample 1 every fqs->samples_per_file.every
334 - if(lqs->c.samples_per_file.skipped >= lqs->c.samples_per_file.every) {
367 + if (lqs->c.samples_per_file.skipped >= lqs->c.samples_per_file.every) {
368 lqs->c.samples_per_file.skipped = 0;
369 should_sample = true;
337 - }
338 - else
370 + } else
371 lqs->c.samples_per_file.skipped++;
372 }
373
342 - if(should_sample) {
374 + if (should_sample) {
375 lqs->c.samples.sampled++;
376 lqs->c.samples_per_file.sampled++;
377 lqs->c.samples_per_time_slot.sampled[slot]++;
@@ -353,10 +385,10 @@ static inline sampling_t is_row_in_sample(
385 lqs->c.samples_per_file.unsampled++;
386 lqs->c.samples_per_time_slot.unsampled[slot]++;
387
356 - if(lqs->c.samples_per_file.unsampled > lqs->c.samples_per_file.sampled) {
388 + if (lqs->c.samples_per_file.unsampled > lqs->c.samples_per_file.sampled) {
389 double progress_by_time = sampling_running_file_query_progress_by_time(lqs, jf, direction, msg_ut);
390
359 - if(progress_by_time > SYSTEMD_JOURNAL_ENABLE_ESTIMATIONS_FILE_PERCENTAGE)
391 + if (progress_by_time > ND_SD_JOURNAL_ENABLE_ESTIMATIONS_FILE_PERCENTAGE)
392 return SAMPLING_STOP_AND_ESTIMATE;
393 }
394
@@ -364,8 +396,13 @@ static inline sampling_t is_row_in_sample(
396 }
397
398 static inline void sampling_update_running_query_file_estimates(
367 - FACETS *facets, sd_journal *j,
368 - LOGS_QUERY_STATUS *lqs, struct journal_file *jf, usec_t msg_ut, FACETS_ANCHOR_DIRECTION direction) {
399 + FACETS *facets,
400 + sd_journal *j,
401 + LOGS_QUERY_STATUS *lqs,
402 + struct nd_journal_file *jf,
403 + usec_t msg_ut,
404 + FACETS_ANCHOR_DIRECTION direction)
405 +{
406 usec_t total_time_ut, remaining_start_ut, remaining_end_ut;
407 sampling_running_file_query_remaining_time(
408 lqs, jf, direction, msg_ut, &total_time_ut, &remaining_start_ut, &remaining_end_ut);
@@ -375,4 +412,4 @@ static inline void sampling_update_running_query_file_estimates(
412 lqs->c.samples_per_file.estimated += remaining_lines;
413 }
414
378 -#endif //NETDATA_SYSTEMD_JOURNAL_SAMPLING_H
415 +#endif //NETDATA_ND_SD_JOURNAL_SAMPLING_H
src/collectors/systemd-journal.plugin/systemd-journal-watcher.c
+184 -150
@@ -43,8 +43,7 @@ ENUM_STR_MAP_DEFINE(INOTIFY_MASK) = {
43 {.id = IN_ONESHOT, .name = "IN_ONESHOT"},
44
45 // terminator
46 - {.id = 0, .name = NULL}
47 -};
46 + {.id = 0, .name = NULL}};
47
48 BITMAP_STR_DEFINE_FUNCTIONS(INOTIFY_MASK, 0, "UNKNOWN");
49
@@ -53,8 +52,8 @@ DEFINE_JUDYL_TYPED(SYMLINKED_DIRS, STRING *);
52 typedef struct watch_entry {
53 int slot;
54
56 - int wd; // Watch descriptor
57 - char *path; // Dynamically allocated path
55 + int wd; // Watch descriptor
56 + char *path; // Dynamically allocated path
57
58 struct watch_entry *next; // for the free list
59 } WatchEntry;
@@ -71,7 +70,8 @@ typedef struct {
70 DICTIONARY *pending;
71 } Watcher;
72
74 -static WatchEntry *get_slot(Watcher *watcher) {
73 +static WatchEntry *get_slot(Watcher *watcher)
74 +{
75 WatchEntry *t;
76
77 if (watcher->freeList != NULL) {
@@ -87,10 +87,10 @@ static WatchEntry *get_slot(Watcher *watcher) {
87 }
88
89 watcher->watchList[watcher->watchCount] = (WatchEntry){
90 - .slot = watcher->watchCount,
91 - .wd = -1,
92 - .path = NULL,
93 - .next = NULL,
90 + .slot = watcher->watchCount,
91 + .wd = -1,
92 + .path = NULL,
93 + .next = NULL,
94 };
95 t = &watcher->watchList[watcher->watchCount];
96 watcher->watchCount++;
@@ -98,7 +98,8 @@ static WatchEntry *get_slot(Watcher *watcher) {
98 return t;
99 }
100
101 -static void free_slot(Watcher *watcher, WatchEntry *t) {
101 +static void free_slot(Watcher *watcher, WatchEntry *t)
102 +{
103 t->wd = -1;
104 freez(t->path);
105 t->path = NULL;
@@ -108,48 +109,45 @@ static void free_slot(Watcher *watcher, WatchEntry *t) {
109 watcher->freeList = t;
110 }
111
111 -static int add_watch(Watcher *watcher, int inotifyFd, const char *path) {
112 +static int add_watch(Watcher *watcher, int inotifyFd, const char *path)
113 +{
114 WatchEntry *t = get_slot(watcher);
115
116 errno_clear();
117 t->wd = inotify_add_watch(inotifyFd, path, WATCH_FOR);
118 if (t->wd == -1) {
117 - nd_log(NDLS_COLLECTORS, NDLP_ERR,
118 - "JOURNAL WATCHER: cannot watch directory: '%s'",
119 - path);
119 + nd_log(NDLS_COLLECTORS, NDLP_ERR, "JOURNAL WATCHER: cannot watch directory: '%s'", path);
120
121 free_slot(watcher, t);
122
123 struct stat info;
124 - if(stat(path, &info) == 0 && S_ISDIR(info.st_mode)) {
124 + if (stat(path, &info) == 0 && S_ISDIR(info.st_mode)) {
125 // the directory exists, but we failed to add the watch
126 // increase errors
127 watcher->errors++;
128 }
129 - }
130 - else {
129 + } else {
130 t->path = strdupz(path);
131
133 - nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
134 - "JOURNAL WATCHER: watching directory: '%s'",
135 - path);
136 -
132 + nd_log(NDLS_COLLECTORS, NDLP_DEBUG, "JOURNAL WATCHER: watching directory: '%s'", path);
133 }
134 return t->wd;
135 }
136
141 -static void remove_watch(Watcher *watcher, int inotifyFd, int wd) {
137 +static void remove_watch(Watcher *watcher, int inotifyFd, int wd)
138 +{
139 errno_clear();
140
141 int i;
142 for (i = 0; i < watcher->watchCount; ++i) {
143 if (watcher->watchList[i].wd == wd) {
144 + nd_log(
145 + NDLS_COLLECTORS,
146 + NDLP_DEBUG,
147 + "JOURNAL WATCHER: removing watch from directory: '%s'",
148 + watcher->watchList[i].path);
149
148 - nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
149 - "JOURNAL WATCHER: removing watch from directory: '%s'",
150 - watcher->watchList[i].path);
151 -
152 - if(inotify_rm_watch(inotifyFd, watcher->watchList[i].wd) == -1)
150 + if (inotify_rm_watch(inotifyFd, watcher->watchList[i].wd) == -1)
151 nd_log(NDLS_COLLECTORS, NDLP_ERR, "JOURNAL WATCHER: inotify_rm_watch() returned -1");
152
153 free_slot(watcher, &watcher->watchList[i]);
@@ -157,15 +155,14 @@ static void remove_watch(Watcher *watcher, int inotifyFd, int wd) {
155 }
156 }
157
160 - nd_log(NDLS_COLLECTORS, NDLP_WARNING,
161 - "JOURNAL WATCHER: cannot find directory watch %d to remove.",
162 - wd);
158 + nd_log(NDLS_COLLECTORS, NDLP_WARNING, "JOURNAL WATCHER: cannot find directory watch %d to remove.", wd);
159 }
160
165 -static void free_watches(Watcher *watcher, int inotifyFd) {
161 +static void free_watches(Watcher *watcher, int inotifyFd)
162 +{
163 for (int i = 0; i < watcher->watchCount; ++i) {
164 if (watcher->watchList[i].wd != -1) {
168 - if(inotify_rm_watch(inotifyFd, watcher->watchList[i].wd) == -1)
165 + if (inotify_rm_watch(inotifyFd, watcher->watchList[i].wd) == -1)
166 nd_log(NDLS_COLLECTORS, NDLP_ERR, "JOURNAL WATCHER: inotify_rm_watch() returned -1");
167 free_slot(watcher, &watcher->watchList[i]);
168 }
@@ -177,10 +174,11 @@ static void free_watches(Watcher *watcher, int inotifyFd) {
174 watcher->pending = NULL;
175 }
176
180 -static void free_symlinked_dirs(Watcher *watcher) {
177 +static void free_symlinked_dirs(Watcher *watcher)
178 +{
179 Word_t idx = 0;
180 STRING *value;
183 - while((value = SYMLINKED_DIRS_FIRST(&watcher->symlinkedDirs, &idx))) {
181 + while ((value = SYMLINKED_DIRS_FIRST(&watcher->symlinkedDirs, &idx))) {
182 SYMLINKED_DIRS_DEL(&watcher->symlinkedDirs, idx);
183 STRING *key = (STRING *)idx;
184 string_freez(key);
@@ -188,7 +186,8 @@ static void free_symlinked_dirs(Watcher *watcher) {
186 }
187 }
188
191 -static char* get_path_from_wd(Watcher *watcher, int wd) {
189 +static char *get_path_from_wd(Watcher *watcher, int wd)
190 +{
191 for (int i = 0; i < watcher->watchCount; ++i) {
192 if (watcher->watchList[i].wd == wd)
193 return watcher->watchList[i].path;
@@ -196,7 +195,8 @@ static char* get_path_from_wd(Watcher *watcher, int wd) {
195 return NULL;
196 }
197
199 -static bool is_directory_watched(Watcher *watcher, const char *path) {
198 +static bool is_directory_watched(Watcher *watcher, const char *path)
199 +{
200 for (int i = 0; i < watcher->watchCount; ++i) {
201 if (watcher->watchList[i].wd != -1 && strcmp(watcher->watchList[i].path, path) == 0) {
202 return true;
@@ -205,7 +205,8 @@ static bool is_directory_watched(Watcher *watcher, const char *path) {
205 return false;
206 }
207
208 -static void watch_directory_and_subdirectories(Watcher *watcher, int inotifyFd, const char *basePath) {
208 +static void watch_directory_and_subdirectories(Watcher *watcher, int inotifyFd, const char *basePath)
209 +{
210 DICTIONARY *dirs = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
211
212 // First resolve any symlinks in the base path
@@ -215,10 +216,11 @@ static void watch_directory_and_subdirectories(Watcher *watcher, int inotifyFd,
216 strncpyz(real_path, basePath, sizeof(real_path));
217 }
218
218 - journal_directory_scan_recursively(NULL, dirs, real_path, 0);
219 + nd_journal_directory_scan_recursively(NULL, dirs, real_path, 0);
220
221 void *x;
221 - dfe_start_read(dirs, x) {
222 + dfe_start_read(dirs, x)
223 + {
224 const char *dirname = x_dfe.name;
225 char resolved_path[PATH_MAX];
226
@@ -240,7 +242,8 @@ static void watch_directory_and_subdirectories(Watcher *watcher, int inotifyFd,
242 dictionary_destroy(dirs);
243 }
244
243 -static bool is_subpath(const char *path, const char *subpath) {
245 +static bool is_subpath(const char *path, const char *subpath)
246 +{
247 // Use strncmp to compare the paths
248 if (strncmp(path, subpath, strlen(path)) == 0) {
249 // Ensure that the next character is a '/' or '\0'
@@ -251,48 +254,61 @@ static bool is_subpath(const char *path, const char *subpath) {
254 return false;
255 }
256
254 -void remove_directory_watch(Watcher *watcher, int inotifyFd, const char *dirPath) {
257 +void remove_directory_watch(Watcher *watcher, int inotifyFd, const char *dirPath)
258 +{
259 for (int i = 0; i < watcher->watchCount; ++i) {
260 WatchEntry *t = &watcher->watchList[i];
261 if (t->wd != -1 && is_subpath(dirPath, t->path)) {
258 - if(inotify_rm_watch(inotifyFd, t->wd) == -1)
259 - nd_log(NDLS_COLLECTORS, NDLP_ERR, "JOURNAL WATCHER: inotify_rm_watch() on path '%s' returned -1", t->path);
262 + if (inotify_rm_watch(inotifyFd, t->wd) == -1)
263 + nd_log(
264 + NDLS_COLLECTORS, NDLP_ERR, "JOURNAL WATCHER: inotify_rm_watch() on path '%s' returned -1", t->path);
265 else
266 nd_log(NDLS_COLLECTORS, NDLP_DEBUG, "JOURNAL WATCHER: stopped watching directory '%s'", t->path);
267 free_slot(watcher, t);
268 }
269 }
270
266 - struct journal_file *jf;
267 - dfe_start_write(journal_files_registry, jf) {
268 - if(is_subpath(dirPath, jf->filename))
269 - dictionary_del(journal_files_registry, jf->filename);
271 + struct nd_journal_file *njf;
272 + dfe_start_write(nd_journal_files_registry, njf)
273 + {
274 + if (is_subpath(dirPath, njf->filename))
275 + dictionary_del(nd_journal_files_registry, njf->filename);
276 }
271 - dfe_done(jf);
277 + dfe_done(njf);
278
273 - dictionary_garbage_collect(journal_files_registry);
279 + dictionary_garbage_collect(nd_journal_files_registry);
280 }
281
276 -void process_event(Watcher *watcher, int inotifyFd, struct inotify_event *event) {
282 +void process_event(Watcher *watcher, int inotifyFd, struct inotify_event *event)
283 +{
284 errno_clear();
285
279 - if(!event->len) {
286 + if (!event->len) {
287 CLEAN_BUFFER *wb = buffer_create(0, NULL);
288 INOTIFY_MASK_2buffer(wb, event->mask, ", ");
282 - nd_log(NDLS_COLLECTORS, NDLP_NOTICE,
283 - "JOURNAL WATCHER: received event with mask %u (%s) and len %u (this is zero) - ignoring it.",
284 - event->mask, buffer_tostring(wb), event->len);
289 + nd_log(
290 + NDLS_COLLECTORS,
291 + NDLP_NOTICE,
292 + "JOURNAL WATCHER: received event with mask %u (%s) and len %u (this is zero) - ignoring it.",
293 + event->mask,
294 + buffer_tostring(wb),
295 + event->len);
296 return;
297 }
298
299 char *dirPath = get_path_from_wd(watcher, event->wd);
289 - if(!dirPath) {
300 + if (!dirPath) {
301 CLEAN_BUFFER *wb = buffer_create(0, NULL);
302 INOTIFY_MASK_2buffer(wb, event->mask, ", ");
292 - nd_log(NDLS_COLLECTORS, NDLP_NOTICE,
293 - "JOURNAL WATCHER: received event with mask %u (%s) and len %u for path: '%s' - "
294 - "but we can't find its watch descriptor - ignoring it.",
295 - event->mask, buffer_tostring(wb), event->len, event->name);
303 + nd_log(
304 + NDLS_COLLECTORS,
305 + NDLP_NOTICE,
306 + "JOURNAL WATCHER: received event with mask %u (%s) and len %u for path: '%s' - "
307 + "but we can't find its watch descriptor - ignoring it.",
308 + event->mask,
309 + buffer_tostring(wb),
310 + event->len,
311 + event->name);
312 return;
313 }
314
@@ -306,7 +322,7 @@ void process_event(Watcher *watcher, int inotifyFd, struct inotify_event *event)
322 }
323 #endif
324
309 - if(event->mask & IN_DELETE_SELF) {
325 + if (event->mask & IN_DELETE_SELF) {
326 remove_watch(watcher, inotifyFd, event->wd);
327 return;
328 }
@@ -341,31 +357,35 @@ void process_event(Watcher *watcher, int inotifyFd, struct inotify_event *event)
357
358 // we leave fullPathString allocated, as it's now in the JudyL set
359
344 - nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
345 - "JOURNAL WATCHER: New symlinked directory created: '%s' -> '%s'",
346 - fullPath, resolved_path);
347 - }
348 - else if (string_strcmp(symlinked, resolved_path) != 0) {
360 + nd_log(
361 + NDLS_COLLECTORS,
362 + NDLP_DEBUG,
363 + "JOURNAL WATCHER: New symlinked directory created: '%s' -> '%s'",
364 + fullPath,
365 + resolved_path);
366 + } else if (string_strcmp(symlinked, resolved_path) != 0) {
367 SYMLINKED_DIRS_SET(
368 &watcher->symlinkedDirs, (uintptr_t)fullPathString, string_strdupz(resolved_path));
369
352 - nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
353 - "JOURNAL WATCHER: Updated symlinked directory: '%s' -> '%s' (was '%s')",
354 - fullPath, resolved_path, string2str(symlinked));
370 + nd_log(
371 + NDLS_COLLECTORS,
372 + NDLP_DEBUG,
373 + "JOURNAL WATCHER: Updated symlinked directory: '%s' -> '%s' (was '%s')",
374 + fullPath,
375 + resolved_path,
376 + string2str(symlinked));
377
378 string_freez(symlinked);
379
380 // we need to free this, since it was already in the JudyL set
381 string_freez(fullPathString);
360 - }
361 - else
382 + } else
383 string_freez(fullPathString); // we don't need it anymore
384 }
385 }
386 }
387 }
367 - }
368 - else if(event->mask & IN_DELETE) {
388 + } else if (event->mask & IN_DELETE) {
389 // Check if it was a symlink
390 STRING *fullPathString = string_strdupz(fullPath);
391 STRING *symlinked = SYMLINKED_DIRS_GET(&watcher->symlinkedDirs, (uintptr_t)fullPathString);
@@ -377,77 +397,84 @@ void process_event(Watcher *watcher, int inotifyFd, struct inotify_event *event)
397 string_freez(symlinked);
398 is_dir = true;
399
380 - nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
381 - "JOURNAL WATCHER: Deleted symlinked directory: '%s' -> '%s'",
382 - fullPath, resolved_path);
400 + nd_log(
401 + NDLS_COLLECTORS,
402 + NDLP_DEBUG,
403 + "JOURNAL WATCHER: Deleted symlinked directory: '%s' -> '%s'",
404 + fullPath,
405 + resolved_path);
406 }
407 string_freez(fullPathString); // the one we allocated above
408 }
409
387 - if(is_dir) {
410 + if (is_dir) {
411 if (event->mask & (IN_DELETE | IN_MOVED_FROM)) {
389 - nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
390 - "JOURNAL WATCHER: Directory deleted or moved out: '%s'",
391 - path_to_use);
412 + nd_log(NDLS_COLLECTORS, NDLP_DEBUG, "JOURNAL WATCHER: Directory deleted or moved out: '%s'", path_to_use);
413
414 remove_directory_watch(watcher, inotifyFd, path_to_use);
394 - }
395 - else if (event->mask & (IN_CREATE | IN_MOVED_TO)) {
396 - nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
397 - "JOURNAL WATCHER: New directory created or moved in: '%s'",
398 - path_to_use);
415 + } else if (event->mask & (IN_CREATE | IN_MOVED_TO)) {
416 + nd_log(
417 + NDLS_COLLECTORS, NDLP_DEBUG, "JOURNAL WATCHER: New directory created or moved in: '%s'", path_to_use);
418
419 watch_directory_and_subdirectories(watcher, inotifyFd, path_to_use);
401 - }
402 - else {
420 + } else {
421 CLEAN_BUFFER *wb = buffer_create(0, NULL);
422 INOTIFY_MASK_2buffer(wb, event->mask, ", ");
405 - nd_log(NDLS_COLLECTORS, NDLP_WARNING,
406 - "JOURNAL WATCHER: Received unhandled event with mask %u (%s) for directory '%s'",
407 - event->mask, buffer_tostring(wb), path_to_use);
423 + nd_log(
424 + NDLS_COLLECTORS,
425 + NDLP_WARNING,
426 + "JOURNAL WATCHER: Received unhandled event with mask %u (%s) for directory '%s'",
427 + event->mask,
428 + buffer_tostring(wb),
429 + path_to_use);
430 }
409 - }
410 - else if(is_journal_file(event->name, (ssize_t)strlen(event->name), NULL)) {
431 + } else if (is_journal_file(event->name, (ssize_t)strlen(event->name), NULL)) {
432 dictionary_set(watcher->pending, path_to_use, NULL, 0);
412 - }
413 - else {
433 + } else {
434 CLEAN_BUFFER *wb = buffer_create(0, NULL);
435 INOTIFY_MASK_2buffer(wb, event->mask, ", ");
416 - nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
417 - "JOURNAL WATCHER: ignoring event with mask %u (%s) for file '%s' ('%s')",
418 - event->mask, buffer_tostring(wb), path_to_use, fullPath);
436 + nd_log(
437 + NDLS_COLLECTORS,
438 + NDLP_DEBUG,
439 + "JOURNAL WATCHER: ignoring event with mask %u (%s) for file '%s' ('%s')",
440 + event->mask,
441 + buffer_tostring(wb),
442 + path_to_use,
443 + fullPath);
444 }
445 }
446
422 -static void process_pending(Watcher *watcher) {
447 +static void process_pending(Watcher *watcher)
448 +{
449 errno_clear();
450
451 void *x;
426 - dfe_start_write(watcher->pending, x) {
452 + dfe_start_write(watcher->pending, x)
453 + {
454 struct stat info;
455 const char *fullPath = x_dfe.name;
456
430 - if(stat(fullPath, &info) != 0) {
431 - nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
432 - "JOURNAL WATCHER: file '%s' no longer exists, removing it from the registry",
433 - fullPath);
434 -
435 - dictionary_del(journal_files_registry, fullPath);
436 - }
437 - else if(S_ISREG(info.st_mode)) {
438 -// nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
439 -// "JOURNAL WATCHER: file '%s' has been added/updated, updating the registry",
440 -// fullPath);
441 -
442 - struct journal_file t = {
443 - .file_last_modified_ut = info.st_mtim.tv_sec * USEC_PER_SEC +
444 - info.st_mtim.tv_nsec / NSEC_PER_USEC,
445 - .last_scan_monotonic_ut = now_monotonic_usec(),
446 - .size = info.st_size,
447 - .max_journal_vs_realtime_delta_ut = JOURNAL_VS_REALTIME_DELTA_DEFAULT_UT,
457 + if (stat(fullPath, &info) != 0) {
458 + nd_log(
459 + NDLS_COLLECTORS,
460 + NDLP_DEBUG,
461 + "JOURNAL WATCHER: file '%s' no longer exists, removing it from the registry",
462 + fullPath);
463 +
464 + dictionary_del(nd_journal_files_registry, fullPath);
465 + } else if (S_ISREG(info.st_mode)) {
466 + // nd_log(NDLS_COLLECTORS, NDLP_DEBUG,
467 + // "JOURNAL WATCHER: file '%s' has been added/updated, updating the registry",
468 + // fullPath);
469 +
470 + struct nd_journal_file t = {
471 + .file_last_modified_ut = info.st_mtim.tv_sec * USEC_PER_SEC + info.st_mtim.tv_nsec / NSEC_PER_USEC,
472 + .last_scan_monotonic_ut = now_monotonic_usec(),
473 + .size = info.st_size,
474 + .max_journal_vs_realtime_delta_ut = JOURNAL_VS_REALTIME_DELTA_DEFAULT_UT,
475 };
449 - struct journal_file *jf = dictionary_set(journal_files_registry, fullPath, &t, sizeof(t));
450 - journal_file_update_header(jf->filename, jf);
476 + struct nd_journal_file *jf = dictionary_set(nd_journal_files_registry, fullPath, &t, sizeof(t));
477 + nd_journal_file_update_header(jf->filename, jf);
478 }
479
480 dictionary_del(watcher->pending, fullPath);
@@ -459,11 +486,13 @@ static void process_pending(Watcher *watcher) {
486
487 size_t journal_watcher_wanted_session_id = 0;
488
462 -void journal_watcher_restart(void) {
489 +void nd_journal_watcher_restart(void)
490 +{
491 __atomic_add_fetch(&journal_watcher_wanted_session_id, 1, __ATOMIC_RELAXED);
492 }
493
466 -static bool process_inotify_events(struct buffered_reader *reader, Watcher *watcher, int inotifyFd) {
494 +static bool process_inotify_events(struct buffered_reader *reader, Watcher *watcher, int inotifyFd)
495 +{
496 errno_clear();
497
498 bool unmount_event = false;
@@ -473,20 +502,22 @@ static bool process_inotify_events(struct buffered_reader *reader, Watcher *watc
502 while (processed + (ssize_t)sizeof(struct inotify_event) <= reader->read_len) {
503 struct inotify_event *event = (struct inotify_event *)(reader->read_buffer + processed);
504
476 - if(event->len > NAME_MAX + 1) {
505 + if (event->len > NAME_MAX + 1) {
506 // The event length is impossibly large
478 - nd_log(NDLS_COLLECTORS, NDLP_ERR,
479 - "JOURNAL WATCHER: received impossibly large event length %u - restarting",
480 - event->len);
507 + nd_log(
508 + NDLS_COLLECTORS,
509 + NDLP_ERR,
510 + "JOURNAL WATCHER: received impossibly large event length %u - restarting",
511 + event->len);
512 return true; // force a restart
513 }
514
515 // Check if we have the complete event including the name
516 ssize_t total_size = (ssize_t)sizeof(struct inotify_event) + event->len;
517 if (processed + total_size > reader->read_len)
487 - break; // Wait for more data
518 + break; // Wait for more data
519
489 - if(event->mask & IN_UNMOUNT) {
520 + if (event->mask & IN_UNMOUNT) {
521 unmount_event = true;
522 break;
523 }
@@ -497,20 +528,18 @@ static bool process_inotify_events(struct buffered_reader *reader, Watcher *watc
528
529 // If we have unprocessed data, move it to the start
530 if (processed < reader->read_len) {
500 - memmove(reader->read_buffer,
501 - reader->read_buffer + processed,
502 - reader->read_len - processed);
531 + memmove(reader->read_buffer, reader->read_buffer + processed, reader->read_len - processed);
532 reader->read_len -= processed;
504 - }
505 - else
533 + } else
534 reader->read_len = 0;
535
536 reader->read_buffer[reader->read_len] = '\0';
537 return unmount_event;
538 }
539
512 -void *journal_watcher_main(void *arg __maybe_unused) {
513 - while(1) {
540 +void *nd_journal_watcher_main(void *arg __maybe_unused)
541 +{
542 + while (1) {
543 size_t journal_watcher_session_id = __atomic_load_n(&journal_watcher_wanted_session_id, __ATOMIC_RELAXED);
544
545 Watcher watcher = {
@@ -518,7 +547,7 @@ void *journal_watcher_main(void *arg __maybe_unused) {
547 .freeList = NULL,
548 .watchCount = 0,
549 .watchListSize = INITIAL_WATCHES,
521 - .pending = dictionary_create(DICT_OPTION_DONT_OVERWRITE_VALUE|DICT_OPTION_SINGLE_THREADED),
550 + .pending = dictionary_create(DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_SINGLE_THREADED),
551 .errors = 0,
552 };
553
@@ -530,7 +559,8 @@ void *journal_watcher_main(void *arg __maybe_unused) {
559 }
560
561 for (unsigned i = 0; i < MAX_JOURNAL_DIRECTORIES; i++) {
533 - if (!journal_directories[i].path) break;
562 + if (!journal_directories[i].path)
563 + break;
564 watch_directory_and_subdirectories(&watcher, inotifyFd, string2str(journal_directories[i].path));
565 }
566
@@ -539,31 +569,35 @@ void *journal_watcher_main(void *arg __maybe_unused) {
569 buffered_reader_init(&reader);
570
571 while (journal_watcher_session_id == __atomic_load_n(&journal_watcher_wanted_session_id, __ATOMIC_RELAXED)) {
542 - buffered_reader_ret_t rc = buffered_reader_read_timeout(
543 - &reader, inotifyFd, SYSTEMD_JOURNAL_EXECUTE_WATCHER_PENDING_EVERY_MS, false);
572 + buffered_reader_ret_t rc =
573 + buffered_reader_read_timeout(&reader, inotifyFd, ND_SD_JOURNAL_EXECUTE_WATCHER_PENDING_EVERY_MS, false);
574
545 - if(rc == BUFFERED_READER_READ_OK || rc == BUFFERED_READER_READ_BUFFER_FULL) {
575 + if (rc == BUFFERED_READER_READ_OK || rc == BUFFERED_READER_READ_BUFFER_FULL) {
576 if (process_inotify_events(&reader, &watcher, inotifyFd))
577 break;
548 - }
549 - else if (rc != BUFFERED_READER_READ_POLL_TIMEOUT) {
550 - nd_log(NDLS_COLLECTORS, NDLP_ERR,
551 - "JOURNAL WATCHER: cannot read inotify events, buffered_reader_read_timeout() returned %d - "
552 - "restarting the watcher.",
553 - rc);
578 + } else if (rc != BUFFERED_READER_READ_POLL_TIMEOUT) {
579 + nd_log(
580 + NDLS_COLLECTORS,
581 + NDLP_ERR,
582 + "JOURNAL WATCHER: cannot read inotify events, buffered_reader_read_timeout() returned %d - "
583 + "restarting the watcher.",
584 + rc);
585 break;
586 }
587
588 usec_t ut = now_monotonic_usec();
558 - if (dictionary_entries(watcher.pending) && (rc == BUFFERED_READER_READ_POLL_TIMEOUT ||
559 - last_headers_update_ut + (SYSTEMD_JOURNAL_EXECUTE_WATCHER_PENDING_EVERY_MS * USEC_PER_MS) <= ut)) {
589 + if (dictionary_entries(watcher.pending) &&
590 + (rc == BUFFERED_READER_READ_POLL_TIMEOUT ||
591 + last_headers_update_ut + (ND_SD_JOURNAL_EXECUTE_WATCHER_PENDING_EVERY_MS * USEC_PER_MS) <= ut)) {
592 process_pending(&watcher);
593 last_headers_update_ut = ut;
594 }
595
564 - if(watcher.errors) {
565 - nd_log(NDLS_COLLECTORS, NDLP_NOTICE,
566 - "JOURNAL WATCHER: there were errors in setting up inotify watches - restarting the watcher.");
596 + if (watcher.errors) {
597 + nd_log(
598 + NDLS_COLLECTORS,
599 + NDLP_NOTICE,
600 + "JOURNAL WATCHER: there were errors in setting up inotify watches - restarting the watcher.");
601 }
602 }
603
@@ -572,7 +606,7 @@ void *journal_watcher_main(void *arg __maybe_unused) {
606 free_symlinked_dirs(&watcher);
607
608 // this will scan the directories and cleanup the registry
575 - journal_files_registry_update();
609 + nd_journal_files_registry_update();
610
611 sleep_usec(2 * USEC_PER_SEC);
612 }
src/collectors/systemd-journal.plugin/systemd-journal.c
+413 -438
@@ -8,10 +8,10 @@
8
9 #include "systemd-internals.h"
10
11 -#define SYSTEMD_JOURNAL_FUNCTION_DESCRIPTION "View, search and analyze systemd journal entries."
12 -#define SYSTEMD_JOURNAL_FUNCTION_NAME "systemd-journal"
13 -#define SYSTEMD_JOURNAL_SAMPLING_SLOTS 1000
14 -#define SYSTEMD_JOURNAL_SAMPLING_RECALIBRATE 10000
11 +#define ND_SD_JOURNAL_FUNCTION_DESCRIPTION "View, search and analyze systemd journal entries."
12 +#define ND_SD_JOURNAL_FUNCTION_NAME "systemd-journal"
13 +#define ND_SD_JOURNAL_SAMPLING_SLOTS 1000
14 +#define ND_SD_JOURNAL_SAMPLING_RECALIBRATE 10000
15
16 #ifdef HAVE_SD_JOURNAL_RESTART_FIELDS
17 #define LQS_DEFAULT_SLICE_MODE 1
@@ -56,8 +56,8 @@ struct lqs_extension {
56 usec_t end_ut;
57 usec_t step_ut;
58 uint32_t enable_after_samples;
59 - uint32_t sampled[SYSTEMD_JOURNAL_SAMPLING_SLOTS];
60 - uint32_t unsampled[SYSTEMD_JOURNAL_SAMPLING_SLOTS];
59 + uint32_t sampled[ND_SD_JOURNAL_SAMPLING_SLOTS];
60 + uint32_t unsampled[ND_SD_JOURNAL_SAMPLING_SLOTS];
61 } samples_per_time_slot;
62
63 // per file progress info
@@ -73,176 +73,148 @@ struct lqs_extension {
73 };
74
75 // prepare LQS
76 -#define LQS_FUNCTION_NAME SYSTEMD_JOURNAL_FUNCTION_NAME
77 -#define LQS_FUNCTION_DESCRIPTION SYSTEMD_JOURNAL_FUNCTION_DESCRIPTION
76 +#define LQS_FUNCTION_NAME ND_SD_JOURNAL_FUNCTION_NAME
77 +#define LQS_FUNCTION_DESCRIPTION ND_SD_JOURNAL_FUNCTION_DESCRIPTION
78 #define LQS_DEFAULT_ITEMS_PER_QUERY 200
79 -#define LQS_DEFAULT_ITEMS_SAMPLING 1000000
80 -#define LQS_SOURCE_TYPE SD_JOURNAL_FILE_SOURCE_TYPE
81 -#define LQS_SOURCE_TYPE_ALL SDJF_ALL
82 -#define LQS_SOURCE_TYPE_NONE SDJF_NONE
83 -#define LQS_PARAMETER_SOURCE_NAME "Journal Sources" // this is how it is shown to users
79 +#define LQS_DEFAULT_ITEMS_SAMPLING 1000000
80 +#define LQS_SOURCE_TYPE SD_JOURNAL_FILE_SOURCE_TYPE
81 +#define LQS_SOURCE_TYPE_ALL ND_SD_JF_ALL
82 +#define LQS_SOURCE_TYPE_NONE ND_SD_JF_NONE
83 +#define LQS_PARAMETER_SOURCE_NAME "Journal Sources" // this is how it is shown to users
84 #define LQS_FUNCTION_GET_INTERNAL_SOURCE_TYPE(value) get_internal_source_type(value)
85 #define LQS_FUNCTION_SOURCE_TO_JSON_ARRAY(wb) available_journal_file_sources_to_json_array(wb)
86 #include "libnetdata/facets/logs_query_status.h"
87
88 #include "systemd-journal-sampling.h"
89
90 -#define FACET_MAX_VALUE_LENGTH 8192
91 -#define SYSTEMD_JOURNAL_DEFAULT_TIMEOUT 60
92 -#define SYSTEMD_JOURNAL_PROGRESS_EVERY_UT (250 * USEC_PER_MS)
93 -#define JOURNAL_KEY_ND_JOURNAL_FILE "ND_JOURNAL_FILE"
94 -#define JOURNAL_KEY_ND_JOURNAL_PROCESS "ND_JOURNAL_PROCESS"
95 -#define JOURNAL_DEFAULT_DIRECTION FACETS_ANCHOR_DIRECTION_BACKWARD
96 -#define SYSTEMD_ALWAYS_VISIBLE_KEYS NULL
97 -
98 -#define SYSTEMD_KEYS_EXCLUDED_FROM_FACETS \
99 - "!MESSAGE_ID" \
100 - "|*MESSAGE*" \
101 - "|*TIMESTAMP*" \
102 - "|__*" \
90 +#define FACET_MAX_VALUE_LENGTH 8192
91 +#define ND_SD_JOURNAL_DEFAULT_TIMEOUT 60
92 +#define ND_SD_JOURNAL_PROGRESS_EVERY_UT (250 * USEC_PER_MS)
93 +#define JOURNAL_KEY_ND_JOURNAL_FILE "ND_JOURNAL_FILE"
94 +#define JOURNAL_KEY_ND_JOURNAL_PROCESS "ND_JOURNAL_PROCESS"
95 +#define JOURNAL_DEFAULT_DIRECTION FACETS_ANCHOR_DIRECTION_BACKWARD
96 +#define SYSTEMD_ALWAYS_VISIBLE_KEYS NULL
97 +
98 +#define SYSTEMD_KEYS_EXCLUDED_FROM_FACETS \
99 + "!MESSAGE_ID" \
100 + "|*MESSAGE*" \
101 + "|*TIMESTAMP*" \
102 + "|__*" \
103 ""
104
105 -#define SYSTEMD_KEYS_INCLUDED_IN_FACETS \
106 - \
107 - /* --- USER JOURNAL FIELDS --- */ \
108 - \
109 - /* "|MESSAGE" */ \
110 - "|MESSAGE_ID" \
111 - "|PRIORITY" \
112 - "|CODE_FILE" \
113 - /* "|CODE_LINE" */ \
114 - "|CODE_FUNC" \
115 - "|ERRNO" \
116 - /* "|INVOCATION_ID" */ \
117 - /* "|USER_INVOCATION_ID" */ \
118 - "|SYSLOG_FACILITY" \
119 - "|SYSLOG_IDENTIFIER" \
120 - /* "|SYSLOG_PID" */ \
121 - /* "|SYSLOG_TIMESTAMP" */ \
122 - /* "|SYSLOG_RAW" */ \
123 - /* "!DOCUMENTATION" */ \
124 - /* "|TID" */ \
125 - "|UNIT" \
126 - "|USER_UNIT" \
127 - "|UNIT_RESULT" /* undocumented */ \
128 - \
129 - \
130 - /* --- TRUSTED JOURNAL FIELDS --- */ \
131 - \
132 - /* "|_PID" */ \
133 - "|_UID" \
134 - "|_GID" \
135 - "|_COMM" \
136 - "|_EXE" \
137 - /* "|_CMDLINE" */ \
138 - "|_CAP_EFFECTIVE" \
139 - /* "|_AUDIT_SESSION" */ \
140 - "|_AUDIT_LOGINUID" \
141 - "|_SYSTEMD_CGROUP" \
142 - "|_SYSTEMD_SLICE" \
143 - "|_SYSTEMD_UNIT" \
144 - "|_SYSTEMD_USER_UNIT" \
145 - "|_SYSTEMD_USER_SLICE" \
146 - "|_SYSTEMD_SESSION" \
147 - "|_SYSTEMD_OWNER_UID" \
148 - "|_SELINUX_CONTEXT" \
149 - /* "|_SOURCE_REALTIME_TIMESTAMP" */ \
150 - "|_BOOT_ID" \
151 - "|_MACHINE_ID" \
152 - /* "|_SYSTEMD_INVOCATION_ID" */ \
153 - "|_HOSTNAME" \
154 - "|_TRANSPORT" \
155 - "|_STREAM_ID" \
156 - /* "|LINE_BREAK" */ \
157 - "|_NAMESPACE" \
158 - "|_RUNTIME_SCOPE" \
159 - \
160 - \
161 - /* --- KERNEL JOURNAL FIELDS --- */ \
162 - \
163 - /* "|_KERNEL_DEVICE" */ \
164 - "|_KERNEL_SUBSYSTEM" \
165 - /* "|_UDEV_SYSNAME" */ \
166 - "|_UDEV_DEVNODE" \
167 - /* "|_UDEV_DEVLINK" */ \
168 - \
169 - \
170 - /* --- LOGGING ON BEHALF --- */ \
171 - \
172 - "|OBJECT_UID" \
173 - "|OBJECT_GID" \
174 - "|OBJECT_COMM" \
175 - "|OBJECT_EXE" \
176 - /* "|OBJECT_CMDLINE" */ \
177 - /* "|OBJECT_AUDIT_SESSION" */ \
178 - "|OBJECT_AUDIT_LOGINUID" \
179 - "|OBJECT_SYSTEMD_CGROUP" \
180 - "|OBJECT_SYSTEMD_SESSION" \
181 - "|OBJECT_SYSTEMD_OWNER_UID" \
182 - "|OBJECT_SYSTEMD_UNIT" \
183 - "|OBJECT_SYSTEMD_USER_UNIT" \
184 - \
185 - \
186 - /* --- CORE DUMPS --- */ \
187 - \
188 - "|COREDUMP_COMM" \
189 - "|COREDUMP_UNIT" \
190 - "|COREDUMP_USER_UNIT" \
191 - "|COREDUMP_SIGNAL_NAME" \
192 - "|COREDUMP_CGROUP" \
193 - \
194 - \
195 - /* --- DOCKER --- */ \
196 - \
197 - "|CONTAINER_ID" \
198 - /* "|CONTAINER_ID_FULL" */ \
199 - "|CONTAINER_NAME" \
200 - "|CONTAINER_TAG" \
201 - "|IMAGE_NAME" /* undocumented */ \
202 - /* "|CONTAINER_PARTIAL_MESSAGE" */ \
203 - \
204 - \
205 - /* --- NETDATA --- */ \
206 - \
207 - "|ND_NIDL_NODE" \
208 - "|ND_NIDL_CONTEXT" \
209 - "|ND_LOG_SOURCE" \
210 - /*"|ND_MODULE" */ \
211 - "|ND_ALERT_NAME" \
212 - "|ND_ALERT_CLASS" \
213 - "|ND_ALERT_COMPONENT" \
214 - "|ND_ALERT_TYPE" \
215 - "|ND_ALERT_STATUS" \
216 - \
105 +#define SYSTEMD_KEYS_INCLUDED_IN_FACETS \
106 + \
107 + /* --- USER JOURNAL FIELDS --- */ \
108 + \
109 + /* "|MESSAGE" */ \
110 + "|MESSAGE_ID" \
111 + "|PRIORITY" \
112 + "|CODE_FILE" /* "|CODE_LINE" */ \
113 + "|CODE_FUNC" \
114 + "|ERRNO" /* "|INVOCATION_ID" */ /* "|USER_INVOCATION_ID" */ \
115 + "|SYSLOG_FACILITY" \
116 + "|SYSLOG_IDENTIFIER" /* "|SYSLOG_PID" */ /* "|SYSLOG_TIMESTAMP" */ /* "|SYSLOG_RAW" */ /* "!DOCUMENTATION" */ /* "|TID" */ \
117 + "|UNIT" \
118 + "|USER_UNIT" \
119 + "|UNIT_RESULT" /* undocumented */ \
120 + \
121 + /* --- TRUSTED JOURNAL FIELDS --- */ \
122 + \
123 + /* "|_PID" */ \
124 + "|_UID" \
125 + "|_GID" \
126 + "|_COMM" \
127 + "|_EXE" /* "|_CMDLINE" */ \
128 + "|_CAP_EFFECTIVE" /* "|_AUDIT_SESSION" */ \
129 + "|_AUDIT_LOGINUID" \
130 + "|_SYSTEMD_CGROUP" \
131 + "|_SYSTEMD_SLICE" \
132 + "|_SYSTEMD_UNIT" \
133 + "|_SYSTEMD_USER_UNIT" \
134 + "|_SYSTEMD_USER_SLICE" \
135 + "|_SYSTEMD_SESSION" \
136 + "|_SYSTEMD_OWNER_UID" \
137 + "|_SELINUX_CONTEXT" /* "|_SOURCE_REALTIME_TIMESTAMP" */ \
138 + "|_BOOT_ID" \
139 + "|_MACHINE_ID" /* "|_SYSTEMD_INVOCATION_ID" */ \
140 + "|_HOSTNAME" \
141 + "|_TRANSPORT" \
142 + "|_STREAM_ID" /* "|LINE_BREAK" */ \
143 + "|_NAMESPACE" \
144 + "|_RUNTIME_SCOPE" \
145 + \
146 + /* --- KERNEL JOURNAL FIELDS --- */ \
147 + \
148 + /* "|_KERNEL_DEVICE" */ \
149 + "|_KERNEL_SUBSYSTEM" /* "|_UDEV_SYSNAME" */ \
150 + "|_UDEV_DEVNODE" /* "|_UDEV_DEVLINK" */ \
151 + \
152 + /* --- LOGGING ON BEHALF --- */ \
153 + \
154 + "|OBJECT_UID" \
155 + "|OBJECT_GID" \
156 + "|OBJECT_COMM" \
157 + "|OBJECT_EXE" /* "|OBJECT_CMDLINE" */ /* "|OBJECT_AUDIT_SESSION" */ \
158 + "|OBJECT_AUDIT_LOGINUID" \
159 + "|OBJECT_SYSTEMD_CGROUP" \
160 + "|OBJECT_SYSTEMD_SESSION" \
161 + "|OBJECT_SYSTEMD_OWNER_UID" \
162 + "|OBJECT_SYSTEMD_UNIT" \
163 + "|OBJECT_SYSTEMD_USER_UNIT" \
164 + \
165 + /* --- CORE DUMPS --- */ \
166 + \
167 + "|COREDUMP_COMM" \
168 + "|COREDUMP_UNIT" \
169 + "|COREDUMP_USER_UNIT" \
170 + "|COREDUMP_SIGNAL_NAME" \
171 + "|COREDUMP_CGROUP" \
172 + \
173 + /* --- DOCKER --- */ \
174 + \
175 + "|CONTAINER_ID" /* "|CONTAINER_ID_FULL" */ \
176 + "|CONTAINER_NAME" \
177 + "|CONTAINER_TAG" \
178 + "|IMAGE_NAME" /* undocumented */ /* "|CONTAINER_PARTIAL_MESSAGE" */ \
179 + \
180 + /* --- NETDATA --- */ \
181 + \
182 + "|ND_NIDL_NODE" \
183 + "|ND_NIDL_CONTEXT" \
184 + "|ND_LOG_SOURCE" /*"|ND_MODULE" */ \
185 + "|ND_ALERT_NAME" \
186 + "|ND_ALERT_CLASS" \
187 + "|ND_ALERT_COMPONENT" \
188 + "|ND_ALERT_TYPE" \
189 + "|ND_ALERT_STATUS" \
190 + \
191 ""
192
219 -// ----------------------------------------------------------------------------
220 -
221 -static SD_JOURNAL_FILE_SOURCE_TYPE get_internal_source_type(const char *value) {
222 - if(strcmp(value, SDJF_SOURCE_ALL_NAME) == 0)
223 - return SDJF_ALL;
224 - else if(strcmp(value, SDJF_SOURCE_LOCAL_NAME) == 0)
225 - return SDJF_LOCAL_ALL;
226 - else if(strcmp(value, SDJF_SOURCE_REMOTES_NAME) == 0)
227 - return SDJF_REMOTE_ALL;
228 - else if(strcmp(value, SDJF_SOURCE_NAMESPACES_NAME) == 0)
229 - return SDJF_LOCAL_NAMESPACE;
230 - else if(strcmp(value, SDJF_SOURCE_LOCAL_SYSTEM_NAME) == 0)
231 - return SDJF_LOCAL_SYSTEM;
232 - else if(strcmp(value, SDJF_SOURCE_LOCAL_USERS_NAME) == 0)
233 - return SDJF_LOCAL_USER;
234 - else if(strcmp(value, SDJF_SOURCE_LOCAL_OTHER_NAME) == 0)
235 - return SDJF_LOCAL_OTHER;
236 -
237 - return SDJF_NONE;
193 +static SD_JOURNAL_FILE_SOURCE_TYPE get_internal_source_type(const char *value)
194 +{
195 + if (strcmp(value, ND_SD_JF_SOURCE_ALL_NAME) == 0)
196 + return ND_SD_JF_ALL;
197 + else if (strcmp(value, ND_SD_JF_SOURCE_LOCAL_NAME) == 0)
198 + return ND_SD_JF_LOCAL_ALL;
199 + else if (strcmp(value, ND_SD_JF_SOURCE_REMOTES_NAME) == 0)
200 + return ND_SD_JF_REMOTE_ALL;
201 + else if (strcmp(value, ND_SD_JF_SOURCE_NAMESPACES_NAME) == 0)
202 + return ND_SD_JF_LOCAL_NAMESPACE;
203 + else if (strcmp(value, ND_SD_JF_SOURCE_LOCAL_SYSTEM_NAME) == 0)
204 + return ND_SD_JF_LOCAL_SYSTEM;
205 + else if (strcmp(value, ND_SD_JF_SOURCE_LOCAL_USERS_NAME) == 0)
206 + return ND_SD_JF_LOCAL_USER;
207 + else if (strcmp(value, ND_SD_JF_SOURCE_LOCAL_OTHER_NAME) == 0)
208 + return ND_SD_JF_LOCAL_OTHER;
209 +
210 + return ND_SD_JF_NONE;
211 }
212
240 -// ----------------------------------------------------------------------------
241 -
242 -static inline bool netdata_systemd_journal_seek_to(sd_journal *j, usec_t timestamp) {
243 - if(sd_journal_seek_realtime_usec(j, timestamp) < 0) {
213 +static inline bool nd_sd_journal_seek_to(sd_journal *j, usec_t timestamp)
214 +{
215 + if (sd_journal_seek_realtime_usec(j, timestamp) < 0) {
216 netdata_log_error("SYSTEMD-JOURNAL: Failed to seek to %" PRIu64, timestamp);
245 - if(sd_journal_seek_tail(j) < 0) {
217 + if (sd_journal_seek_tail(j) < 0) {
218 netdata_log_error("SYSTEMD-JOURNAL: Failed to seek to journal's tail");
219 return false;
220 }
@@ -253,50 +225,64 @@ static inline bool netdata_systemd_journal_seek_to(sd_journal *j, usec_t timesta
225
226 #define JD_SOURCE_REALTIME_TIMESTAMP "_SOURCE_REALTIME_TIMESTAMP"
227
256 -// ----------------------------------------------------------------------------
257 -
258 -static inline size_t netdata_systemd_journal_process_row(sd_journal *j, FACETS *facets, struct journal_file *jf, usec_t *msg_ut) {
228 +static inline size_t
229 +nd_sd_journal_process_row(sd_journal *j, FACETS *facets, struct nd_journal_file *njf, usec_t *msg_ut)
230 +{
231 const void *data;
232 size_t length, bytes = 0;
233
262 - facets_add_key_value_length(facets, JOURNAL_KEY_ND_JOURNAL_FILE, sizeof(JOURNAL_KEY_ND_JOURNAL_FILE) - 1, jf->filename, jf->filename_len);
234 + facets_add_key_value_length(
235 + facets, JOURNAL_KEY_ND_JOURNAL_FILE, sizeof(JOURNAL_KEY_ND_JOURNAL_FILE) - 1, njf->filename, njf->filename_len);
236
264 - SD_JOURNAL_FOREACH_DATA(j, data, length) {
237 + SD_JOURNAL_FOREACH_DATA(j, data, length)
238 + {
239 const char *key, *value;
240 size_t key_length, value_length;
241
268 - if(!parse_journal_field(data, length, &key, &key_length, &value, &value_length))
242 + if (!parse_journal_field(data, length, &key, &key_length, &value, &value_length))
243 continue;
244
245 #ifdef NETDATA_INTERNAL_CHECKS
246 usec_t origin_journal_ut = *msg_ut;
247 #endif
274 - if(unlikely(key_length == sizeof(JD_SOURCE_REALTIME_TIMESTAMP) - 1 &&
275 - memcmp(key, JD_SOURCE_REALTIME_TIMESTAMP, sizeof(JD_SOURCE_REALTIME_TIMESTAMP) - 1) == 0)) {
248 + if (unlikely(
249 + key_length == sizeof(JD_SOURCE_REALTIME_TIMESTAMP) - 1 &&
250 + memcmp(key, JD_SOURCE_REALTIME_TIMESTAMP, sizeof(JD_SOURCE_REALTIME_TIMESTAMP) - 1) == 0)) {
251 usec_t ut = str2ull(value, NULL);
277 - if(ut && ut < *msg_ut) {
252 + if (ut && ut < *msg_ut) {
253 usec_t delta = *msg_ut - ut;
254 *msg_ut = ut;
255
281 - if(delta > JOURNAL_VS_REALTIME_DELTA_MAX_UT)
256 + if (delta > JOURNAL_VS_REALTIME_DELTA_MAX_UT)
257 delta = JOURNAL_VS_REALTIME_DELTA_MAX_UT;
258
259 // update max_journal_vs_realtime_delta_ut if the delta increased
285 - usec_t expected = jf->max_journal_vs_realtime_delta_ut;
260 + usec_t expected = njf->max_journal_vs_realtime_delta_ut;
261 do {
287 - if(delta <= expected)
262 + if (delta <= expected)
263 break;
289 - } while(!__atomic_compare_exchange_n(&jf->max_journal_vs_realtime_delta_ut, &expected, delta, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED));
290 -
291 - internal_error(delta > expected,
292 - "increased max_journal_vs_realtime_delta_ut from %"PRIu64" to %"PRIu64", "
293 - "journal %"PRIu64", actual %"PRIu64" (delta %"PRIu64")"
294 - , expected, delta, origin_journal_ut, *msg_ut, origin_journal_ut - (*msg_ut));
264 + } while (!__atomic_compare_exchange_n(
265 + &njf->max_journal_vs_realtime_delta_ut, &expected, delta, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED));
266 +
267 + internal_error(
268 + delta > expected,
269 + "increased max_journal_vs_realtime_delta_ut from %" PRIu64 " to %" PRIu64 ", "
270 + "journal %" PRIu64 ", actual %" PRIu64 " (delta %" PRIu64 ")",
271 + expected,
272 + delta,
273 + origin_journal_ut,
274 + *msg_ut,
275 + origin_journal_ut - (*msg_ut));
276 }
277 }
278
279 bytes += length;
299 - facets_add_key_value_length(facets, key, key_length, value, value_length <= FACET_MAX_VALUE_LENGTH ? value_length : FACET_MAX_VALUE_LENGTH);
280 + facets_add_key_value_length(
281 + facets,
282 + key,
283 + key_length,
284 + value,
285 + value_length <= FACET_MAX_VALUE_LENGTH ? value_length : FACET_MAX_VALUE_LENGTH);
286 }
287
288 return bytes;
@@ -307,13 +293,14 @@ static inline size_t netdata_systemd_journal_process_row(sd_journal *j, FACETS *
293 #define FUNCTION_PROGRESS_EVERY_ROWS (1ULL << 13)
294 #define FUNCTION_DATA_ONLY_CHECK_EVERY_ROWS (1ULL << 7)
295
310 -static inline ND_SD_JOURNAL_STATUS check_stop(const bool *cancelled, const usec_t *stop_monotonic_ut) {
311 - if(cancelled && __atomic_load_n(cancelled, __ATOMIC_RELAXED)) {
296 +static inline ND_SD_JOURNAL_STATUS check_stop(const bool *cancelled, const usec_t *stop_monotonic_ut)
297 +{
298 + if (cancelled && __atomic_load_n(cancelled, __ATOMIC_RELAXED)) {
299 internal_error(true, "Function has been cancelled");
300 return ND_SD_JOURNAL_CANCELLED;
301 }
302
316 - if(now_monotonic_usec() > __atomic_load_n(stop_monotonic_ut, __ATOMIC_RELAXED)) {
303 + if (now_monotonic_usec() > __atomic_load_n(stop_monotonic_ut, __ATOMIC_RELAXED)) {
304 internal_error(true, "Function timed out");
305 return ND_SD_JOURNAL_TIMED_OUT;
306 }
@@ -321,12 +308,14 @@ static inline ND_SD_JOURNAL_STATUS check_stop(const bool *cancelled, const usec_
308 return ND_SD_JOURNAL_OK;
309 }
310
324 -ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_backward(
325 - sd_journal *j, BUFFER *wb __maybe_unused, FACETS *facets,
326 - struct journal_file *jf,
327 - LOGS_QUERY_STATUS *fqs) {
328 -
329 - usec_t anchor_delta = __atomic_load_n(&jf->max_journal_vs_realtime_delta_ut, __ATOMIC_RELAXED);
311 +ND_SD_JOURNAL_STATUS nd_sd_journal_query_backward(
312 + sd_journal *j,
313 + BUFFER *wb __maybe_unused,
314 + FACETS *facets,
315 + struct nd_journal_file *njf,
316 + LOGS_QUERY_STATUS *fqs)
317 +{
318 + usec_t anchor_delta = __atomic_load_n(&njf->max_journal_vs_realtime_delta_ut, __ATOMIC_RELAXED);
319 lqs_query_timeframe(fqs, anchor_delta);
320 usec_t start_ut = fqs->query.start_ut;
321 usec_t stop_ut = fqs->query.stop_ut;
@@ -335,12 +324,12 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_backward(
324 fqs->c.query_file.start_ut = start_ut;
325 fqs->c.query_file.stop_ut = stop_ut;
326
338 - if(!netdata_systemd_journal_seek_to(j, start_ut))
327 + if (!nd_sd_journal_seek_to(j, start_ut))
328 return ND_SD_JOURNAL_FAILED_TO_SEEK;
329
330 size_t errors_no_timestamp = 0;
331 usec_t latest_msg_ut = 0; // the biggest timestamp we have seen so far
343 - usec_t first_msg_ut = 0; // the first message we got from the db
332 + usec_t first_msg_ut = 0; // the first message we got from the db
333 size_t row_counter = 0, last_row_counter = 0, rows_useful = 0;
334 size_t bytes = 0, last_bytes = 0;
335
@@ -352,7 +341,7 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_backward(
341 facets_rows_begin(facets);
342 while (status == ND_SD_JOURNAL_OK && sd_journal_previous(j) > 0) {
343 usec_t msg_ut = 0;
355 - if(sd_journal_get_realtime_usec(j, &msg_ut) < 0 || !msg_ut) {
344 + if (sd_journal_get_realtime_usec(j, &msg_ut) < 0 || !msg_ut) {
345 errors_no_timestamp++;
346 continue;
347 }
@@ -363,48 +352,48 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_backward(
352 if (unlikely(msg_ut < stop_ut))
353 break;
354
366 - if(unlikely(msg_ut > latest_msg_ut))
355 + if (unlikely(msg_ut > latest_msg_ut))
356 latest_msg_ut = msg_ut;
357
369 - if(unlikely(!first_msg_ut)) {
358 + if (unlikely(!first_msg_ut)) {
359 first_msg_ut = msg_ut;
360 fqs->c.query_file.first_msg_ut = msg_ut;
361
362 #ifdef HAVE_SD_JOURNAL_GET_SEQNUM
374 - if(sd_journal_get_seqnum(j, &fqs->c.query_file.first_msg_seqnum, &fqs->c.query_file.first_msg_writer) < 0) {
363 + if (sd_journal_get_seqnum(j, &fqs->c.query_file.first_msg_seqnum, &fqs->c.query_file.first_msg_writer) <
364 + 0) {
365 fqs->c.query_file.first_msg_seqnum = 0;
366 fqs->c.query_file.first_msg_writer = SD_ID128_NULL;
367 }
368 #endif
369 }
370
381 - sampling_t sample = is_row_in_sample(j, fqs, jf, msg_ut,
382 - FACETS_ANCHOR_DIRECTION_BACKWARD,
383 - facets_row_candidate_to_keep(facets, msg_ut));
371 + sampling_t sample = is_row_in_sample(
372 + j, fqs, njf, msg_ut, FACETS_ANCHOR_DIRECTION_BACKWARD, facets_row_candidate_to_keep(facets, msg_ut));
373
385 - if(sample == SAMPLING_FULL) {
386 - bytes += netdata_systemd_journal_process_row(j, facets, jf, &msg_ut);
374 + if (sample == SAMPLING_FULL) {
375 + bytes += nd_sd_journal_process_row(j, facets, njf, &msg_ut);
376
377 // make sure each line gets a unique timestamp
389 - if(unlikely(msg_ut >= last_usec_from && msg_ut <= last_usec_to))
378 + if (unlikely(msg_ut >= last_usec_from && msg_ut <= last_usec_to))
379 msg_ut = --last_usec_from;
380 else
381 last_usec_from = last_usec_to = msg_ut;
382
394 - if(facets_row_finished(facets, msg_ut))
383 + if (facets_row_finished(facets, msg_ut))
384 rows_useful++;
385
386 row_counter++;
398 - if(unlikely((row_counter % FUNCTION_DATA_ONLY_CHECK_EVERY_ROWS) == 0 &&
399 - stop_when_full &&
400 - facets_rows(facets) >= fqs->rq.entries)) {
387 + if (unlikely(
388 + (row_counter % FUNCTION_DATA_ONLY_CHECK_EVERY_ROWS) == 0 && stop_when_full &&
389 + facets_rows(facets) >= fqs->rq.entries)) {
390 // stop the data only query
391 usec_t oldest = facets_row_oldest_ut(facets);
403 - if(oldest && msg_ut < (oldest - anchor_delta))
392 + if (oldest && msg_ut < (oldest - anchor_delta))
393 break;
394 }
395
407 - if(unlikely(row_counter % FUNCTION_PROGRESS_EVERY_ROWS == 0)) {
396 + if (unlikely(row_counter % FUNCTION_PROGRESS_EVERY_ROWS == 0)) {
397 FUNCTION_PROGRESS_UPDATE_ROWS(fqs->c.rows_read, row_counter - last_row_counter);
398 last_row_counter = row_counter;
399
@@ -413,11 +402,10 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_backward(
402
403 status = check_stop(fqs->cancelled, fqs->stop_monotonic_ut);
404 }
416 - }
417 - else if(sample == SAMPLING_SKIP_FIELDS)
405 + } else if (sample == SAMPLING_SKIP_FIELDS)
406 facets_row_finished_unsampled(facets, msg_ut);
407 else {
420 - sampling_update_running_query_file_estimates(facets, j, fqs, jf, msg_ut, FACETS_ANCHOR_DIRECTION_BACKWARD);
408 + sampling_update_running_query_file_estimates(facets, j, fqs, njf, msg_ut, FACETS_ANCHOR_DIRECTION_BACKWARD);
409 break;
410 }
411 }
@@ -427,21 +415,23 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_backward(
415
416 fqs->c.rows_useful += rows_useful;
417
430 - if(errors_no_timestamp)
418 + if (errors_no_timestamp)
419 netdata_log_error("SYSTEMD-JOURNAL: %zu lines did not have timestamps", errors_no_timestamp);
420
433 - if(latest_msg_ut > fqs->last_modified)
421 + if (latest_msg_ut > fqs->last_modified)
422 fqs->last_modified = latest_msg_ut;
423
424 return status;
425 }
426
439 -ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_forward(
440 - sd_journal *j, BUFFER *wb __maybe_unused, FACETS *facets,
441 - struct journal_file *jf,
442 - LOGS_QUERY_STATUS *fqs) {
443 -
444 - usec_t anchor_delta = __atomic_load_n(&jf->max_journal_vs_realtime_delta_ut, __ATOMIC_RELAXED);
427 +ND_SD_JOURNAL_STATUS nd_sd_journal_query_forward(
428 + sd_journal *j,
429 + BUFFER *wb __maybe_unused,
430 + FACETS *facets,
431 + struct nd_journal_file *njf,
432 + LOGS_QUERY_STATUS *fqs)
433 +{
434 + usec_t anchor_delta = __atomic_load_n(&njf->max_journal_vs_realtime_delta_ut, __ATOMIC_RELAXED);
435 lqs_query_timeframe(fqs, anchor_delta);
436 usec_t start_ut = fqs->query.start_ut;
437 usec_t stop_ut = fqs->query.stop_ut;
@@ -450,12 +440,12 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_forward(
440 fqs->c.query_file.start_ut = start_ut;
441 fqs->c.query_file.stop_ut = stop_ut;
442
453 - if(!netdata_systemd_journal_seek_to(j, start_ut))
443 + if (!nd_sd_journal_seek_to(j, start_ut))
444 return ND_SD_JOURNAL_FAILED_TO_SEEK;
445
446 size_t errors_no_timestamp = 0;
447 usec_t latest_msg_ut = 0; // the biggest timestamp we have seen so far
458 - usec_t first_msg_ut = 0; // the first message we got from the db
448 + usec_t first_msg_ut = 0; // the first message we got from the db
449 size_t row_counter = 0, last_row_counter = 0, rows_useful = 0;
450 size_t bytes = 0, last_bytes = 0;
451
@@ -467,7 +457,7 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_forward(
457 facets_rows_begin(facets);
458 while (status == ND_SD_JOURNAL_OK && sd_journal_next(j) > 0) {
459 usec_t msg_ut = 0;
470 - if(sd_journal_get_realtime_usec(j, &msg_ut) < 0 || !msg_ut) {
460 + if (sd_journal_get_realtime_usec(j, &msg_ut) < 0 || !msg_ut) {
461 errors_no_timestamp++;
462 continue;
463 }
@@ -478,41 +468,40 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_forward(
468 if (unlikely(msg_ut > stop_ut))
469 break;
470
481 - if(likely(msg_ut > latest_msg_ut))
471 + if (likely(msg_ut > latest_msg_ut))
472 latest_msg_ut = msg_ut;
473
484 - if(unlikely(!first_msg_ut)) {
474 + if (unlikely(!first_msg_ut)) {
475 first_msg_ut = msg_ut;
476 fqs->c.query_file.first_msg_ut = msg_ut;
477 }
478
489 - sampling_t sample = is_row_in_sample(j, fqs, jf, msg_ut,
490 - FACETS_ANCHOR_DIRECTION_FORWARD,
491 - facets_row_candidate_to_keep(facets, msg_ut));
479 + sampling_t sample = is_row_in_sample(
480 + j, fqs, njf, msg_ut, FACETS_ANCHOR_DIRECTION_FORWARD, facets_row_candidate_to_keep(facets, msg_ut));
481
493 - if(sample == SAMPLING_FULL) {
494 - bytes += netdata_systemd_journal_process_row(j, facets, jf, &msg_ut);
482 + if (sample == SAMPLING_FULL) {
483 + bytes += nd_sd_journal_process_row(j, facets, njf, &msg_ut);
484
485 // make sure each line gets a unique timestamp
497 - if(unlikely(msg_ut >= last_usec_from && msg_ut <= last_usec_to))
486 + if (unlikely(msg_ut >= last_usec_from && msg_ut <= last_usec_to))
487 msg_ut = ++last_usec_to;
488 else
489 last_usec_from = last_usec_to = msg_ut;
490
502 - if(facets_row_finished(facets, msg_ut))
491 + if (facets_row_finished(facets, msg_ut))
492 rows_useful++;
493
494 row_counter++;
506 - if(unlikely((row_counter % FUNCTION_DATA_ONLY_CHECK_EVERY_ROWS) == 0 &&
507 - stop_when_full &&
508 - facets_rows(facets) >= fqs->rq.entries)) {
495 + if (unlikely(
496 + (row_counter % FUNCTION_DATA_ONLY_CHECK_EVERY_ROWS) == 0 && stop_when_full &&
497 + facets_rows(facets) >= fqs->rq.entries)) {
498 // stop the data only query
499 usec_t newest = facets_row_newest_ut(facets);
511 - if(newest && msg_ut > (newest + anchor_delta))
500 + if (newest && msg_ut > (newest + anchor_delta))
501 break;
502 }
503
515 - if(unlikely(row_counter % FUNCTION_PROGRESS_EVERY_ROWS == 0)) {
504 + if (unlikely(row_counter % FUNCTION_PROGRESS_EVERY_ROWS == 0)) {
505 FUNCTION_PROGRESS_UPDATE_ROWS(fqs->c.rows_read, row_counter - last_row_counter);
506 last_row_counter = row_counter;
507
@@ -521,11 +510,10 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_forward(
510
511 status = check_stop(fqs->cancelled, fqs->stop_monotonic_ut);
512 }
524 - }
525 - else if(sample == SAMPLING_SKIP_FIELDS)
513 + } else if (sample == SAMPLING_SKIP_FIELDS)
514 facets_row_finished_unsampled(facets, msg_ut);
515 else {
528 - sampling_update_running_query_file_estimates(facets, j, fqs, jf, msg_ut, FACETS_ANCHOR_DIRECTION_FORWARD);
516 + sampling_update_running_query_file_estimates(facets, j, fqs, njf, msg_ut, FACETS_ANCHOR_DIRECTION_FORWARD);
517 break;
518 }
519 }
@@ -535,28 +523,29 @@ ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_forward(
523
524 fqs->c.rows_useful += rows_useful;
525
538 - if(errors_no_timestamp)
526 + if (errors_no_timestamp)
527 netdata_log_error("SYSTEMD-JOURNAL: %zu lines did not have timestamps", errors_no_timestamp);
528
541 - if(latest_msg_ut > fqs->last_modified)
529 + if (latest_msg_ut > fqs->last_modified)
530 fqs->last_modified = latest_msg_ut;
531
532 return status;
533 }
534
547 -bool netdata_systemd_journal_check_if_modified_since(sd_journal *j, usec_t seek_to, usec_t last_modified) {
535 +bool nd_sd_journal_check_if_modified_since(sd_journal *j, usec_t seek_to, usec_t last_modified)
536 +{
537 // return true, if data have been modified since the timestamp
538
550 - if(!last_modified || !seek_to)
539 + if (!last_modified || !seek_to)
540 return false;
541
553 - if(!netdata_systemd_journal_seek_to(j, seek_to))
542 + if (!nd_sd_journal_seek_to(j, seek_to))
543 return false;
544
545 usec_t first_msg_ut = 0;
546 while (sd_journal_previous(j) > 0) {
547 usec_t msg_ut;
559 - if(sd_journal_get_realtime_usec(j, &msg_ut) < 0)
548 + if (sd_journal_get_realtime_usec(j, &msg_ut) < 0)
549 continue;
550
551 first_msg_ut = msg_ut;
@@ -567,7 +556,8 @@ bool netdata_systemd_journal_check_if_modified_since(sd_journal *j, usec_t seek_
556 }
557
558 #ifdef HAVE_SD_JOURNAL_RESTART_FIELDS
570 -static bool netdata_systemd_filtering_by_journal(sd_journal *j, FACETS *facets, LOGS_QUERY_STATUS *lqs) {
559 +static bool netdata_systemd_filtering_by_journal(sd_journal *j, FACETS *facets, LOGS_QUERY_STATUS *lqs)
560 +{
561 const char *field = NULL;
562 const void *data = NULL;
563 size_t data_length;
@@ -575,46 +565,47 @@ static bool netdata_systemd_filtering_by_journal(sd_journal *j, FACETS *facets,
565 size_t failures = 0;
566 size_t filters_added = 0;
567
578 - SD_JOURNAL_FOREACH_FIELD(j, field) { // for each key
568 + SD_JOURNAL_FOREACH_FIELD(j, field)
569 + { // for each key
570 bool interesting;
571
581 - if(lqs->rq.data_only)
572 + if (lqs->rq.data_only)
573 interesting = facets_key_name_is_filter(facets, field);
574 else
575 interesting = facets_key_name_is_facet(facets, field);
576
586 - if(interesting) {
587 - if(sd_journal_query_unique(j, field) >= 0) {
577 + if (interesting) {
578 + if (sd_journal_query_unique(j, field) >= 0) {
579 bool added_this_key = false;
580 size_t added_values = 0;
581
591 - SD_JOURNAL_FOREACH_UNIQUE(j, data, data_length) { // for each value of the key
582 + SD_JOURNAL_FOREACH_UNIQUE(j, data, data_length)
583 + { // for each value of the key
584 const char *key, *value;
585 size_t key_length, value_length;
586
595 - if(!parse_journal_field(data, data_length, &key, &key_length, &value, &value_length))
587 + if (!parse_journal_field(data, data_length, &key, &key_length, &value, &value_length))
588 continue;
589
590 facets_add_possible_value_name_to_key(facets, key, key_length, value, value_length);
591
600 - if(!facets_key_name_value_length_is_selected(facets, key, key_length, value, value_length))
592 + if (!facets_key_name_value_length_is_selected(facets, key, key_length, value, value_length))
593 continue;
594
603 - if(added_keys && !added_this_key) {
604 - if(sd_journal_add_conjunction(j) < 0) // key AND key AND key
595 + if (added_keys && !added_this_key) {
596 + if (sd_journal_add_conjunction(j) < 0) // key AND key AND key
597 failures++;
598
599 added_this_key = true;
600 added_keys++;
609 - }
610 - else if(added_values)
611 - if(sd_journal_add_disjunction(j) < 0) // value OR value OR value
601 + } else if (added_values)
602 + if (sd_journal_add_disjunction(j) < 0) // value OR value OR value
603 failures++;
604
614 - if(sd_journal_add_match(j, data, data_length) < 0)
605 + if (sd_journal_add_match(j, data, data_length) < 0)
606 failures++;
607
617 - if(!added_keys) {
608 + if (!added_keys) {
609 added_keys++;
610 added_this_key = true;
611 }
@@ -626,7 +617,7 @@ static bool netdata_systemd_filtering_by_journal(sd_journal *j, FACETS *facets,
617 }
618 }
619
629 - if(failures) {
620 + if (failures) {
621 lqs_log_error(lqs, "failed to setup journal filter, will run the full query.");
622 sd_journal_flush_matches(j);
623 return true;
@@ -636,22 +627,24 @@ static bool netdata_systemd_filtering_by_journal(sd_journal *j, FACETS *facets,
627 }
628 #endif // HAVE_SD_JOURNAL_RESTART_FIELDS
629
639 -static ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_one_file(
640 - const char *filename, BUFFER *wb, FACETS *facets,
641 - struct journal_file *jf,
642 - LOGS_QUERY_STATUS *fqs) {
643 -
630 +static ND_SD_JOURNAL_STATUS nd_sd_journal_query_one_file(
631 + const char *filename,
632 + BUFFER *wb,
633 + FACETS *facets,
634 + struct nd_journal_file *njf,
635 + LOGS_QUERY_STATUS *fqs)
636 +{
637 sd_journal *j = NULL;
638 errno_clear();
639
640 fstat_cache_enable_on_thread();
641
642 const char *paths[2] = {
650 - [0] = filename,
651 - [1] = NULL,
643 + [0] = filename,
644 + [1] = NULL,
645 };
646
654 - if(sd_journal_open_files(&j, paths, ND_SD_JOURNAL_OPEN_FLAGS) < 0 || !j) {
647 + if (sd_journal_open_files(&j, paths, ND_SD_JOURNAL_OPEN_FLAGS) < 0 || !j) {
648 netdata_log_error("JOURNAL: cannot open file '%s' for query", filename);
649 fstat_cache_disable_on_thread();
650 return ND_SD_JOURNAL_FAILED_TO_OPEN;
@@ -661,7 +654,7 @@ static ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_one_file(
654 bool matches_filters = true;
655
656 #ifdef HAVE_SD_JOURNAL_RESTART_FIELDS
664 - if(fqs->rq.slice) {
657 + if (fqs->rq.slice) {
658 usec_t started = now_monotonic_usec();
659
660 matches_filters = netdata_systemd_filtering_by_journal(j, facets, fqs) || !fqs->rq.filters;
@@ -671,13 +664,12 @@ static ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_one_file(
664 }
665 #endif // HAVE_SD_JOURNAL_RESTART_FIELDS
666
674 - if(matches_filters) {
675 - if(fqs->rq.direction == FACETS_ANCHOR_DIRECTION_FORWARD)
676 - status = netdata_systemd_journal_query_forward(j, wb, facets, jf, fqs);
667 + if (matches_filters) {
668 + if (fqs->rq.direction == FACETS_ANCHOR_DIRECTION_FORWARD)
669 + status = nd_sd_journal_query_forward(j, wb, facets, njf, fqs);
670 else
678 - status = netdata_systemd_journal_query_backward(j, wb, facets, jf, fqs);
679 - }
680 - else
671 + status = nd_sd_journal_query_backward(j, wb, facets, njf, fqs);
672 + } else
673 status = ND_SD_JOURNAL_NO_FILE_MATCHED;
674
675 sd_journal_close(j);
@@ -686,32 +678,32 @@ static ND_SD_JOURNAL_STATUS netdata_systemd_journal_query_one_file(
678 return status;
679 }
680
689 -static bool jf_is_mine(struct journal_file *jf, LOGS_QUERY_STATUS *fqs) {
690 -
691 - if((fqs->rq.source_type == SDJF_NONE && !fqs->rq.sources) || (jf->source_type & fqs->rq.source_type) ||
692 - (fqs->rq.sources && simple_pattern_matches(fqs->rq.sources, string2str(jf->source)))) {
693 -
694 - if(!jf->msg_last_ut)
681 +static bool jf_is_mine(struct nd_journal_file *njf, LOGS_QUERY_STATUS *fqs)
682 +{
683 + if ((fqs->rq.source_type == ND_SD_JF_NONE && !fqs->rq.sources) || (njf->source_type & fqs->rq.source_type) ||
684 + (fqs->rq.sources && simple_pattern_matches(fqs->rq.sources, string2str(njf->source)))) {
685 + if (!njf->msg_last_ut)
686 // the file is not scanned yet, or the timestamps have not been updated,
687 // so we don't know if it can contribute or not - let's add it.
688 return true;
689
690 usec_t anchor_delta = JOURNAL_VS_REALTIME_DELTA_MAX_UT;
700 - usec_t first_ut = jf->msg_first_ut - anchor_delta;
701 - usec_t last_ut = jf->msg_last_ut + anchor_delta;
691 + usec_t first_ut = njf->msg_first_ut - anchor_delta;
692 + usec_t last_ut = njf->msg_last_ut + anchor_delta;
693
703 - if(last_ut >= fqs->rq.after_ut && first_ut <= fqs->rq.before_ut)
694 + if (last_ut >= fqs->rq.after_ut && first_ut <= fqs->rq.before_ut)
695 return true;
696 }
697
698 return false;
699 }
700
710 -static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
701 +static int nd_sd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs)
702 +{
703 FACETS *facets = lqs->facets;
704
705 ND_SD_JOURNAL_STATUS status = ND_SD_JOURNAL_NO_FILE_MATCHED;
714 - struct journal_file *jf;
706 + struct nd_journal_file *njf;
707
708 lqs->c.files_matched = 0;
709 lqs->c.file_working = 0;
@@ -720,40 +712,39 @@ static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
712 lqs->c.bytes_read = 0;
713
714 size_t files_used = 0;
723 - size_t files_max = dictionary_entries(journal_files_registry);
715 + size_t files_max = dictionary_entries(nd_journal_files_registry);
716 const DICTIONARY_ITEM *file_items[files_max];
717
718 // count the files
719 bool files_are_newer = false;
728 - dfe_start_read(journal_files_registry, jf) {
729 - if(!jf_is_mine(jf, lqs))
720 + dfe_start_read(nd_journal_files_registry, njf)
721 + {
722 + if (!jf_is_mine(njf, lqs))
723 continue;
724
732 - file_items[files_used++] = dictionary_acquired_item_dup(journal_files_registry, jf_dfe.item);
725 + file_items[files_used++] = dictionary_acquired_item_dup(nd_journal_files_registry, njf_dfe.item);
726
734 - if(jf->msg_last_ut > lqs->rq.if_modified_since)
727 + if (njf->msg_last_ut > lqs->rq.if_modified_since)
728 files_are_newer = true;
729 }
730 dfe_done(jf);
731
732 lqs->c.files_matched = files_used;
733
741 - if(lqs->rq.if_modified_since && !files_are_newer) {
734 + if (lqs->rq.if_modified_since && !files_are_newer) {
735 // release the files
743 - for(size_t f = 0; f < files_used ;f++)
744 - dictionary_acquired_item_release(journal_files_registry, file_items[f]);
736 + for (size_t f = 0; f < files_used; f++)
737 + dictionary_acquired_item_release(nd_journal_files_registry, file_items[f]);
738
739 return rrd_call_function_error(wb, "No new data since the previous call.", HTTP_RESP_NOT_MODIFIED);
740 }
741
742 // sort the files, so that they are optimal for facets
750 - if(files_used >= 2) {
743 + if (files_used >= 2) {
744 if (lqs->rq.direction == FACETS_ANCHOR_DIRECTION_BACKWARD)
752 - qsort(file_items, files_used, sizeof(const DICTIONARY_ITEM *),
753 - journal_file_dict_items_backward_compar);
745 + qsort(file_items, files_used, sizeof(const DICTIONARY_ITEM *), nd_journal_file_dict_items_backward_compar);
746 else
755 - qsort(file_items, files_used, sizeof(const DICTIONARY_ITEM *),
756 - journal_file_dict_items_forward_compar);
747 + qsort(file_items, files_used, sizeof(const DICTIONARY_ITEM *), nd_journal_file_dict_items_forward_compar);
748 }
749
750 bool partial = false;
@@ -766,24 +757,23 @@ static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
757 sampling_query_init(lqs, facets);
758
759 buffer_json_member_add_array(wb, "_journal_files");
769 - for(size_t f = 0; f < files_used ;f++) {
760 + for (size_t f = 0; f < files_used; f++) {
761 const char *filename = dictionary_acquired_item_name(file_items[f]);
771 - jf = dictionary_acquired_item_value(file_items[f]);
762 + njf = dictionary_acquired_item_value(file_items[f]);
763
773 - if(!jf_is_mine(jf, lqs))
764 + if (!jf_is_mine(njf, lqs))
765 continue;
766
767 started_ut = ended_ut;
768
769 // do not even try to do the query if we expect it to pass the timeout
779 - if(ended_ut + max_duration_ut * 3 >= *lqs->stop_monotonic_ut) {
770 + if (ended_ut + max_duration_ut * 3 >= *lqs->stop_monotonic_ut) {
771 partial = true;
772 status = ND_SD_JOURNAL_TIMED_OUT;
773 break;
774 }
775
776 lqs->c.file_working++;
786 - // fqs->cached_count = 0;
777
778 size_t fs_calls = fstat_thread_calls;
779 size_t fs_cached = fstat_thread_cached_responses;
@@ -792,21 +782,9 @@ static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
782 size_t bytes_read = lqs->c.bytes_read;
783 size_t matches_setup_ut = lqs->c.matches_setup_ut;
784
795 - sampling_file_init(lqs, jf);
796 -
797 - ND_SD_JOURNAL_STATUS tmp_status = netdata_systemd_journal_query_one_file(filename, wb, facets, jf, lqs);
785 + sampling_file_init(lqs, njf);
786
799 -// nd_log(NDLS_COLLECTORS, NDLP_INFO,
800 -// "JOURNAL ESTIMATION FINAL: '%s' "
801 -// "total lines %zu [sampled=%zu, unsampled=%zu, estimated=%zu], "
802 -// "file [%"PRIu64" - %"PRIu64", duration %"PRId64", known lines in file %zu], "
803 -// "query [%"PRIu64" - %"PRIu64", duration %"PRId64"], "
804 -// , jf->filename
805 -// , fqs->samples_per_file.sampled + fqs->samples_per_file.unsampled + fqs->samples_per_file.estimated
806 -// , fqs->samples_per_file.sampled, fqs->samples_per_file.unsampled, fqs->samples_per_file.estimated
807 -// , jf->msg_first_ut, jf->msg_last_ut, jf->msg_last_ut - jf->msg_first_ut, jf->messages_in_file
808 -// , fqs->query_file.start_ut, fqs->query_file.stop_ut, fqs->query_file.stop_ut - fqs->query_file.start_ut
809 -// );
787 + ND_SD_JOURNAL_STATUS tmp_status = nd_sd_journal_query_one_file(filename, wb, facets, njf, lqs);
788
789 rows_useful = lqs->c.rows_useful - rows_useful;
790 rows_read = lqs->c.rows_read - rows_read;
@@ -818,11 +796,11 @@ static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
796 ended_ut = now_monotonic_usec();
797 duration_ut = ended_ut - started_ut;
798
821 - if(duration_ut > max_duration_ut)
799 + if (duration_ut > max_duration_ut)
800 max_duration_ut = duration_ut;
801
802 progress_duration_ut += duration_ut;
825 - if(progress_duration_ut >= SYSTEMD_JOURNAL_PROGRESS_EVERY_UT) {
803 + if (progress_duration_ut >= ND_SD_JOURNAL_PROGRESS_EVERY_UT) {
804 progress_duration_ut = 0;
805 netdata_mutex_lock(&stdout_mutex);
806 pluginsd_function_progress_to_stdout(lqs->rq.transaction, f + 1, files_used);
@@ -833,25 +811,27 @@ static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
811 {
812 // information about the file
813 buffer_json_member_add_string(wb, "_filename", filename);
836 - buffer_json_member_add_uint64(wb, "_source_type", jf->source_type);
837 - buffer_json_member_add_string(wb, "_source", string2str(jf->source));
838 - buffer_json_member_add_uint64(wb, "_last_modified_ut", jf->file_last_modified_ut);
839 - buffer_json_member_add_uint64(wb, "_msg_first_ut", jf->msg_first_ut);
840 - buffer_json_member_add_uint64(wb, "_msg_last_ut", jf->msg_last_ut);
841 - buffer_json_member_add_uint64(wb, "_journal_vs_realtime_delta_ut", jf->max_journal_vs_realtime_delta_ut);
814 + buffer_json_member_add_uint64(wb, "_source_type", njf->source_type);
815 + buffer_json_member_add_string(wb, "_source", string2str(njf->source));
816 + buffer_json_member_add_uint64(wb, "_last_modified_ut", njf->file_last_modified_ut);
817 + buffer_json_member_add_uint64(wb, "_msg_first_ut", njf->msg_first_ut);
818 + buffer_json_member_add_uint64(wb, "_msg_last_ut", njf->msg_last_ut);
819 + buffer_json_member_add_uint64(wb, "_journal_vs_realtime_delta_ut", njf->max_journal_vs_realtime_delta_ut);
820
821 // information about the current use of the file
822 buffer_json_member_add_uint64(wb, "duration_ut", ended_ut - started_ut);
823 buffer_json_member_add_uint64(wb, "rows_read", rows_read);
824 buffer_json_member_add_uint64(wb, "rows_useful", rows_useful);
847 - buffer_json_member_add_double(wb, "rows_per_second", (double) rows_read / (double) duration_ut * (double) USEC_PER_SEC);
825 + buffer_json_member_add_double(
826 + wb, "rows_per_second", (double)rows_read / (double)duration_ut * (double)USEC_PER_SEC);
827 buffer_json_member_add_uint64(wb, "bytes_read", bytes_read);
849 - buffer_json_member_add_double(wb, "bytes_per_second", (double) bytes_read / (double) duration_ut * (double) USEC_PER_SEC);
828 + buffer_json_member_add_double(
829 + wb, "bytes_per_second", (double)bytes_read / (double)duration_ut * (double)USEC_PER_SEC);
830 buffer_json_member_add_uint64(wb, "duration_matches_ut", matches_setup_ut);
831 buffer_json_member_add_uint64(wb, "fstat_query_calls", fs_calls);
832 buffer_json_member_add_uint64(wb, "fstat_query_cached_responses", fs_cached);
833
854 - if(lqs->rq.sampling) {
834 + if (lqs->rq.sampling) {
835 buffer_json_member_add_object(wb, "_sampling");
836 {
837 buffer_json_member_add_uint64(wb, "sampled", lqs->c.samples_per_file.sampled);
@@ -864,7 +844,7 @@ static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
844 buffer_json_object_close(wb); // journal file
845
846 bool stop = false;
867 - switch(tmp_status) {
847 + switch (tmp_status) {
848 case ND_SD_JOURNAL_OK:
849 case ND_SD_JOURNAL_NO_FILE_MATCHED:
850 status = (status == ND_SD_JOURNAL_OK) ? ND_SD_JOURNAL_OK : tmp_status;
@@ -873,7 +853,7 @@ static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
853 case ND_SD_JOURNAL_FAILED_TO_OPEN:
854 case ND_SD_JOURNAL_FAILED_TO_SEEK:
855 partial = true;
876 - if(status == ND_SD_JOURNAL_NO_FILE_MATCHED)
856 + if (status == ND_SD_JOURNAL_NO_FILE_MATCHED)
857 status = tmp_status;
858 break;
859
@@ -889,19 +869,20 @@ static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
869 break;
870 }
871
892 - if(stop)
872 + if (stop)
873 break;
874 }
875 buffer_json_array_close(wb); // _journal_files
876
877 // release the files
898 - for(size_t f = 0; f < files_used ;f++)
899 - dictionary_acquired_item_release(journal_files_registry, file_items[f]);
878 + for (size_t f = 0; f < files_used; f++)
879 + dictionary_acquired_item_release(nd_journal_files_registry, file_items[f]);
880
881 switch (status) {
882 case ND_SD_JOURNAL_OK:
903 - if(lqs->rq.if_modified_since && !lqs->c.rows_useful)
904 - return rrd_call_function_error(wb, "No additional useful data since the previous call.", HTTP_RESP_NOT_MODIFIED);
883 + if (lqs->rq.if_modified_since && !lqs->c.rows_useful)
884 + return rrd_call_function_error(
885 + wb, "No additional useful data since the previous call.", HTTP_RESP_NOT_MODIFIED);
886 break;
887
888 case ND_SD_JOURNAL_TIMED_OUT:
@@ -918,7 +899,8 @@ static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
899 return rrd_call_function_error(wb, "Failed to open systemd journal file.", HTTP_RESP_INTERNAL_SERVER_ERROR);
900
901 case ND_SD_JOURNAL_FAILED_TO_SEEK:
921 - return rrd_call_function_error(wb, "Failed to seek in systemd journal file.", HTTP_RESP_INTERNAL_SERVER_ERROR);
902 + return rrd_call_function_error(
903 + wb, "Failed to seek in systemd journal file.", HTTP_RESP_INTERNAL_SERVER_ERROR);
904
905 default:
906 return rrd_call_function_error(wb, "Unknown status", HTTP_RESP_INTERNAL_SERVER_ERROR);
@@ -929,55 +911,59 @@ static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
911 buffer_json_member_add_string(wb, "type", "table");
912
913 // build a message for the query
932 - if(!lqs->rq.data_only) {
914 + if (!lqs->rq.data_only) {
915 CLEAN_BUFFER *msg = buffer_create(0, NULL);
916 CLEAN_BUFFER *msg_description = buffer_create(0, NULL);
917 ND_LOG_FIELD_PRIORITY msg_priority = NDLP_INFO;
918
937 - if(!journal_files_completed_once()) {
919 + if (!nd_journal_files_completed_once()) {
920 buffer_strcat(msg, "Journals are still being scanned. ");
939 - buffer_strcat(msg_description
940 - , "LIBRARY SCAN: The journal files are still being scanned, you are probably viewing incomplete data. ");
921 + buffer_strcat(
922 + msg_description,
923 + "LIBRARY SCAN: The journal files are still being scanned, you are probably viewing incomplete data. ");
924 msg_priority = NDLP_WARNING;
925 }
926
944 - if(partial) {
927 + if (partial) {
928 buffer_strcat(msg, "Query timed-out, incomplete data. ");
946 - buffer_strcat(msg_description
947 - , "QUERY TIMEOUT: The query timed out and may not include all the data of the selected window. ");
929 + buffer_strcat(
930 + msg_description,
931 + "QUERY TIMEOUT: The query timed out and may not include all the data of the selected window. ");
932 msg_priority = NDLP_WARNING;
933 }
934
951 - if(lqs->c.samples.estimated || lqs->c.samples.unsampled) {
952 - double percent = (double) (lqs->c.samples.sampled * 100.0 /
953 - (lqs->c.samples.estimated + lqs->c.samples.unsampled + lqs->c.samples.sampled));
935 + if (lqs->c.samples.estimated || lqs->c.samples.unsampled) {
936 + double percent = (double)(lqs->c.samples.sampled * 100.0 /
937 + (lqs->c.samples.estimated + lqs->c.samples.unsampled + lqs->c.samples.sampled));
938 buffer_sprintf(msg, "%.2f%% real data", percent);
939 buffer_sprintf(msg_description, "ACTUAL DATA: The filters counters reflect %0.2f%% of the data. ", percent);
940 msg_priority = MIN(msg_priority, NDLP_NOTICE);
941 }
942
959 - if(lqs->c.samples.unsampled) {
960 - double percent = (double) (lqs->c.samples.unsampled * 100.0 /
961 - (lqs->c.samples.estimated + lqs->c.samples.unsampled + lqs->c.samples.sampled));
943 + if (lqs->c.samples.unsampled) {
944 + double percent = (double)(lqs->c.samples.unsampled * 100.0 /
945 + (lqs->c.samples.estimated + lqs->c.samples.unsampled + lqs->c.samples.sampled));
946 buffer_sprintf(msg, ", %.2f%% unsampled", percent);
963 - buffer_sprintf(msg_description
964 - , "UNSAMPLED DATA: %0.2f%% of the events exist and have been counted, but their values have not been evaluated, so they are not included in the filters counters. "
965 - , percent);
947 + buffer_sprintf(
948 + msg_description,
949 + "UNSAMPLED DATA: %0.2f%% of the events exist and have been counted, but their values have not been evaluated, so they are not included in the filters counters. ",
950 + percent);
951 msg_priority = MIN(msg_priority, NDLP_NOTICE);
952 }
953
969 - if(lqs->c.samples.estimated) {
970 - double percent = (double) (lqs->c.samples.estimated * 100.0 /
971 - (lqs->c.samples.estimated + lqs->c.samples.unsampled + lqs->c.samples.sampled));
954 + if (lqs->c.samples.estimated) {
955 + double percent = (double)(lqs->c.samples.estimated * 100.0 /
956 + (lqs->c.samples.estimated + lqs->c.samples.unsampled + lqs->c.samples.sampled));
957 buffer_sprintf(msg, ", %.2f%% estimated", percent);
973 - buffer_sprintf(msg_description
974 - , "ESTIMATED DATA: The query selected a large amount of data, so to avoid delaying too much, the presented data are estimated by %0.2f%%. "
975 - , percent);
958 + buffer_sprintf(
959 + msg_description,
960 + "ESTIMATED DATA: The query selected a large amount of data, so to avoid delaying too much, the presented data are estimated by %0.2f%%. ",
961 + percent);
962 msg_priority = MIN(msg_priority, NDLP_NOTICE);
963 }
964
965 buffer_json_member_add_object(wb, "message");
980 - if(buffer_tostring(msg)) {
966 + if (buffer_tostring(msg)) {
967 buffer_json_member_add_string(wb, "title", buffer_tostring(msg));
968 buffer_json_member_add_string(wb, "description", buffer_tostring(msg_description));
969 buffer_json_member_add_string(wb, "status", nd_log_id2priority(msg_priority));
@@ -986,12 +972,12 @@ static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
972 buffer_json_object_close(wb); // message
973 }
974
989 - if(!lqs->rq.data_only) {
975 + if (!lqs->rq.data_only) {
976 buffer_json_member_add_time_t(wb, "update_every", 1);
991 - buffer_json_member_add_string(wb, "help", SYSTEMD_JOURNAL_FUNCTION_DESCRIPTION);
977 + buffer_json_member_add_string(wb, "help", ND_SD_JOURNAL_FUNCTION_DESCRIPTION);
978 }
979
994 - if(!lqs->rq.data_only || lqs->rq.tail)
980 + if (!lqs->rq.data_only || lqs->rq.tail)
981 buffer_json_member_add_uint64(wb, "last_modified", lqs->last_modified);
982
983 facets_sort_and_reorder_keys(facets);
@@ -1007,7 +993,7 @@ static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
993 }
994 buffer_json_object_close(wb); // _fstat_caching
995
1010 - if(lqs->rq.sampling) {
996 + if (lqs->rq.sampling) {
997 buffer_json_member_add_object(wb, "_sampling");
998 {
999 buffer_json_member_add_uint64(wb, "sampled", lqs->c.samples.sampled);
@@ -1022,7 +1008,8 @@ static int netdata_systemd_journal_query(BUFFER *wb, LOGS_QUERY_STATUS *lqs) {
1008 return wb->response_code;
1009 }
1010
1025 -static void systemd_journal_register_transformations(LOGS_QUERY_STATUS *lqs) {
1011 +static void systemd_journal_register_transformations(LOGS_QUERY_STATUS *lqs)
1012 +{
1013 FACETS *facets = lqs->facets;
1014 LOGS_QUERY_REQUEST *rq = &lqs->rq;
1015
@@ -1031,120 +1018,108 @@ static void systemd_journal_register_transformations(LOGS_QUERY_STATUS *lqs) {
1018
1019 facets_register_row_severity(facets, syslog_priority_to_facet_severity, NULL);
1020
1034 - facets_register_key_name(
1035 - facets, "_HOSTNAME", rq->default_facet | FACET_KEY_OPTION_VISIBLE);
1021 + facets_register_key_name(facets, "_HOSTNAME", rq->default_facet | FACET_KEY_OPTION_VISIBLE);
1022
1023 facets_register_dynamic_key_name(
1038 - facets, JOURNAL_KEY_ND_JOURNAL_PROCESS,
1024 + facets,
1025 + JOURNAL_KEY_ND_JOURNAL_PROCESS,
1026 FACET_KEY_OPTION_NEVER_FACET | FACET_KEY_OPTION_VISIBLE,
1040 - netdata_systemd_journal_dynamic_row_id, NULL);
1027 + nd_sd_journal_dynamic_row_id,
1028 + NULL);
1029
1030 facets_register_key_name(
1043 - facets, "MESSAGE",
1044 - FACET_KEY_OPTION_NEVER_FACET | FACET_KEY_OPTION_MAIN_TEXT |
1045 - FACET_KEY_OPTION_VISIBLE | FACET_KEY_OPTION_FTS);
1046 -
1047 - // facets_register_dynamic_key_name(
1048 - // facets, "MESSAGE",
1049 - // FACET_KEY_OPTION_NEVER_FACET | FACET_KEY_OPTION_MAIN_TEXT | FACET_KEY_OPTION_RICH_TEXT |
1050 - // FACET_KEY_OPTION_VISIBLE | FACET_KEY_OPTION_FTS,
1051 - // netdata_systemd_journal_rich_message, NULL);
1031 + facets,
1032 + "MESSAGE",
1033 + FACET_KEY_OPTION_NEVER_FACET | FACET_KEY_OPTION_MAIN_TEXT | FACET_KEY_OPTION_VISIBLE | FACET_KEY_OPTION_FTS);
1034
1035 facets_register_key_name_transformation(
1054 - facets, "PRIORITY",
1055 - rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW |
1056 - FACET_KEY_OPTION_EXPANDED_FILTER,
1057 - netdata_systemd_journal_transform_priority, NULL);
1036 + facets,
1037 + "PRIORITY",
1038 + rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW | FACET_KEY_OPTION_EXPANDED_FILTER,
1039 + nd_sd_journal_transform_priority,
1040 + NULL);
1041
1042 facets_register_key_name_transformation(
1060 - facets, "SYSLOG_FACILITY",
1061 - rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW |
1062 - FACET_KEY_OPTION_EXPANDED_FILTER,
1063 - netdata_systemd_journal_transform_syslog_facility, NULL);
1043 + facets,
1044 + "SYSLOG_FACILITY",
1045 + rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW | FACET_KEY_OPTION_EXPANDED_FILTER,
1046 + nd_sd_journal_transform_syslog_facility,
1047 + NULL);
1048
1049 facets_register_key_name_transformation(
1066 - facets, "ERRNO",
1067 - rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW,
1068 - netdata_systemd_journal_transform_errno, NULL);
1050 + facets, "ERRNO", rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW, nd_sd_journal_transform_errno, NULL);
1051
1070 - facets_register_key_name(
1071 - facets, JOURNAL_KEY_ND_JOURNAL_FILE,
1072 - FACET_KEY_OPTION_NEVER_FACET);
1052 + facets_register_key_name(facets, JOURNAL_KEY_ND_JOURNAL_FILE, FACET_KEY_OPTION_NEVER_FACET);
1053
1074 - facets_register_key_name(
1075 - facets, "SYSLOG_IDENTIFIER", rq->default_facet);
1054 + facets_register_key_name(facets, "SYSLOG_IDENTIFIER", rq->default_facet);
1055
1077 - facets_register_key_name(
1078 - facets, "UNIT", rq->default_facet);
1056 + facets_register_key_name(facets, "UNIT", rq->default_facet);
1057
1080 - facets_register_key_name(
1081 - facets, "USER_UNIT", rq->default_facet);
1058 + facets_register_key_name(facets, "USER_UNIT", rq->default_facet);
1059
1060 facets_register_key_name_transformation(
1084 - facets, "MESSAGE_ID",
1085 - rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW |
1086 - FACET_KEY_OPTION_EXPANDED_FILTER,
1087 - netdata_systemd_journal_transform_message_id, NULL);
1061 + facets,
1062 + "MESSAGE_ID",
1063 + rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW | FACET_KEY_OPTION_EXPANDED_FILTER,
1064 + nd_sd_journal_transform_message_id,
1065 + NULL);
1066
1067 facets_register_key_name_transformation(
1090 - facets, "_BOOT_ID",
1091 - rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW,
1092 - netdata_systemd_journal_transform_boot_id, NULL);
1068 + facets, "_BOOT_ID", rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW, nd_sd_journal_transform_boot_id, NULL);
1069
1070 facets_register_key_name_transformation(
1095 - facets, "_SYSTEMD_OWNER_UID",
1071 + facets,
1072 + "_SYSTEMD_OWNER_UID",
1073 rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW,
1097 - netdata_systemd_journal_transform_uid, NULL);
1074 + nd_sd_journal_transform_uid,
1075 + NULL);
1076
1077 facets_register_key_name_transformation(
1100 - facets, "_UID",
1101 - rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW,
1102 - netdata_systemd_journal_transform_uid, NULL);
1078 + facets, "_UID", rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW, nd_sd_journal_transform_uid, NULL);
1079
1080 facets_register_key_name_transformation(
1105 - facets, "OBJECT_SYSTEMD_OWNER_UID",
1081 + facets,
1082 + "OBJECT_SYSTEMD_OWNER_UID",
1083 rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW,
1107 - netdata_systemd_journal_transform_uid, NULL);
1084 + nd_sd_journal_transform_uid,
1085 + NULL);
1086
1087 facets_register_key_name_transformation(
1110 - facets, "OBJECT_UID",
1111 - rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW,
1112 - netdata_systemd_journal_transform_uid, NULL);
1088 + facets, "OBJECT_UID", rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW, nd_sd_journal_transform_uid, NULL);
1089
1090 facets_register_key_name_transformation(
1115 - facets, "_GID",
1116 - rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW,
1117 - netdata_systemd_journal_transform_gid, NULL);
1091 + facets, "_GID", rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW, nd_sd_journal_transform_gid, NULL);
1092
1093 facets_register_key_name_transformation(
1120 - facets, "OBJECT_GID",
1121 - rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW,
1122 - netdata_systemd_journal_transform_gid, NULL);
1094 + facets, "OBJECT_GID", rq->default_facet | FACET_KEY_OPTION_TRANSFORM_VIEW, nd_sd_journal_transform_gid, NULL);
1095
1096 facets_register_key_name_transformation(
1125 - facets, "_CAP_EFFECTIVE",
1126 - FACET_KEY_OPTION_TRANSFORM_VIEW,
1127 - netdata_systemd_journal_transform_cap_effective, NULL);
1097 + facets, "_CAP_EFFECTIVE", FACET_KEY_OPTION_TRANSFORM_VIEW, nd_sd_journal_transform_cap_effective, NULL);
1098
1099 facets_register_key_name_transformation(
1130 - facets, "_AUDIT_LOGINUID",
1131 - FACET_KEY_OPTION_TRANSFORM_VIEW,
1132 - netdata_systemd_journal_transform_uid, NULL);
1100 + facets, "_AUDIT_LOGINUID", FACET_KEY_OPTION_TRANSFORM_VIEW, nd_sd_journal_transform_uid, NULL);
1101
1102 facets_register_key_name_transformation(
1135 - facets, "OBJECT_AUDIT_LOGINUID",
1136 - FACET_KEY_OPTION_TRANSFORM_VIEW,
1137 - netdata_systemd_journal_transform_uid, NULL);
1103 + facets, "OBJECT_AUDIT_LOGINUID", FACET_KEY_OPTION_TRANSFORM_VIEW, nd_sd_journal_transform_uid, NULL);
1104
1105 facets_register_key_name_transformation(
1140 - facets, "_SOURCE_REALTIME_TIMESTAMP",
1106 + facets,
1107 + "_SOURCE_REALTIME_TIMESTAMP",
1108 FACET_KEY_OPTION_TRANSFORM_VIEW,
1142 - netdata_systemd_journal_transform_timestamp_usec, NULL);
1109 + nd_sd_journal_transform_timestamp_usec,
1110 + NULL);
1111 }
1112
1145 -void function_systemd_journal(const char *transaction, char *function, usec_t *stop_monotonic_ut, bool *cancelled,
1146 - BUFFER *payload, HTTP_ACCESS access __maybe_unused,
1147 - const char *source __maybe_unused, void *data __maybe_unused) {
1113 +void function_systemd_journal(
1114 + const char *transaction,
1115 + char *function,
1116 + usec_t *stop_monotonic_ut,
1117 + bool *cancelled,
1118 + BUFFER *payload,
1119 + HTTP_ACCESS access __maybe_unused,
1120 + const char *source __maybe_unused,
1121 + void *data __maybe_unused)
1122 +{
1123 fstat_thread_calls = 0;
1124 fstat_thread_cached_responses = 0;
1125
@@ -1175,7 +1150,7 @@ void function_systemd_journal(const char *transaction, char *function, usec_t *s
1150 // ------------------------------------------------------------------------
1151 // parse the parameters
1152
1178 - if(lqs_request_parse_and_validate(lqs, wb, function, payload, have_slice, "PRIORITY")) {
1153 + if (lqs_request_parse_and_validate(lqs, wb, function, payload, have_slice, "PRIORITY")) {
1154 systemd_journal_register_transformations(lqs);
1155
1156 // ------------------------------------------------------------------------
@@ -1189,7 +1164,7 @@ void function_systemd_journal(const char *transaction, char *function, usec_t *s
1164 if (lqs->rq.info)
1165 lqs_info_response(wb, lqs->facets);
1166 else {
1192 - netdata_systemd_journal_query(wb, lqs);
1167 + nd_sd_journal_query(wb, lqs);
1168 if (wb->response_code == HTTP_RESP_OK)
1169 buffer_json_finalize(wb);
1170 }
src/collectors/systemd-journal.plugin/systemd-main.c
+46 -45
@@ -3,12 +3,13 @@
3 #include "systemd-internals.h"
4 #include "libnetdata/required_dummies.h"
5
6 -#define SYSTEMD_JOURNAL_WORKER_THREADS 5
6 +#define ND_SD_JOURNAL_WORKER_THREADS 5
7
8 netdata_mutex_t stdout_mutex = NETDATA_MUTEX_INITIALIZER;
9 static bool plugin_should_exit = false;
10
11 -static bool journal_data_directories_exist() {
11 +static bool journal_data_directories_exist()
12 +{
13 struct stat st;
14 for (unsigned i = 0; i < MAX_JOURNAL_DIRECTORIES && journal_directories[i].path; i++) {
15 if ((stat(string2str(journal_directories[i].path), &st) == 0) && S_ISDIR(st.st_mode))
@@ -17,19 +18,21 @@ static bool journal_data_directories_exist() {
18 return false;
19 }
20
20 -int main(int argc __maybe_unused, char **argv __maybe_unused) {
21 +int main(int argc __maybe_unused, char **argv __maybe_unused)
22 +{
23 nd_thread_tag_set("sd-jrnl.plugin");
24 nd_log_initialize_for_external_plugins("systemd-journal.plugin");
25 netdata_threads_init_for_external_plugins(0);
26
27 netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX");
26 - if(verify_netdata_host_prefix(true) == -1) exit(1);
28 + if (verify_netdata_host_prefix(true) == -1)
29 + exit(1);
30
31 // ------------------------------------------------------------------------
32 // initialization
33
31 - netdata_systemd_journal_annotations_init();
32 - journal_init_files_and_directories();
34 + nd_sd_journal_annotations_init();
35 + nd_journal_init_files_and_directories();
36
37 if (!journal_data_directories_exist()) {
38 nd_log_collector(NDLP_INFO, "unable to locate journal data directories. Exiting...");
@@ -41,26 +44,22 @@ int main(int argc __maybe_unused, char **argv __maybe_unused) {
44 // ------------------------------------------------------------------------
45 // debug
46
44 - if(argc == 2 && strcmp(argv[1], "debug") == 0) {
45 - journal_files_registry_update();
47 + if (argc == 2 && strcmp(argv[1], "debug") == 0) {
48 + nd_journal_files_registry_update();
49
50 bool cancelled = false;
51 usec_t stop_monotonic_ut = now_monotonic_usec() + 600 * USEC_PER_SEC;
49 - // char buf[] = "systemd-journal after:1726573205 before:1726574105 last:200 facets:F9q1S4.MEeL,DHKucpqUoe1,MewN7JHJ.3X,LKWfxQdCIoc,IjWzTvQ9.4t,O6O.cgYOhns,KmQ1KSeTSfO,IIsT7Ytfxy6,EQD6.NflJQq,I6rMJzShJIE,DxoIlg6RTuM,AU4H2NMVPXJ,H4mcdIPho07,EDYhj5U8330,DloDtGMQHje,JHSbsQ2fXqr,AIRrOu._40Z,NFZXv8AEpS_,Iiic3t4NuxV,F2YCtRNSfDv,GOUMAmZiRrq,O0VYoHcyq49,FDQoaBH15Bp,ClBB5dSGmCc,GTwmQptJYkk,BWH4O3GPNSL,APv6JsKkF9X,IAURKhjtcRF,Jw1dz4fJmFr slice:true source:all";
50 - char buf[] = "systemd-journal after:-8640000 before:0 direction:backward last:200 data_only:false slice:true facets: source:all";
51 - // char buf[] = "systemd-journal after:1695332964 before:1695937764 direction:backward last:100 slice:true source:all DHKucpqUoe1:PtVoyIuX.MU";
52 - // char buf[] = "systemd-journal after:1694511062 before:1694514662 anchor:1694514122024403";
53 - function_systemd_journal("123", buf, &stop_monotonic_ut, &cancelled,
54 - NULL, HTTP_ACCESS_ALL, NULL, NULL);
55 -// function_systemd_units("123", "systemd-units", 600, &cancelled);
52 + char buf[] =
53 + "systemd-journal after:-8640000 before:0 direction:backward last:200 data_only:false slice:true facets: source:all";
54 + function_systemd_journal("123", buf, &stop_monotonic_ut, &cancelled, NULL, HTTP_ACCESS_ALL, NULL, NULL);
55 exit(1);
56 }
57 #ifdef ENABLE_SYSTEMD_DBUS
59 - if(argc == 2 && strcmp(argv[1], "debug-units") == 0) {
58 + if (argc == 2 && strcmp(argv[1], "debug-units") == 0) {
59 bool cancelled = false;
60 usec_t stop_monotonic_ut = now_monotonic_usec() + 600 * USEC_PER_SEC;
62 - function_systemd_units("123", "systemd-units", &stop_monotonic_ut, &cancelled,
63 - NULL, HTTP_ACCESS_ALL, NULL, NULL);
61 + function_systemd_units(
62 + "123", "systemd-units", &stop_monotonic_ut, &cancelled, NULL, HTTP_ACCESS_ALL, NULL, NULL);
63 exit(1);
64 }
65 #endif
@@ -68,45 +67,47 @@ int main(int argc __maybe_unused, char **argv __maybe_unused) {
67 // ------------------------------------------------------------------------
68 // watcher thread
69
71 - nd_thread_create("SDWATCH", NETDATA_THREAD_OPTION_DONT_LOG, journal_watcher_main, NULL);
70 + nd_thread_create("SDWATCH", NETDATA_THREAD_OPTION_DONT_LOG, nd_journal_watcher_main, NULL);
71
72 // ------------------------------------------------------------------------
73 // the event loop for functions
74
75 struct functions_evloop_globals *wg =
77 - functions_evloop_init(SYSTEMD_JOURNAL_WORKER_THREADS, "SDJ", &stdout_mutex, &plugin_should_exit);
76 + functions_evloop_init(ND_SD_JOURNAL_WORKER_THREADS, "SDJ", &stdout_mutex, &plugin_should_exit);
77
79 - functions_evloop_add_function(wg,
80 - SYSTEMD_JOURNAL_FUNCTION_NAME,
81 - function_systemd_journal,
82 - SYSTEMD_JOURNAL_DEFAULT_TIMEOUT,
83 - NULL);
78 + functions_evloop_add_function(
79 + wg, ND_SD_JOURNAL_FUNCTION_NAME, function_systemd_journal, ND_SD_JOURNAL_DEFAULT_TIMEOUT, NULL);
80
81 #ifdef ENABLE_SYSTEMD_DBUS
86 - functions_evloop_add_function(wg,
87 - SYSTEMD_UNITS_FUNCTION_NAME,
88 - function_systemd_units,
89 - SYSTEMD_UNITS_DEFAULT_TIMEOUT,
90 - NULL);
82 + functions_evloop_add_function(
83 + wg, ND_SD_UNITS_FUNCTION_NAME, function_systemd_units, ND_SD_UNITS_DEFAULT_TIMEOUT, NULL);
84 #endif
85
93 - systemd_journal_dyncfg_init(wg);
86 + nd_systemd_journal_dyncfg_init(wg);
87
88 // ------------------------------------------------------------------------
89 // register functions to netdata
90
91 netdata_mutex_lock(&stdout_mutex);
92
100 - fprintf(stdout, PLUGINSD_KEYWORD_FUNCTION " GLOBAL \"%s\" %d \"%s\" \"logs\" "HTTP_ACCESS_FORMAT" %d\n",
101 - SYSTEMD_JOURNAL_FUNCTION_NAME, SYSTEMD_JOURNAL_DEFAULT_TIMEOUT, SYSTEMD_JOURNAL_FUNCTION_DESCRIPTION,
102 - (HTTP_ACCESS_FORMAT_CAST)(HTTP_ACCESS_SIGNED_ID | HTTP_ACCESS_SAME_SPACE | HTTP_ACCESS_SENSITIVE_DATA),
103 - RRDFUNCTIONS_PRIORITY_DEFAULT);
93 + fprintf(
94 + stdout,
95 + PLUGINSD_KEYWORD_FUNCTION " GLOBAL \"%s\" %d \"%s\" \"logs\" " HTTP_ACCESS_FORMAT " %d\n",
96 + ND_SD_JOURNAL_FUNCTION_NAME,
97 + ND_SD_JOURNAL_DEFAULT_TIMEOUT,
98 + ND_SD_JOURNAL_FUNCTION_DESCRIPTION,
99 + (HTTP_ACCESS_FORMAT_CAST)(HTTP_ACCESS_SIGNED_ID | HTTP_ACCESS_SAME_SPACE | HTTP_ACCESS_SENSITIVE_DATA),
100 + RRDFUNCTIONS_PRIORITY_DEFAULT);
101
102 #ifdef ENABLE_SYSTEMD_DBUS
106 - fprintf(stdout, PLUGINSD_KEYWORD_FUNCTION " GLOBAL \"%s\" %d \"%s\" \"top\" "HTTP_ACCESS_FORMAT" %d\n",
107 - SYSTEMD_UNITS_FUNCTION_NAME, SYSTEMD_UNITS_DEFAULT_TIMEOUT, SYSTEMD_UNITS_FUNCTION_DESCRIPTION,
108 - (HTTP_ACCESS_FORMAT_CAST)(HTTP_ACCESS_SIGNED_ID | HTTP_ACCESS_SAME_SPACE | HTTP_ACCESS_SENSITIVE_DATA),
109 - RRDFUNCTIONS_PRIORITY_DEFAULT);
103 + fprintf(
104 + stdout,
105 + PLUGINSD_KEYWORD_FUNCTION " GLOBAL \"%s\" %d \"%s\" \"top\" " HTTP_ACCESS_FORMAT " %d\n",
106 + ND_SD_UNITS_FUNCTION_NAME,
107 + ND_SD_UNITS_DEFAULT_TIMEOUT,
108 + ND_SD_UNITS_FUNCTION_DESCRIPTION,
109 + (HTTP_ACCESS_FORMAT_CAST)(HTTP_ACCESS_SIGNED_ID | HTTP_ACCESS_SAME_SPACE | HTTP_ACCESS_SENSITIVE_DATA),
110 + RRDFUNCTIONS_PRIORITY_DEFAULT);
111 #endif
112
113 fflush(stdout);
@@ -115,15 +116,15 @@ int main(int argc __maybe_unused, char **argv __maybe_unused) {
116 // ------------------------------------------------------------------------
117
118 usec_t send_newline_ut = 0;
118 - usec_t since_last_scan_ut = SYSTEMD_JOURNAL_ALL_FILES_SCAN_EVERY_USEC * 2; // something big to trigger scanning at start
119 + usec_t since_last_scan_ut =
120 + ND_SD_JOURNAL_ALL_FILES_SCAN_EVERY_USEC * 2; // something big to trigger scanning at start
121 const bool tty = isatty(fileno(stdout)) == 1;
122
123 heartbeat_t hb;
124 heartbeat_init(&hb, USEC_PER_SEC);
123 - while(!plugin_should_exit) {
124 -
125 - if(since_last_scan_ut > SYSTEMD_JOURNAL_ALL_FILES_SCAN_EVERY_USEC) {
126 - journal_files_registry_update();
125 + while (!plugin_should_exit) {
126 + if (since_last_scan_ut > ND_SD_JOURNAL_ALL_FILES_SCAN_EVERY_USEC) {
127 + nd_journal_files_registry_update();
128 since_last_scan_ut = 0;
129 }
130
@@ -131,7 +132,7 @@ int main(int argc __maybe_unused, char **argv __maybe_unused) {
132 since_last_scan_ut += dt_ut;
133 send_newline_ut += dt_ut;
134
134 - if(!tty && send_newline_ut > USEC_PER_SEC) {
135 + if (!tty && send_newline_ut > USEC_PER_SEC) {
136 send_newline_and_flush(&stdout_mutex);
137 send_newline_ut = 0;
138 }
src/collectors/systemd-journal.plugin/systemd-units.c
+796 -591
@@ -5,79 +5,80 @@
5 #ifdef ENABLE_SYSTEMD_DBUS
6 #include <systemd/sd-bus.h>
7
8 -#define SYSTEMD_UNITS_MAX_PARAMS 10
9 -#define SYSTEMD_UNITS_DBUS_TYPES "(ssssssouso)"
8 +#define ND_SD_UNITS_MAX_PARAMS 10
9 +#define ND_SD_UNITS_DBUS_TYPES "(ssssssouso)"
10
11 // ----------------------------------------------------------------------------
12 // copied from systemd: string-table.h
13
14 typedef char sd_char;
15 -#define XCONCATENATE(x, y) x ## y
15 +#define XCONCATENATE(x, y) x##y
16 #define CONCATENATE(x, y) XCONCATENATE(x, y)
17
18 #ifndef __COVERITY__
19 -# define VOID_0 ((void)0)
19 +#define VOID_0 ((void)0)
20 #else
21 -# define VOID_0 ((void*)0)
21 +#define VOID_0 ((void *)0)
22 #endif
23
24 -#define ELEMENTSOF(x) \
25 - (__builtin_choose_expr( \
26 - !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
27 - sizeof(x)/sizeof((x)[0]), \
28 - VOID_0))
24 +#define ELEMENTSOF(x) \
25 + (__builtin_choose_expr(!__builtin_types_compatible_p(typeof(x), typeof(&*(x))), sizeof(x) / sizeof((x)[0]), VOID_0))
26
27 #define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
28 #define UNIQ __COUNTER__
32 -#define __CMP(aq, a, bq, b) \
33 - ({ \
34 - const typeof(a) UNIQ_T(A, aq) = (a); \
35 - const typeof(b) UNIQ_T(B, bq) = (b); \
36 - UNIQ_T(A, aq) < UNIQ_T(B, bq) ? -1 : \
37 - UNIQ_T(A, aq) > UNIQ_T(B, bq) ? 1 : 0; \
38 - })
29 +#define __CMP(aq, a, bq, b) \
30 + ({ \
31 + const typeof(a) UNIQ_T(A, aq) = (a); \
32 + const typeof(b) UNIQ_T(B, bq) = (b); \
33 + UNIQ_T(A, aq)<UNIQ_T(B, bq) ? -1 : UNIQ_T(A, aq)> UNIQ_T(B, bq) ? 1 : 0; \
34 + })
35 #define CMP(a, b) __CMP(UNIQ, (a), UNIQ, (b))
36
41 -static inline int strcmp_ptr(const sd_char *a, const sd_char *b) {
37 +static inline int strcmp_ptr(const sd_char *a, const sd_char *b)
38 +{
39 if (a && b)
40 return strcmp(a, b);
41
42 return CMP(a, b);
43 }
44
48 -static inline bool streq_ptr(const sd_char *a, const sd_char *b) {
45 +static inline bool streq_ptr(const sd_char *a, const sd_char *b)
46 +{
47 return strcmp_ptr(a, b) == 0;
48 }
49
52 -static ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
50 +static ssize_t string_table_lookup(const char *const *table, size_t len, const char *key)
51 +{
52 if (!key || !*key)
53 return -EINVAL;
54
55 for (size_t i = 0; i < len; ++i)
56 if (streq_ptr(table[i], key))
58 - return (ssize_t) i;
57 + return (ssize_t)i;
58
59 return -EINVAL;
60 }
61
62 /* For basic lookup tables with strictly enumerated entries */
64 -#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
65 - scope const char *name##_to_string(type i) { \
66 - if (i < 0 || i >= (type) ELEMENTSOF(name##_table)) \
67 - return NULL; \
68 - return name##_table[i]; \
69 - }
63 +#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name, type, scope) \
64 + scope const char *name##_to_string(type i) \
65 + { \
66 + if (i < 0 || i >= (type)ELEMENTSOF(name##_table)) \
67 + return NULL; \
68 + return name##_table[i]; \
69 + }
70
71 -#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
72 - scope type name##_from_string(const char *s) { \
73 - return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
74 - }
71 +#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name, type, scope) \
72 + scope type name##_from_string(const char *s) \
73 + { \
74 + return (type)string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
75 + }
76
76 -#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
77 - _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
78 - _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope)
77 +#define _DEFINE_STRING_TABLE_LOOKUP(name, type, scope) \
78 + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name, type, scope) \
79 + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name, type, scope)
80
80 -#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
81 +#define DEFINE_STRING_TABLE_LOOKUP(name, type) _DEFINE_STRING_TABLE_LOOKUP(name, type, )
82
83 // ----------------------------------------------------------------------------
84 // copied from systemd: unit-def.h
@@ -101,9 +102,9 @@ typedef enum UnitType {
102 typedef enum UnitLoadState {
103 UNIT_STUB,
104 UNIT_LOADED,
104 - UNIT_NOT_FOUND, /* error condition #1: unit file not found */
105 - UNIT_BAD_SETTING, /* error condition #2: we couldn't parse some essential unit file setting */
106 - UNIT_ERROR, /* error condition #3: other "system" error, catchall for the rest */
105 + UNIT_NOT_FOUND, /* error condition #1: unit file not found */
106 + UNIT_BAD_SETTING, /* error condition #2: we couldn't parse some essential unit file setting */
107 + UNIT_ERROR, /* error condition #3: other "system" error, catchall for the rest */
108 UNIT_MERGED,
109 UNIT_MASKED,
110 _UNIT_LOAD_STATE_MAX,
@@ -141,8 +142,8 @@ typedef enum DeviceState {
142
143 typedef enum MountState {
144 MOUNT_DEAD,
144 - MOUNT_MOUNTING, /* /usr/bin/mount is running, but the mount is not done yet. */
145 - MOUNT_MOUNTING_DONE, /* /usr/bin/mount is running, and the mount is done. */
145 + MOUNT_MOUNTING, /* /usr/bin/mount is running, but the mount is not done yet. */
146 + MOUNT_MOUNTING_DONE, /* /usr/bin/mount is running, and the mount is done. */
147 MOUNT_MOUNTED,
148 MOUNT_REMOUNTING,
149 MOUNT_UNMOUNTING,
@@ -184,22 +185,22 @@ typedef enum ServiceState {
185 SERVICE_START,
186 SERVICE_START_POST,
187 SERVICE_RUNNING,
187 - SERVICE_EXITED, /* Nothing is running anymore, but RemainAfterExit is true hence this is OK */
188 - SERVICE_RELOAD, /* Reloading via ExecReload= */
189 - SERVICE_RELOAD_SIGNAL, /* Reloading via SIGHUP requested */
190 - SERVICE_RELOAD_NOTIFY, /* Waiting for READY=1 after RELOADING=1 notify */
191 - SERVICE_STOP, /* No STOP_PRE state, instead just register multiple STOP executables */
188 + SERVICE_EXITED, /* Nothing is running anymore, but RemainAfterExit is true hence this is OK */
189 + SERVICE_RELOAD, /* Reloading via ExecReload= */
190 + SERVICE_RELOAD_SIGNAL, /* Reloading via SIGHUP requested */
191 + SERVICE_RELOAD_NOTIFY, /* Waiting for READY=1 after RELOADING=1 notify */
192 + SERVICE_STOP, /* No STOP_PRE state, instead just register multiple STOP executables */
193 SERVICE_STOP_WATCHDOG,
194 SERVICE_STOP_SIGTERM,
195 SERVICE_STOP_SIGKILL,
196 SERVICE_STOP_POST,
196 - SERVICE_FINAL_WATCHDOG, /* In case the STOP_POST executable needs to be aborted. */
197 - SERVICE_FINAL_SIGTERM, /* In case the STOP_POST executable hangs, we shoot that down, too */
197 + SERVICE_FINAL_WATCHDOG, /* In case the STOP_POST executable needs to be aborted. */
198 + SERVICE_FINAL_SIGTERM, /* In case the STOP_POST executable hangs, we shoot that down, too */
199 SERVICE_FINAL_SIGKILL,
200 SERVICE_FAILED,
201 SERVICE_DEAD_BEFORE_AUTO_RESTART,
202 SERVICE_FAILED_BEFORE_AUTO_RESTART,
202 - SERVICE_DEAD_RESOURCES_PINNED, /* Like SERVICE_DEAD, but with pinned resources */
203 + SERVICE_DEAD_RESOURCES_PINNED, /* Like SERVICE_DEAD, but with pinned resources */
204 SERVICE_AUTO_RESTART,
205 SERVICE_AUTO_RESTART_QUEUED,
206 SERVICE_CLEANING,
@@ -235,8 +236,8 @@ typedef enum SocketState {
236
237 typedef enum SwapState {
238 SWAP_DEAD,
238 - SWAP_ACTIVATING, /* /sbin/swapon is running, but the swap not yet enabled. */
239 - SWAP_ACTIVATING_DONE, /* /sbin/swapon is running, and the swap is done. */
239 + SWAP_ACTIVATING, /* /sbin/swapon is running, but the swap not yet enabled. */
240 + SWAP_ACTIVATING_DONE, /* /sbin/swapon is running, and the swap is done. */
241 SWAP_ACTIVE,
242 SWAP_DEACTIVATING,
243 SWAP_DEACTIVATING_SIGTERM,
@@ -276,193 +277,180 @@ typedef enum FreezerState {
277 // ----------------------------------------------------------------------------
278 // copied from systemd: unit-def.c
279
279 -static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
280 - [UNIT_SERVICE] = "service",
281 - [UNIT_SOCKET] = "socket",
282 - [UNIT_TARGET] = "target",
283 - [UNIT_DEVICE] = "device",
284 - [UNIT_MOUNT] = "mount",
285 - [UNIT_AUTOMOUNT] = "automount",
286 - [UNIT_SWAP] = "swap",
287 - [UNIT_TIMER] = "timer",
288 - [UNIT_PATH] = "path",
289 - [UNIT_SLICE] = "slice",
290 - [UNIT_SCOPE] = "scope",
280 +static const char *const unit_type_table[_UNIT_TYPE_MAX] = {
281 + [UNIT_SERVICE] = "service",
282 + [UNIT_SOCKET] = "socket",
283 + [UNIT_TARGET] = "target",
284 + [UNIT_DEVICE] = "device",
285 + [UNIT_MOUNT] = "mount",
286 + [UNIT_AUTOMOUNT] = "automount",
287 + [UNIT_SWAP] = "swap",
288 + [UNIT_TIMER] = "timer",
289 + [UNIT_PATH] = "path",
290 + [UNIT_SLICE] = "slice",
291 + [UNIT_SCOPE] = "scope",
292 };
293
294 DEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType);
295
295 -static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
296 - [UNIT_STUB] = "stub",
297 - [UNIT_LOADED] = "loaded",
298 - [UNIT_NOT_FOUND] = "not-found",
299 - [UNIT_BAD_SETTING] = "bad-setting",
300 - [UNIT_ERROR] = "error",
301 - [UNIT_MERGED] = "merged",
302 - [UNIT_MASKED] = "masked"
303 -};
296 +static const char *const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
297 + [UNIT_STUB] = "stub",
298 + [UNIT_LOADED] = "loaded",
299 + [UNIT_NOT_FOUND] = "not-found",
300 + [UNIT_BAD_SETTING] = "bad-setting",
301 + [UNIT_ERROR] = "error",
302 + [UNIT_MERGED] = "merged",
303 + [UNIT_MASKED] = "masked"};
304
305 DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
306
307 -static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
308 - [UNIT_ACTIVE] = "active",
309 - [UNIT_RELOADING] = "reloading",
310 - [UNIT_INACTIVE] = "inactive",
311 - [UNIT_FAILED] = "failed",
312 - [UNIT_ACTIVATING] = "activating",
313 - [UNIT_DEACTIVATING] = "deactivating",
314 - [UNIT_MAINTENANCE] = "maintenance",
307 +static const char *const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
308 + [UNIT_ACTIVE] = "active",
309 + [UNIT_RELOADING] = "reloading",
310 + [UNIT_INACTIVE] = "inactive",
311 + [UNIT_FAILED] = "failed",
312 + [UNIT_ACTIVATING] = "activating",
313 + [UNIT_DEACTIVATING] = "deactivating",
314 + [UNIT_MAINTENANCE] = "maintenance",
315 };
316
317 DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
318
319 -static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
320 - [AUTOMOUNT_DEAD] = "dead",
321 - [AUTOMOUNT_WAITING] = "waiting",
322 - [AUTOMOUNT_RUNNING] = "running",
323 - [AUTOMOUNT_FAILED] = "failed"
324 -};
319 +static const char *const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
320 + [AUTOMOUNT_DEAD] = "dead",
321 + [AUTOMOUNT_WAITING] = "waiting",
322 + [AUTOMOUNT_RUNNING] = "running",
323 + [AUTOMOUNT_FAILED] = "failed"};
324
325 DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
326
328 -static const char* const device_state_table[_DEVICE_STATE_MAX] = {
329 - [DEVICE_DEAD] = "dead",
330 - [DEVICE_TENTATIVE] = "tentative",
331 - [DEVICE_PLUGGED] = "plugged",
327 +static const char *const device_state_table[_DEVICE_STATE_MAX] = {
328 + [DEVICE_DEAD] = "dead",
329 + [DEVICE_TENTATIVE] = "tentative",
330 + [DEVICE_PLUGGED] = "plugged",
331 };
332
333 DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
334
336 -static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
337 - [MOUNT_DEAD] = "dead",
338 - [MOUNT_MOUNTING] = "mounting",
339 - [MOUNT_MOUNTING_DONE] = "mounting-done",
340 - [MOUNT_MOUNTED] = "mounted",
341 - [MOUNT_REMOUNTING] = "remounting",
342 - [MOUNT_UNMOUNTING] = "unmounting",
343 - [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
344 - [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
345 - [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
346 - [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
347 - [MOUNT_FAILED] = "failed",
348 - [MOUNT_CLEANING] = "cleaning",
335 +static const char *const mount_state_table[_MOUNT_STATE_MAX] = {
336 + [MOUNT_DEAD] = "dead",
337 + [MOUNT_MOUNTING] = "mounting",
338 + [MOUNT_MOUNTING_DONE] = "mounting-done",
339 + [MOUNT_MOUNTED] = "mounted",
340 + [MOUNT_REMOUNTING] = "remounting",
341 + [MOUNT_UNMOUNTING] = "unmounting",
342 + [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
343 + [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
344 + [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
345 + [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
346 + [MOUNT_FAILED] = "failed",
347 + [MOUNT_CLEANING] = "cleaning",
348 };
349
350 DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
351
353 -static const char* const path_state_table[_PATH_STATE_MAX] = {
354 - [PATH_DEAD] = "dead",
355 - [PATH_WAITING] = "waiting",
356 - [PATH_RUNNING] = "running",
357 - [PATH_FAILED] = "failed"
358 -};
352 +static const char *const path_state_table[_PATH_STATE_MAX] =
353 + {[PATH_DEAD] = "dead", [PATH_WAITING] = "waiting", [PATH_RUNNING] = "running", [PATH_FAILED] = "failed"};
354
355 DEFINE_STRING_TABLE_LOOKUP(path_state, PathState);
356
362 -static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
363 - [SCOPE_DEAD] = "dead",
364 - [SCOPE_START_CHOWN] = "start-chown",
365 - [SCOPE_RUNNING] = "running",
366 - [SCOPE_ABANDONED] = "abandoned",
367 - [SCOPE_STOP_SIGTERM] = "stop-sigterm",
368 - [SCOPE_STOP_SIGKILL] = "stop-sigkill",
369 - [SCOPE_FAILED] = "failed",
357 +static const char *const scope_state_table[_SCOPE_STATE_MAX] = {
358 + [SCOPE_DEAD] = "dead",
359 + [SCOPE_START_CHOWN] = "start-chown",
360 + [SCOPE_RUNNING] = "running",
361 + [SCOPE_ABANDONED] = "abandoned",
362 + [SCOPE_STOP_SIGTERM] = "stop-sigterm",
363 + [SCOPE_STOP_SIGKILL] = "stop-sigkill",
364 + [SCOPE_FAILED] = "failed",
365 };
366
367 DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
368
374 -static const char* const service_state_table[_SERVICE_STATE_MAX] = {
375 - [SERVICE_DEAD] = "dead",
376 - [SERVICE_CONDITION] = "condition",
377 - [SERVICE_START_PRE] = "start-pre",
378 - [SERVICE_START] = "start",
379 - [SERVICE_START_POST] = "start-post",
380 - [SERVICE_RUNNING] = "running",
381 - [SERVICE_EXITED] = "exited",
382 - [SERVICE_RELOAD] = "reload",
383 - [SERVICE_RELOAD_SIGNAL] = "reload-signal",
384 - [SERVICE_RELOAD_NOTIFY] = "reload-notify",
385 - [SERVICE_STOP] = "stop",
386 - [SERVICE_STOP_WATCHDOG] = "stop-watchdog",
387 - [SERVICE_STOP_SIGTERM] = "stop-sigterm",
388 - [SERVICE_STOP_SIGKILL] = "stop-sigkill",
389 - [SERVICE_STOP_POST] = "stop-post",
390 - [SERVICE_FINAL_WATCHDOG] = "final-watchdog",
391 - [SERVICE_FINAL_SIGTERM] = "final-sigterm",
392 - [SERVICE_FINAL_SIGKILL] = "final-sigkill",
393 - [SERVICE_FAILED] = "failed",
394 - [SERVICE_DEAD_BEFORE_AUTO_RESTART] = "dead-before-auto-restart",
395 - [SERVICE_FAILED_BEFORE_AUTO_RESTART] = "failed-before-auto-restart",
396 - [SERVICE_DEAD_RESOURCES_PINNED] = "dead-resources-pinned",
397 - [SERVICE_AUTO_RESTART] = "auto-restart",
398 - [SERVICE_AUTO_RESTART_QUEUED] = "auto-restart-queued",
399 - [SERVICE_CLEANING] = "cleaning",
369 +static const char *const service_state_table[_SERVICE_STATE_MAX] = {
370 + [SERVICE_DEAD] = "dead",
371 + [SERVICE_CONDITION] = "condition",
372 + [SERVICE_START_PRE] = "start-pre",
373 + [SERVICE_START] = "start",
374 + [SERVICE_START_POST] = "start-post",
375 + [SERVICE_RUNNING] = "running",
376 + [SERVICE_EXITED] = "exited",
377 + [SERVICE_RELOAD] = "reload",
378 + [SERVICE_RELOAD_SIGNAL] = "reload-signal",
379 + [SERVICE_RELOAD_NOTIFY] = "reload-notify",
380 + [SERVICE_STOP] = "stop",
381 + [SERVICE_STOP_WATCHDOG] = "stop-watchdog",
382 + [SERVICE_STOP_SIGTERM] = "stop-sigterm",
383 + [SERVICE_STOP_SIGKILL] = "stop-sigkill",
384 + [SERVICE_STOP_POST] = "stop-post",
385 + [SERVICE_FINAL_WATCHDOG] = "final-watchdog",
386 + [SERVICE_FINAL_SIGTERM] = "final-sigterm",
387 + [SERVICE_FINAL_SIGKILL] = "final-sigkill",
388 + [SERVICE_FAILED] = "failed",
389 + [SERVICE_DEAD_BEFORE_AUTO_RESTART] = "dead-before-auto-restart",
390 + [SERVICE_FAILED_BEFORE_AUTO_RESTART] = "failed-before-auto-restart",
391 + [SERVICE_DEAD_RESOURCES_PINNED] = "dead-resources-pinned",
392 + [SERVICE_AUTO_RESTART] = "auto-restart",
393 + [SERVICE_AUTO_RESTART_QUEUED] = "auto-restart-queued",
394 + [SERVICE_CLEANING] = "cleaning",
395 };
396
397 DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState);
398
404 -static const char* const slice_state_table[_SLICE_STATE_MAX] = {
405 - [SLICE_DEAD] = "dead",
406 - [SLICE_ACTIVE] = "active"
407 -};
399 +static const char *const slice_state_table[_SLICE_STATE_MAX] = {[SLICE_DEAD] = "dead", [SLICE_ACTIVE] = "active"};
400
401 DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
402
411 -static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
412 - [SOCKET_DEAD] = "dead",
413 - [SOCKET_START_PRE] = "start-pre",
414 - [SOCKET_START_CHOWN] = "start-chown",
415 - [SOCKET_START_POST] = "start-post",
416 - [SOCKET_LISTENING] = "listening",
417 - [SOCKET_RUNNING] = "running",
418 - [SOCKET_STOP_PRE] = "stop-pre",
419 - [SOCKET_STOP_PRE_SIGTERM] = "stop-pre-sigterm",
420 - [SOCKET_STOP_PRE_SIGKILL] = "stop-pre-sigkill",
421 - [SOCKET_STOP_POST] = "stop-post",
422 - [SOCKET_FINAL_SIGTERM] = "final-sigterm",
423 - [SOCKET_FINAL_SIGKILL] = "final-sigkill",
424 - [SOCKET_FAILED] = "failed",
425 - [SOCKET_CLEANING] = "cleaning",
403 +static const char *const socket_state_table[_SOCKET_STATE_MAX] = {
404 + [SOCKET_DEAD] = "dead",
405 + [SOCKET_START_PRE] = "start-pre",
406 + [SOCKET_START_CHOWN] = "start-chown",
407 + [SOCKET_START_POST] = "start-post",
408 + [SOCKET_LISTENING] = "listening",
409 + [SOCKET_RUNNING] = "running",
410 + [SOCKET_STOP_PRE] = "stop-pre",
411 + [SOCKET_STOP_PRE_SIGTERM] = "stop-pre-sigterm",
412 + [SOCKET_STOP_PRE_SIGKILL] = "stop-pre-sigkill",
413 + [SOCKET_STOP_POST] = "stop-post",
414 + [SOCKET_FINAL_SIGTERM] = "final-sigterm",
415 + [SOCKET_FINAL_SIGKILL] = "final-sigkill",
416 + [SOCKET_FAILED] = "failed",
417 + [SOCKET_CLEANING] = "cleaning",
418 };
419
420 DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
421
430 -static const char* const swap_state_table[_SWAP_STATE_MAX] = {
431 - [SWAP_DEAD] = "dead",
432 - [SWAP_ACTIVATING] = "activating",
433 - [SWAP_ACTIVATING_DONE] = "activating-done",
434 - [SWAP_ACTIVE] = "active",
435 - [SWAP_DEACTIVATING] = "deactivating",
436 - [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
437 - [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
438 - [SWAP_FAILED] = "failed",
439 - [SWAP_CLEANING] = "cleaning",
422 +static const char *const swap_state_table[_SWAP_STATE_MAX] = {
423 + [SWAP_DEAD] = "dead",
424 + [SWAP_ACTIVATING] = "activating",
425 + [SWAP_ACTIVATING_DONE] = "activating-done",
426 + [SWAP_ACTIVE] = "active",
427 + [SWAP_DEACTIVATING] = "deactivating",
428 + [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
429 + [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
430 + [SWAP_FAILED] = "failed",
431 + [SWAP_CLEANING] = "cleaning",
432 };
433
434 DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
435
444 -static const char* const target_state_table[_TARGET_STATE_MAX] = {
445 - [TARGET_DEAD] = "dead",
446 - [TARGET_ACTIVE] = "active"
447 -};
436 +static const char *const target_state_table[_TARGET_STATE_MAX] = {[TARGET_DEAD] = "dead", [TARGET_ACTIVE] = "active"};
437
438 DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
439
451 -static const char* const timer_state_table[_TIMER_STATE_MAX] = {
452 - [TIMER_DEAD] = "dead",
453 - [TIMER_WAITING] = "waiting",
454 - [TIMER_RUNNING] = "running",
455 - [TIMER_ELAPSED] = "elapsed",
456 - [TIMER_FAILED] = "failed"
457 -};
440 +static const char *const timer_state_table[_TIMER_STATE_MAX] = {
441 + [TIMER_DEAD] = "dead",
442 + [TIMER_WAITING] = "waiting",
443 + [TIMER_RUNNING] = "running",
444 + [TIMER_ELAPSED] = "elapsed",
445 + [TIMER_FAILED] = "failed"};
446
447 DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
448
461 -static const char* const freezer_state_table[_FREEZER_STATE_MAX] = {
462 - [FREEZER_RUNNING] = "running",
463 - [FREEZER_FREEZING] = "freezing",
464 - [FREEZER_FROZEN] = "frozen",
465 - [FREEZER_THAWING] = "thawing",
449 +static const char *const freezer_state_table[_FREEZER_STATE_MAX] = {
450 + [FREEZER_RUNNING] = "running",
451 + [FREEZER_FREEZING] = "freezing",
452 + [FREEZER_FROZEN] = "frozen",
453 + [FREEZER_THAWING] = "thawing",
454 };
455
456 DEFINE_STRING_TABLE_LOOKUP(freezer_state, FreezerState);
@@ -505,28 +493,32 @@ static const struct {
493 .info = "Service Type",
494 .options = RRDF_FIELD_OPTS_VISIBLE,
495 .filter = RRDF_FIELD_FILTER_MULTISELECT,
508 - }, {
496 + },
497 + {
498 .member = "Result",
499 .value_type = SD_BUS_TYPE_STRING,
500 .show_as = "Result",
501 .info = "Result",
502 .options = RRDF_FIELD_OPTS_VISIBLE,
503 .filter = RRDF_FIELD_FILTER_MULTISELECT,
515 - }, {
504 + },
505 + {
506 .member = "UnitFileState",
507 .value_type = SD_BUS_TYPE_STRING,
508 .show_as = "Enabled",
509 .info = "Unit File State",
510 .options = RRDF_FIELD_OPTS_NONE,
511 .filter = RRDF_FIELD_FILTER_MULTISELECT,
522 - }, {
512 + },
513 + {
514 .member = "UnitFilePreset",
515 .value_type = SD_BUS_TYPE_STRING,
516 .show_as = "Preset",
517 .info = "Unit File Preset",
518 .options = RRDF_FIELD_OPTS_NONE,
519 .filter = RRDF_FIELD_FILTER_MULTISELECT,
529 - }, {
520 + },
521 + {
522 .member = "FreezerState",
523 .value_type = SD_BUS_TYPE_STRING,
524 .show_as = "FreezerState",
@@ -534,97 +526,97 @@ static const struct {
526 .options = RRDF_FIELD_OPTS_NONE,
527 .filter = RRDF_FIELD_FILTER_MULTISELECT,
528 .handler = update_freezer_state,
537 - },
538 -// { .member = "Id", .signature = "s", },
539 -// { .member = "LoadState", .signature = "s", },
540 -// { .member = "ActiveState", .signature = "s", },
541 -// { .member = "SubState", .signature = "s", },
542 -// { .member = "Description", .signature = "s", },
543 -// { .member = "Following", .signature = "s", },
544 -// { .member = "Documentation", .signature = "as", },
545 -// { .member = "FragmentPath", .signature = "s", },
546 -// { .member = "SourcePath", .signature = "s", },
547 -// { .member = "ControlGroup", .signature = "s", },
548 -// { .member = "DropInPaths", .signature = "as", },
549 -// { .member = "LoadError", .signature = "(ss)", },
550 -// { .member = "TriggeredBy", .signature = "as", },
551 -// { .member = "Triggers", .signature = "as", },
552 -// { .member = "InactiveExitTimestamp", .signature = "t", },
553 -// { .member = "InactiveExitTimestampMonotonic", .signature = "t", },
554 -// { .member = "ActiveEnterTimestamp", .signature = "t", },
555 -// { .member = "ActiveExitTimestamp", .signature = "t", },
556 -// { .member = "RuntimeMaxUSec", .signature = "t", },
557 -// { .member = "InactiveEnterTimestamp", .signature = "t", },
558 -// { .member = "NeedDaemonReload", .signature = "b", },
559 -// { .member = "Transient", .signature = "b", },
560 -// { .member = "ExecMainPID", .signature = "u", },
561 -// { .member = "MainPID", .signature = "u", },
562 -// { .member = "ControlPID", .signature = "u", },
563 -// { .member = "StatusText", .signature = "s", },
564 -// { .member = "PIDFile", .signature = "s", },
565 -// { .member = "StatusErrno", .signature = "i", },
566 -// { .member = "FileDescriptorStoreMax", .signature = "u", },
567 -// { .member = "NFileDescriptorStore", .signature = "u", },
568 -// { .member = "ExecMainStartTimestamp", .signature = "t", },
569 -// { .member = "ExecMainExitTimestamp", .signature = "t", },
570 -// { .member = "ExecMainCode", .signature = "i", },
571 -// { .member = "ExecMainStatus", .signature = "i", },
572 -// { .member = "LogNamespace", .signature = "s", },
573 -// { .member = "ConditionTimestamp", .signature = "t", },
574 -// { .member = "ConditionResult", .signature = "b", },
575 -// { .member = "Conditions", .signature = "a(sbbsi)", },
576 -// { .member = "AssertTimestamp", .signature = "t", },
577 -// { .member = "AssertResult", .signature = "b", },
578 -// { .member = "Asserts", .signature = "a(sbbsi)", },
579 -// { .member = "NextElapseUSecRealtime", .signature = "t", },
580 -// { .member = "NextElapseUSecMonotonic", .signature = "t", },
581 -// { .member = "NAccepted", .signature = "u", },
582 -// { .member = "NConnections", .signature = "u", },
583 -// { .member = "NRefused", .signature = "u", },
584 -// { .member = "Accept", .signature = "b", },
585 -// { .member = "Listen", .signature = "a(ss)", },
586 -// { .member = "SysFSPath", .signature = "s", },
587 -// { .member = "Where", .signature = "s", },
588 -// { .member = "What", .signature = "s", },
589 -// { .member = "MemoryCurrent", .signature = "t", },
590 -// { .member = "MemoryAvailable", .signature = "t", },
591 -// { .member = "DefaultMemoryMin", .signature = "t", },
592 -// { .member = "DefaultMemoryLow", .signature = "t", },
593 -// { .member = "DefaultStartupMemoryLow", .signature = "t", },
594 -// { .member = "MemoryMin", .signature = "t", },
595 -// { .member = "MemoryLow", .signature = "t", },
596 -// { .member = "StartupMemoryLow", .signature = "t", },
597 -// { .member = "MemoryHigh", .signature = "t", },
598 -// { .member = "StartupMemoryHigh", .signature = "t", },
599 -// { .member = "MemoryMax", .signature = "t", },
600 -// { .member = "StartupMemoryMax", .signature = "t", },
601 -// { .member = "MemorySwapMax", .signature = "t", },
602 -// { .member = "StartupMemorySwapMax", .signature = "t", },
603 -// { .member = "MemoryZSwapMax", .signature = "t", },
604 -// { .member = "StartupMemoryZSwapMax", .signature = "t", },
605 -// { .member = "MemoryLimit", .signature = "t", },
606 -// { .member = "CPUUsageNSec", .signature = "t", },
607 -// { .member = "TasksCurrent", .signature = "t", },
608 -// { .member = "TasksMax", .signature = "t", },
609 -// { .member = "IPIngressBytes", .signature = "t", },
610 -// { .member = "IPEgressBytes", .signature = "t", },
611 -// { .member = "IOReadBytes", .signature = "t", },
612 -// { .member = "IOWriteBytes", .signature = "t", },
613 -// { .member = "ExecCondition", .signature = "a(sasbttttuii)", },
614 -// { .member = "ExecConditionEx", .signature = "a(sasasttttuii)", },
615 -// { .member = "ExecStartPre", .signature = "a(sasbttttuii)", },
616 -// { .member = "ExecStartPreEx", .signature = "a(sasasttttuii)", },
617 -// { .member = "ExecStart", .signature = "a(sasbttttuii)", },
618 -// { .member = "ExecStartEx", .signature = "a(sasasttttuii)", },
619 -// { .member = "ExecStartPost", .signature = "a(sasbttttuii)", },
620 -// { .member = "ExecStartPostEx", .signature = "a(sasasttttuii)", },
621 -// { .member = "ExecReload", .signature = "a(sasbttttuii)", },
622 -// { .member = "ExecReloadEx", .signature = "a(sasasttttuii)", },
623 -// { .member = "ExecStopPre", .signature = "a(sasbttttuii)", },
624 -// { .member = "ExecStop", .signature = "a(sasbttttuii)", },
625 -// { .member = "ExecStopEx", .signature = "a(sasasttttuii)", },
626 -// { .member = "ExecStopPost", .signature = "a(sasbttttuii)", },
627 -// { .member = "ExecStopPostEx", .signature = "a(sasasttttuii)", },
529 + },
530 + // { .member = "Id", .signature = "s", },
531 + // { .member = "LoadState", .signature = "s", },
532 + // { .member = "ActiveState", .signature = "s", },
533 + // { .member = "SubState", .signature = "s", },
534 + // { .member = "Description", .signature = "s", },
535 + // { .member = "Following", .signature = "s", },
536 + // { .member = "Documentation", .signature = "as", },
537 + // { .member = "FragmentPath", .signature = "s", },
538 + // { .member = "SourcePath", .signature = "s", },
539 + // { .member = "ControlGroup", .signature = "s", },
540 + // { .member = "DropInPaths", .signature = "as", },
541 + // { .member = "LoadError", .signature = "(ss)", },
542 + // { .member = "TriggeredBy", .signature = "as", },
543 + // { .member = "Triggers", .signature = "as", },
544 + // { .member = "InactiveExitTimestamp", .signature = "t", },
545 + // { .member = "InactiveExitTimestampMonotonic", .signature = "t", },
546 + // { .member = "ActiveEnterTimestamp", .signature = "t", },
547 + // { .member = "ActiveExitTimestamp", .signature = "t", },
548 + // { .member = "RuntimeMaxUSec", .signature = "t", },
549 + // { .member = "InactiveEnterTimestamp", .signature = "t", },
550 + // { .member = "NeedDaemonReload", .signature = "b", },
551 + // { .member = "Transient", .signature = "b", },
552 + // { .member = "ExecMainPID", .signature = "u", },
553 + // { .member = "MainPID", .signature = "u", },
554 + // { .member = "ControlPID", .signature = "u", },
555 + // { .member = "StatusText", .signature = "s", },
556 + // { .member = "PIDFile", .signature = "s", },
557 + // { .member = "StatusErrno", .signature = "i", },
558 + // { .member = "FileDescriptorStoreMax", .signature = "u", },
559 + // { .member = "NFileDescriptorStore", .signature = "u", },
560 + // { .member = "ExecMainStartTimestamp", .signature = "t", },
561 + // { .member = "ExecMainExitTimestamp", .signature = "t", },
562 + // { .member = "ExecMainCode", .signature = "i", },
563 + // { .member = "ExecMainStatus", .signature = "i", },
564 + // { .member = "LogNamespace", .signature = "s", },
565 + // { .member = "ConditionTimestamp", .signature = "t", },
566 + // { .member = "ConditionResult", .signature = "b", },
567 + // { .member = "Conditions", .signature = "a(sbbsi)", },
568 + // { .member = "AssertTimestamp", .signature = "t", },
569 + // { .member = "AssertResult", .signature = "b", },
570 + // { .member = "Asserts", .signature = "a(sbbsi)", },
571 + // { .member = "NextElapseUSecRealtime", .signature = "t", },
572 + // { .member = "NextElapseUSecMonotonic", .signature = "t", },
573 + // { .member = "NAccepted", .signature = "u", },
574 + // { .member = "NConnections", .signature = "u", },
575 + // { .member = "NRefused", .signature = "u", },
576 + // { .member = "Accept", .signature = "b", },
577 + // { .member = "Listen", .signature = "a(ss)", },
578 + // { .member = "SysFSPath", .signature = "s", },
579 + // { .member = "Where", .signature = "s", },
580 + // { .member = "What", .signature = "s", },
581 + // { .member = "MemoryCurrent", .signature = "t", },
582 + // { .member = "MemoryAvailable", .signature = "t", },
583 + // { .member = "DefaultMemoryMin", .signature = "t", },
584 + // { .member = "DefaultMemoryLow", .signature = "t", },
585 + // { .member = "DefaultStartupMemoryLow", .signature = "t", },
586 + // { .member = "MemoryMin", .signature = "t", },
587 + // { .member = "MemoryLow", .signature = "t", },
588 + // { .member = "StartupMemoryLow", .signature = "t", },
589 + // { .member = "MemoryHigh", .signature = "t", },
590 + // { .member = "StartupMemoryHigh", .signature = "t", },
591 + // { .member = "MemoryMax", .signature = "t", },
592 + // { .member = "StartupMemoryMax", .signature = "t", },
593 + // { .member = "MemorySwapMax", .signature = "t", },
594 + // { .member = "StartupMemorySwapMax", .signature = "t", },
595 + // { .member = "MemoryZSwapMax", .signature = "t", },
596 + // { .member = "StartupMemoryZSwapMax", .signature = "t", },
597 + // { .member = "MemoryLimit", .signature = "t", },
598 + // { .member = "CPUUsageNSec", .signature = "t", },
599 + // { .member = "TasksCurrent", .signature = "t", },
600 + // { .member = "TasksMax", .signature = "t", },
601 + // { .member = "IPIngressBytes", .signature = "t", },
602 + // { .member = "IPEgressBytes", .signature = "t", },
603 + // { .member = "IOReadBytes", .signature = "t", },
604 + // { .member = "IOWriteBytes", .signature = "t", },
605 + // { .member = "ExecCondition", .signature = "a(sasbttttuii)", },
606 + // { .member = "ExecConditionEx", .signature = "a(sasasttttuii)", },
607 + // { .member = "ExecStartPre", .signature = "a(sasbttttuii)", },
608 + // { .member = "ExecStartPreEx", .signature = "a(sasasttttuii)", },
609 + // { .member = "ExecStart", .signature = "a(sasbttttuii)", },
610 + // { .member = "ExecStartEx", .signature = "a(sasasttttuii)", },
611 + // { .member = "ExecStartPost", .signature = "a(sasbttttuii)", },
612 + // { .member = "ExecStartPostEx", .signature = "a(sasasttttuii)", },
613 + // { .member = "ExecReload", .signature = "a(sasbttttuii)", },
614 + // { .member = "ExecReloadEx", .signature = "a(sasasttttuii)", },
615 + // { .member = "ExecStopPre", .signature = "a(sasbttttuii)", },
616 + // { .member = "ExecStop", .signature = "a(sasbttttuii)", },
617 + // { .member = "ExecStopEx", .signature = "a(sasasttttuii)", },
618 + // { .member = "ExecStopPost", .signature = "a(sasbttttuii)", },
619 + // { .member = "ExecStopPostEx", .signature = "a(sasasttttuii)", },
620 };
621
622 #define _UNIT_ATTRIBUTE_MAX (sizeof(unit_attributes) / sizeof(unit_attributes[0]))
@@ -669,40 +661,45 @@ typedef struct UnitInfo {
661 struct UnitInfo *prev, *next;
662 } UnitInfo;
663
672 -static void update_freezer_state(UnitInfo *u, UnitAttribute *ua) {
664 +static void update_freezer_state(UnitInfo *u, UnitAttribute *ua)
665 +{
666 u->FreezerState = freezer_state_from_string(ua->str);
667 }
668
669 // ----------------------------------------------------------------------------
670 // common helpers
671
679 -static void log_dbus_error(int r, const char *msg) {
680 - netdata_log_error("SYSTEMD_UNITS: %s failed with error %d (%s)", msg, r, strerror(-r));
672 +static void log_dbus_error(int r, const char *msg)
673 +{
674 + netdata_log_error("ND_SD_UNITS: %s failed with error %d (%s)", msg, r, strerror(-r));
675 }
676
677 // ----------------------------------------------------------------------------
678 // attributes management
679
686 -static inline ssize_t unit_property_slot_from_string(const char *s) {
687 - if(!s || !*s)
680 +static inline ssize_t unit_property_slot_from_string(const char *s)
681 +{
682 + if (!s || !*s)
683 return -EINVAL;
684
690 - for(size_t i = 0; i < _UNIT_ATTRIBUTE_MAX ;i++)
691 - if(streq_ptr(unit_attributes[i].member, s))
685 + for (size_t i = 0; i < _UNIT_ATTRIBUTE_MAX; i++)
686 + if (streq_ptr(unit_attributes[i].member, s))
687 return (ssize_t)i;
688
689 return -EINVAL;
690 }
691
697 -static inline const char *unit_property_name_to_string_from_slot(ssize_t i) {
698 - if(i >= 0 && i < (ssize_t)_UNIT_ATTRIBUTE_MAX)
692 +static inline const char *unit_property_name_to_string_from_slot(ssize_t i)
693 +{
694 + if (i >= 0 && i < (ssize_t)_UNIT_ATTRIBUTE_MAX)
695 return unit_attributes[i].member;
696
697 return NULL;
698 }
699
704 -static inline void systemd_unit_free_property(char type, struct UnitAttribute *at) {
705 - switch(type) {
700 +static inline void systemd_unit_free_property(char type, struct UnitAttribute *at)
701 +{
702 + switch (type) {
703 case SD_BUS_TYPE_STRING:
704 case SD_BUS_TYPE_OBJECT_PATH:
705 freez(at->str);
@@ -714,18 +711,19 @@ static inline void systemd_unit_free_property(char type, struct UnitAttribute *a
711 }
712 }
713
717 -static int systemd_unit_get_property(sd_bus_message *m, UnitInfo *u, const char *name) {
714 +static int systemd_unit_get_property(sd_bus_message *m, UnitInfo *u, const char *name)
715 +{
716 int r;
717 char type;
718
719 r = sd_bus_message_peek_type(m, &type, NULL);
722 - if(r < 0) {
720 + if (r < 0) {
721 log_dbus_error(r, "sd_bus_message_peek_type()");
722 return r;
723 }
724
725 ssize_t slot = unit_property_slot_from_string(name);
728 - if(slot < 0) {
726 + if (slot < 0) {
727 // internal_error(true, "unused attribute '%s' for unit '%s'", name, u->id);
728 sd_bus_message_skip(m, NULL);
729 return 0;
@@ -733,9 +731,12 @@ static int systemd_unit_get_property(sd_bus_message *m, UnitInfo *u, const char
731
732 systemd_unit_free_property(unit_attributes[slot].value_type, &u->attributes[slot]);
733
736 - if(unit_attributes[slot].value_type != type) {
737 - netdata_log_error("Type of field '%s' expected to be '%c' but found '%c'. Ignoring field.",
738 - unit_attributes[slot].member, unit_attributes[slot].value_type, type);
734 + if (unit_attributes[slot].value_type != type) {
735 + netdata_log_error(
736 + "Type of field '%s' expected to be '%c' but found '%c'. Ignoring field.",
737 + unit_attributes[slot].member,
738 + unit_attributes[slot].value_type,
739 + type);
740 sd_bus_message_skip(m, NULL);
741 return 0;
742 }
@@ -746,104 +747,90 @@ static int systemd_unit_get_property(sd_bus_message *m, UnitInfo *u, const char
747 char *s;
748
749 r = sd_bus_message_read_basic(m, type, &s);
749 - if(r < 0) {
750 + if (r < 0) {
751 log_dbus_error(r, "sd_bus_message_read_basic()");
752 return r;
753 }
754
754 - if(s && *s)
755 + if (s && *s)
756 u->attributes[slot].str = strdupz(s);
756 - }
757 - break;
757 + } break;
758
759 case SD_BUS_TYPE_BOOLEAN: {
760 r = sd_bus_message_read_basic(m, type, &u->attributes[slot].boolean);
761 - if(r < 0) {
761 + if (r < 0) {
762 log_dbus_error(r, "sd_bus_message_read_basic()");
763 return r;
764 }
765 - }
766 - break;
765 + } break;
766
767 case SD_BUS_TYPE_UINT64: {
768 r = sd_bus_message_read_basic(m, type, &u->attributes[slot].uint64);
770 - if(r < 0) {
769 + if (r < 0) {
770 log_dbus_error(r, "sd_bus_message_read_basic()");
771 return r;
772 }
774 - }
775 - break;
773 + } break;
774
775 case SD_BUS_TYPE_INT64: {
776 r = sd_bus_message_read_basic(m, type, &u->attributes[slot].int64);
779 - if(r < 0) {
777 + if (r < 0) {
778 log_dbus_error(r, "sd_bus_message_read_basic()");
779 return r;
780 }
783 - }
784 - break;
781 + } break;
782
783 case SD_BUS_TYPE_UINT32: {
784 r = sd_bus_message_read_basic(m, type, &u->attributes[slot].uint32);
788 - if(r < 0) {
785 + if (r < 0) {
786 log_dbus_error(r, "sd_bus_message_read_basic()");
787 return r;
788 }
792 - }
793 - break;
789 + } break;
790
791 case SD_BUS_TYPE_INT32: {
792 r = sd_bus_message_read_basic(m, type, &u->attributes[slot].int32);
797 - if(r < 0) {
793 + if (r < 0) {
794 log_dbus_error(r, "sd_bus_message_read_basic()");
795 return r;
796 }
801 - }
802 - break;
797 + } break;
798
799 case SD_BUS_TYPE_DOUBLE: {
800 r = sd_bus_message_read_basic(m, type, &u->attributes[slot].dbl);
806 - if(r < 0) {
801 + if (r < 0) {
802 log_dbus_error(r, "sd_bus_message_read_basic()");
803 return r;
804 }
810 - }
811 - break;
805 + } break;
806
807 case SD_BUS_TYPE_ARRAY: {
808 internal_error(true, "member '%s' is an array", name);
809 sd_bus_message_skip(m, NULL);
810 return 0;
817 - }
818 - break;
811 + } break;
812
813 default: {
814 internal_error(true, "unknown field type '%c' for key '%s'", type, name);
815 sd_bus_message_skip(m, NULL);
816 return 0;
824 - }
825 - break;
817 + } break;
818 }
819
828 - if(unit_attributes[slot].handler)
820 + if (unit_attributes[slot].handler)
821 unit_attributes[slot].handler(u, &u->attributes[slot]);
822
823 return 0;
824 }
825
834 -static int systemd_unit_get_all_properties(sd_bus *bus, UnitInfo *u) {
826 +static int systemd_unit_get_all_properties(sd_bus *bus, UnitInfo *u)
827 +{
828 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
829 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
830 int r;
831
839 - r = sd_bus_call_method(bus,
840 - "org.freedesktop.systemd1",
841 - u->unit_path,
842 - "org.freedesktop.DBus.Properties",
843 - "GetAll",
844 - &error,
845 - &m,
846 - "s", "");
832 + r = sd_bus_call_method(
833 + bus, "org.freedesktop.systemd1", u->unit_path, "org.freedesktop.DBus.Properties", "GetAll", &error, &m, "s", "");
834 if (r < 0) {
835 log_dbus_error(r, "sd_bus_call_method(p1)");
836 return r;
@@ -879,24 +866,24 @@ static int systemd_unit_get_all_properties(sd_bus *bus, UnitInfo *u) {
866 systemd_unit_get_property(m, u, member);
867
868 r = sd_bus_message_exit_container(m);
882 - if(r < 0) {
869 + if (r < 0) {
870 log_dbus_error(r, "sd_bus_message_exit_container(p6)");
871 return r;
872 }
873
874 r = sd_bus_message_exit_container(m);
888 - if(r < 0) {
875 + if (r < 0) {
876 log_dbus_error(r, "sd_bus_message_exit_container(p7)");
877 return r;
878 }
879 }
893 - if(r < 0) {
880 + if (r < 0) {
881 log_dbus_error(r, "sd_bus_message_enter_container(p8)");
882 return r;
883 }
884
885 r = sd_bus_message_exit_container(m);
899 - if(r < 0) {
886 + if (r < 0) {
887 log_dbus_error(r, "sd_bus_message_exit_container(p9)");
888 return r;
889 }
@@ -904,41 +891,41 @@ static int systemd_unit_get_all_properties(sd_bus *bus, UnitInfo *u) {
891 return 0;
892 }
893
907 -static void systemd_units_get_all_properties(sd_bus *bus, UnitInfo *base) {
908 - for(UnitInfo *u = base ; u ;u = u->next)
894 +static void systemd_units_get_all_properties(sd_bus *bus, UnitInfo *base)
895 +{
896 + for (UnitInfo *u = base; u; u = u->next)
897 systemd_unit_get_all_properties(bus, u);
898 }
899
912 -
913 -
900 // ----------------------------------------------------------------------------
901 // main unit info
902
917 -static int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
903 +static int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u)
904 +{
905 assert(message);
906 assert(u);
907
908 u->type = NULL;
909
910 int r = sd_bus_message_read(
924 - message,
925 - SYSTEMD_UNITS_DBUS_TYPES,
926 - &u->id,
927 - &u->description,
928 - &u->load_state,
929 - &u->active_state,
930 - &u->sub_state,
931 - &u->following,
932 - &u->unit_path,
933 - &u->job_id,
934 - &u->job_type,
935 - &u->job_path);
936 -
937 - if(r <= 0)
911 + message,
912 + ND_SD_UNITS_DBUS_TYPES,
913 + &u->id,
914 + &u->description,
915 + &u->load_state,
916 + &u->active_state,
917 + &u->sub_state,
918 + &u->following,
919 + &u->unit_path,
920 + &u->job_id,
921 + &u->job_type,
922 + &u->job_path);
923 +
924 + if (r <= 0)
925 return r;
926
927 char *dot;
941 - if(u->id && (dot = strrchr(u->id, '.')) != NULL)
928 + if (u->id && (dot = strrchr(u->id, '.')) != NULL)
929 u->type = &dot[1];
930 else
931 u->type = "unknown";
@@ -947,7 +934,7 @@ static int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
934 u->UnitLoadState = unit_load_state_from_string(u->load_state);
935 u->UnitActiveState = unit_active_state_from_string(u->active_state);
936
950 - switch(u->UnitType) {
937 + switch (u->UnitType) {
938 case UNIT_SERVICE:
939 u->ServiceState = service_state_from_string(u->sub_state);
940 break;
@@ -999,35 +986,40 @@ static int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
986 return r;
987 }
988
1002 -static int hex_to_int(char c) {
1003 - if (c >= '0' && c <= '9') return c - '0';
1004 - if (c >= 'a' && c <= 'f') return c - 'a' + 10;
1005 - if (c >= 'A' && c <= 'F') return c - 'A' + 10;
989 +static int hex_to_int(char c)
990 +{
991 + if (c >= '0' && c <= '9')
992 + return c - '0';
993 + if (c >= 'a' && c <= 'f')
994 + return c - 'a' + 10;
995 + if (c >= 'A' && c <= 'F')
996 + return c - 'A' + 10;
997 return 0;
998 }
999
1000 // un-escape hex sequences (\xNN) in id
1010 -static void txt_decode(char *txt) {
1011 - if(!txt || !*txt)
1001 +static void txt_decode(char *txt)
1002 +{
1003 + if (!txt || !*txt)
1004 return;
1005
1006 char *src = txt, *dst = txt;
1007
1008 size_t id_len = strlen(src);
1009 size_t s = 0, d = 0;
1018 - for(; s < id_len ; s++) {
1019 - if(src[s] == '\\' && src[s + 1] == 'x' && isxdigit(src[s + 2]) && isxdigit(src[s + 3])) {
1010 + for (; s < id_len; s++) {
1011 + if (src[s] == '\\' && src[s + 1] == 'x' && isxdigit(src[s + 2]) && isxdigit(src[s + 3])) {
1012 int value = (hex_to_int(src[s + 2]) << 4) + hex_to_int(src[s + 3]);
1013 dst[d++] = (char)value;
1014 s += 3;
1023 - }
1024 - else
1015 + } else
1016 dst[d++] = src[s];
1017 }
1018 dst[d] = '\0';
1019 }
1020
1030 -static UnitInfo *systemd_units_get_all(void) {
1021 +static UnitInfo *systemd_units_get_all(void)
1022 +{
1023 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
1024 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1025 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
@@ -1043,20 +1035,21 @@ static UnitInfo *systemd_units_get_all(void) {
1035
1036 // This calls the ListUnits method of the org.freedesktop.systemd1.Manager interface
1037 // Replace "ListUnits" with "ListUnitsFiltered" to get specific units based on filters
1046 - r = sd_bus_call_method(bus,
1047 - "org.freedesktop.systemd1", /* service to contact */
1048 - "/org/freedesktop/systemd1", /* object path */
1049 - "org.freedesktop.systemd1.Manager", /* interface name */
1050 - "ListUnits", /* method name */
1051 - &error, /* object to return error in */
1052 - &reply, /* return message on success */
1053 - NULL); /* input signature */
1038 + r = sd_bus_call_method(
1039 + bus,
1040 + "org.freedesktop.systemd1", /* service to contact */
1041 + "/org/freedesktop/systemd1", /* object path */
1042 + "org.freedesktop.systemd1.Manager", /* interface name */
1043 + "ListUnits", /* method name */
1044 + &error, /* object to return error in */
1045 + &reply, /* return message on success */
1046 + NULL); /* input signature */
1047 if (r < 0) {
1048 log_dbus_error(r, "sd_bus_call_method()");
1049 return base;
1050 }
1051
1059 - r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, SYSTEMD_UNITS_DBUS_TYPES);
1052 + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, ND_SD_UNITS_DBUS_TYPES);
1053 if (r < 0) {
1054 log_dbus_error(r, "sd_bus_message_enter_container()");
1055 return base;
@@ -1103,8 +1096,9 @@ static UnitInfo *systemd_units_get_all(void) {
1096 return base;
1097 }
1098
1106 -static void systemd_units_free_all(UnitInfo *base) {
1107 - while(base) {
1099 +static void systemd_units_free_all(UnitInfo *base)
1100 +{
1101 + while (base) {
1102 UnitInfo *u = base;
1103 DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(base, u, prev, next);
1104 freez((void *)u->id);
@@ -1118,7 +1112,7 @@ static void systemd_units_free_all(UnitInfo *base) {
1112 freez((void *)u->job_type);
1113 freez((void *)u->job_path);
1114
1121 - for(int i = 0; i < (ssize_t)_UNIT_ATTRIBUTE_MAX ;i++)
1115 + for (int i = 0; i < (ssize_t)_UNIT_ATTRIBUTE_MAX; i++)
1116 systemd_unit_free_property(unit_attributes[i].value_type, &u->attributes[i]);
1117
1118 freez(u);
@@ -1127,28 +1121,29 @@ static void systemd_units_free_all(UnitInfo *base) {
1121
1122 // ----------------------------------------------------------------------------
1123
1130 -static void netdata_systemd_units_function_help(const char *transaction) {
1124 +static void netdata_systemd_units_function_help(const char *transaction)
1125 +{
1126 BUFFER *wb = buffer_create(0, NULL);
1132 - buffer_sprintf(wb,
1133 - "%s / %s\n"
1134 - "\n"
1135 - "%s\n"
1136 - "\n"
1137 - "The following parameters are supported:\n"
1138 - "\n"
1139 - " help\n"
1140 - " Shows this help message.\n"
1141 - "\n"
1142 - " info\n"
1143 - " Request initial configuration information about the plugin.\n"
1144 - " The key entity returned is the required_params array, which includes\n"
1145 - " all the available systemd journal sources.\n"
1146 - " When `info` is requested, all other parameters are ignored.\n"
1147 - "\n"
1148 - , program_name
1149 - , SYSTEMD_UNITS_FUNCTION_NAME
1150 - , SYSTEMD_UNITS_FUNCTION_DESCRIPTION
1151 - );
1127 + buffer_sprintf(
1128 + wb,
1129 + "%s / %s\n"
1130 + "\n"
1131 + "%s\n"
1132 + "\n"
1133 + "The following parameters are supported:\n"
1134 + "\n"
1135 + " help\n"
1136 + " Shows this help message.\n"
1137 + "\n"
1138 + " info\n"
1139 + " Request initial configuration information about the plugin.\n"
1140 + " The key entity returned is the required_params array, which includes\n"
1141 + " all the available systemd journal sources.\n"
1142 + " When `info` is requested, all other parameters are ignored.\n"
1143 + "\n",
1144 + program_name,
1145 + ND_SD_UNITS_FUNCTION_NAME,
1146 + ND_SD_UNITS_FUNCTION_DESCRIPTION);
1147
1148 netdata_mutex_lock(&stdout_mutex);
1149 wb->response_code = HTTP_RESP_OK;
@@ -1160,13 +1155,14 @@ static void netdata_systemd_units_function_help(const char *transaction) {
1155 buffer_free(wb);
1156 }
1157
1163 -static void netdata_systemd_units_function_info(const char *transaction) {
1158 +static void netdata_systemd_units_function_info(const char *transaction)
1159 +{
1160 BUFFER *wb = buffer_create(0, NULL);
1161 buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_MINIFY);
1162
1163 buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
1164 buffer_json_member_add_string(wb, "type", "table");
1169 - buffer_json_member_add_string(wb, "help", SYSTEMD_UNITS_FUNCTION_DESCRIPTION);
1165 + buffer_json_member_add_string(wb, "help", ND_SD_UNITS_FUNCTION_DESCRIPTION);
1166
1167 buffer_json_finalize(wb);
1168 netdata_mutex_lock(&stdout_mutex);
@@ -1181,10 +1177,11 @@ static void netdata_systemd_units_function_info(const char *transaction) {
1177
1178 // ----------------------------------------------------------------------------
1179
1184 -static void systemd_unit_priority(UnitInfo *u, size_t units) {
1180 +static void systemd_unit_priority(UnitInfo *u, size_t units)
1181 +{
1182 uint32_t prio;
1183
1187 - switch(u->severity) {
1184 + switch (u->severity) {
1185 case FACET_ROW_SEVERITY_CRITICAL:
1186 prio = 0;
1187 break;
@@ -1211,24 +1208,28 @@ static void systemd_unit_priority(UnitInfo *u, size_t units) {
1208 u->prio = (prio * units) + u->prio;
1209 }
1210
1214 -static inline FACET_ROW_SEVERITY if_less(FACET_ROW_SEVERITY current, FACET_ROW_SEVERITY max, FACET_ROW_SEVERITY target) {
1211 +static inline FACET_ROW_SEVERITY if_less(FACET_ROW_SEVERITY current, FACET_ROW_SEVERITY max, FACET_ROW_SEVERITY target)
1212 +{
1213 FACET_ROW_SEVERITY wanted = current;
1216 - if(current < target)
1214 + if (current < target)
1215 wanted = target > max ? max : target;
1216 return wanted;
1217 }
1218
1221 -static inline FACET_ROW_SEVERITY if_normal(FACET_ROW_SEVERITY current, FACET_ROW_SEVERITY max, FACET_ROW_SEVERITY target) {
1219 +static inline FACET_ROW_SEVERITY
1220 +if_normal(FACET_ROW_SEVERITY current, FACET_ROW_SEVERITY max, FACET_ROW_SEVERITY target)
1221 +{
1222 FACET_ROW_SEVERITY wanted = current;
1223 - if(current == FACET_ROW_SEVERITY_NORMAL)
1223 + if (current == FACET_ROW_SEVERITY_NORMAL)
1224 wanted = target > max ? max : target;
1225 return wanted;
1226 }
1227
1228 -static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1228 +static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u)
1229 +{
1230 FACET_ROW_SEVERITY severity, max_severity;
1231
1231 - switch(u->UnitLoadState) {
1232 + switch (u->UnitLoadState) {
1233 case UNIT_ERROR:
1234 case UNIT_BAD_SETTING:
1235 severity = FACET_ROW_SEVERITY_CRITICAL;
@@ -1258,7 +1259,7 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1259 break;
1260 }
1261
1261 - switch(u->UnitActiveState) {
1262 + switch (u->UnitActiveState) {
1263 case UNIT_FAILED:
1264 severity = if_less(severity, max_severity, FACET_ROW_SEVERITY_CRITICAL);
1265 break;
@@ -1282,7 +1283,7 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1283 break;
1284 }
1285
1285 - switch(u->FreezerState) {
1286 + switch (u->FreezerState) {
1287 default:
1288 case FREEZER_FROZEN:
1289 case FREEZER_FREEZING:
@@ -1294,9 +1295,9 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1295 break;
1296 }
1297
1297 - switch(u->UnitType) {
1298 + switch (u->UnitType) {
1299 case UNIT_SERVICE:
1299 - switch(u->ServiceState) {
1300 + switch (u->ServiceState) {
1301 case SERVICE_FAILED:
1302 case SERVICE_FAILED_BEFORE_AUTO_RESTART:
1303 severity = if_less(severity, max_severity, FACET_ROW_SEVERITY_CRITICAL);
@@ -1340,7 +1341,7 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1341 break;
1342
1343 case UNIT_MOUNT:
1343 - switch(u->MountState) {
1344 + switch (u->MountState) {
1345 case MOUNT_FAILED:
1346 severity = if_less(severity, max_severity, FACET_ROW_SEVERITY_CRITICAL);
1347 break;
@@ -1371,7 +1372,7 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1372 break;
1373
1374 case UNIT_SWAP:
1374 - switch(u->SwapState) {
1375 + switch (u->SwapState) {
1376 case SWAP_FAILED:
1377 severity = if_less(severity, max_severity, FACET_ROW_SEVERITY_CRITICAL);
1378 break;
@@ -1399,7 +1400,7 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1400 break;
1401
1402 case UNIT_SOCKET:
1402 - switch(u->SocketState) {
1403 + switch (u->SocketState) {
1404 case SOCKET_FAILED:
1405 severity = if_less(severity, max_severity, FACET_ROW_SEVERITY_CRITICAL);
1406 break;
@@ -1431,7 +1432,7 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1432 break;
1433
1434 case UNIT_TARGET:
1434 - switch(u->TargetState) {
1435 + switch (u->TargetState) {
1436 default:
1437 severity = if_less(severity, max_severity, FACET_ROW_SEVERITY_WARNING);
1438 break;
@@ -1446,7 +1447,7 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1447 break;
1448
1449 case UNIT_DEVICE:
1449 - switch(u->DeviceState) {
1450 + switch (u->DeviceState) {
1451 default:
1452 severity = if_less(severity, max_severity, FACET_ROW_SEVERITY_WARNING);
1453 break;
@@ -1465,7 +1466,7 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1466 break;
1467
1468 case UNIT_AUTOMOUNT:
1468 - switch(u->AutomountState) {
1469 + switch (u->AutomountState) {
1470 case AUTOMOUNT_FAILED:
1471 severity = if_less(severity, max_severity, FACET_ROW_SEVERITY_CRITICAL);
1472 break;
@@ -1485,7 +1486,7 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1486 break;
1487
1488 case UNIT_TIMER:
1488 - switch(u->TimerState) {
1489 + switch (u->TimerState) {
1490 case TIMER_FAILED:
1491 severity = if_less(severity, max_severity, FACET_ROW_SEVERITY_CRITICAL);
1492 break;
@@ -1506,7 +1507,7 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1507 break;
1508
1509 case UNIT_PATH:
1509 - switch(u->PathState) {
1510 + switch (u->PathState) {
1511 case PATH_FAILED:
1512 severity = if_less(severity, max_severity, FACET_ROW_SEVERITY_CRITICAL);
1513 break;
@@ -1526,7 +1527,7 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1527 break;
1528
1529 case UNIT_SLICE:
1529 - switch(u->SliceState) {
1530 + switch (u->SliceState) {
1531 default:
1532 severity = if_less(severity, max_severity, FACET_ROW_SEVERITY_WARNING);
1533 break;
@@ -1541,7 +1542,7 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1542 break;
1543
1544 case UNIT_SCOPE:
1544 - switch(u->ScopeState) {
1545 + switch (u->ScopeState) {
1546 case SCOPE_FAILED:
1547 severity = if_less(severity, max_severity, FACET_ROW_SEVERITY_CRITICAL);
1548 break;
@@ -1575,46 +1576,54 @@ static FACET_ROW_SEVERITY system_unit_severity(UnitInfo *u) {
1576 return severity;
1577 }
1578
1578 -static int unit_info_compar(const void *a, const void *b) {
1579 +static int unit_info_compar(const void *a, const void *b)
1580 +{
1581 UnitInfo *u1 = *((UnitInfo **)a);
1582 UnitInfo *u2 = *((UnitInfo **)b);
1583
1584 return strcasecmp(u1->id, u2->id);
1585 }
1586
1585 -static void systemd_units_assign_priority(UnitInfo *base) {
1587 +static void systemd_units_assign_priority(UnitInfo *base)
1588 +{
1589 size_t units = 0, c = 0, prio = 0;
1587 - for(UnitInfo *u = base; u ; u = u->next)
1590 + for (UnitInfo *u = base; u; u = u->next)
1591 units++;
1592
1593 UnitInfo *array[units];
1591 - for(UnitInfo *u = base; u ; u = u->next)
1594 + for (UnitInfo *u = base; u; u = u->next)
1595 array[c++] = u;
1596
1597 qsort(array, units, sizeof(UnitInfo *), unit_info_compar);
1598
1596 - for(c = 0; c < units ; c++) {
1599 + for (c = 0; c < units; c++) {
1600 array[c]->prio = prio++;
1601 system_unit_severity(array[c]);
1602 systemd_unit_priority(array[c], units);
1603 }
1604 }
1605
1603 -void function_systemd_units(const char *transaction, char *function,
1604 - usec_t *stop_monotonic_ut __maybe_unused, bool *cancelled __maybe_unused,
1605 - BUFFER *payload __maybe_unused, HTTP_ACCESS access __maybe_unused,
1606 - const char *source __maybe_unused, void *data __maybe_unused) {
1607 - char *words[SYSTEMD_UNITS_MAX_PARAMS] = { NULL };
1608 - size_t num_words = quoted_strings_splitter_whitespace(function, words, SYSTEMD_UNITS_MAX_PARAMS);
1609 - for(int i = 1; i < SYSTEMD_UNITS_MAX_PARAMS ;i++) {
1606 +void function_systemd_units(
1607 + const char *transaction,
1608 + char *function,
1609 + usec_t *stop_monotonic_ut __maybe_unused,
1610 + bool *cancelled __maybe_unused,
1611 + BUFFER *payload __maybe_unused,
1612 + HTTP_ACCESS access __maybe_unused,
1613 + const char *source __maybe_unused,
1614 + void *data __maybe_unused)
1615 +{
1616 + char *words[ND_SD_UNITS_MAX_PARAMS] = {NULL};
1617 + size_t num_words = quoted_strings_splitter_whitespace(function, words, ND_SD_UNITS_MAX_PARAMS);
1618 + for (int i = 1; i < ND_SD_UNITS_MAX_PARAMS; i++) {
1619 char *keyword = get_word(words, num_words, i);
1611 - if(!keyword) break;
1620 + if (!keyword)
1621 + break;
1622
1613 - if(strcmp(keyword, "info") == 0) {
1623 + if (strcmp(keyword, "info") == 0) {
1624 netdata_systemd_units_function_info(transaction);
1625 return;
1616 - }
1617 - else if(strcmp(keyword, "help") == 0) {
1626 + } else if (strcmp(keyword, "help") == 0) {
1627 netdata_systemd_units_function_help(transaction);
1628 return;
1629 }
@@ -1629,13 +1638,13 @@ void function_systemd_units(const char *transaction, char *function,
1638 buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
1639 buffer_json_member_add_string(wb, "type", "table");
1640 buffer_json_member_add_time_t(wb, "update_every", 10);
1632 - buffer_json_member_add_string(wb, "help", SYSTEMD_UNITS_FUNCTION_DESCRIPTION);
1641 + buffer_json_member_add_string(wb, "help", ND_SD_UNITS_FUNCTION_DESCRIPTION);
1642 buffer_json_member_add_array(wb, "data");
1643
1635 - size_t count[_UNIT_ATTRIBUTE_MAX] = { 0 };
1644 + size_t count[_UNIT_ATTRIBUTE_MAX] = {0};
1645 struct UnitAttribute max[_UNIT_ATTRIBUTE_MAX];
1646
1638 - for(UnitInfo *u = base; u ;u = u->next) {
1647 + for (UnitInfo *u = base; u; u = u->next) {
1648 buffer_json_add_array_item_array(wb);
1649 {
1650 buffer_json_add_array_item_string(wb, u->id);
@@ -1657,40 +1666,46 @@ void function_systemd_units(const char *transaction, char *function,
1666 buffer_json_add_array_item_string(wb, u->job_type);
1667 buffer_json_add_array_item_string(wb, u->job_path);
1668
1660 - for(ssize_t i = 0; i < (ssize_t)_UNIT_ATTRIBUTE_MAX ;i++) {
1661 - switch(unit_attributes[i].value_type) {
1669 + for (ssize_t i = 0; i < (ssize_t)_UNIT_ATTRIBUTE_MAX; i++) {
1670 + switch (unit_attributes[i].value_type) {
1671 case SD_BUS_TYPE_OBJECT_PATH:
1672 case SD_BUS_TYPE_STRING:
1664 - buffer_json_add_array_item_string(wb, u->attributes[i].str && *u->attributes[i].str ? u->attributes[i].str : "-");
1673 + buffer_json_add_array_item_string(
1674 + wb, u->attributes[i].str && *u->attributes[i].str ? u->attributes[i].str : "-");
1675 break;
1676
1677 case SD_BUS_TYPE_UINT64:
1678 buffer_json_add_array_item_uint64(wb, u->attributes[i].uint64);
1669 - if(!count[i]++) max[i].uint64 = 0;
1679 + if (!count[i]++)
1680 + max[i].uint64 = 0;
1681 max[i].uint64 = MAX(max[i].uint64, u->attributes[i].uint64);
1682 break;
1683
1684 case SD_BUS_TYPE_UINT32:
1685 buffer_json_add_array_item_uint64(wb, u->attributes[i].uint32);
1675 - if(!count[i]++) max[i].uint32 = 0;
1686 + if (!count[i]++)
1687 + max[i].uint32 = 0;
1688 max[i].uint32 = MAX(max[i].uint32, u->attributes[i].uint32);
1689 break;
1690
1691 case SD_BUS_TYPE_INT64:
1692 buffer_json_add_array_item_uint64(wb, u->attributes[i].int64);
1681 - if(!count[i]++) max[i].uint64 = 0;
1693 + if (!count[i]++)
1694 + max[i].uint64 = 0;
1695 max[i].int64 = MAX(max[i].int64, u->attributes[i].int64);
1696 break;
1697
1698 case SD_BUS_TYPE_INT32:
1699 buffer_json_add_array_item_uint64(wb, u->attributes[i].int32);
1687 - if(!count[i]++) max[i].int32 = 0;
1700 + if (!count[i]++)
1701 + max[i].int32 = 0;
1702 max[i].int32 = MAX(max[i].int32, u->attributes[i].int32);
1703 break;
1704
1705 case SD_BUS_TYPE_DOUBLE:
1706 buffer_json_add_array_item_double(wb, u->attributes[i].dbl);
1693 - if(!count[i]++) max[i].dbl = 0.0;
1707 + if (!count[i]++)
1708 + max[i].dbl = 0.0;
1709 max[i].dbl = MAX(max[i].dbl, u->attributes[i].dbl);
1710 break;
1711
@@ -1715,105 +1730,231 @@ void function_systemd_units(const char *transaction, char *function,
1730 {
1731 size_t field_id = 0;
1732
1718 - buffer_rrdf_table_add_field(wb, field_id++, "id", "Unit ID",
1719 - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1720 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1721 - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
1722 - RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_UNIQUE_KEY | RRDF_FIELD_OPTS_WRAP | RRDF_FIELD_OPTS_FULL_WIDTH,
1723 - NULL);
1733 + buffer_rrdf_table_add_field(
1734 + wb,
1735 + field_id++,
1736 + "id",
1737 + "Unit ID",
1738 + RRDF_FIELD_TYPE_STRING,
1739 + RRDF_FIELD_VISUAL_VALUE,
1740 + RRDF_FIELD_TRANSFORM_NONE,
1741 + 0,
1742 + NULL,
1743 + NAN,
1744 + RRDF_FIELD_SORT_ASCENDING,
1745 + NULL,
1746 + RRDF_FIELD_SUMMARY_COUNT,
1747 + RRDF_FIELD_FILTER_NONE,
1748 + RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_UNIQUE_KEY | RRDF_FIELD_OPTS_WRAP | RRDF_FIELD_OPTS_FULL_WIDTH,
1749 + NULL);
1750 +
1751 + buffer_rrdf_table_add_field(
1752 + wb,
1753 + field_id++,
1754 + "rowOptions",
1755 + "rowOptions",
1756 + RRDF_FIELD_TYPE_NONE,
1757 + RRDR_FIELD_VISUAL_ROW_OPTIONS,
1758 + RRDF_FIELD_TRANSFORM_NONE,
1759 + 0,
1760 + NULL,
1761 + NAN,
1762 + RRDF_FIELD_SORT_FIXED,
1763 + NULL,
1764 + RRDF_FIELD_SUMMARY_COUNT,
1765 + RRDF_FIELD_FILTER_NONE,
1766 + RRDF_FIELD_OPTS_DUMMY,
1767 + NULL);
1768
1769 buffer_rrdf_table_add_field(
1726 - wb, field_id++,
1727 - "rowOptions", "rowOptions",
1728 - RRDF_FIELD_TYPE_NONE,
1729 - RRDR_FIELD_VISUAL_ROW_OPTIONS,
1730 - RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
1731 - RRDF_FIELD_SORT_FIXED,
1732 - NULL,
1733 - RRDF_FIELD_SUMMARY_COUNT,
1734 - RRDF_FIELD_FILTER_NONE,
1735 - RRDF_FIELD_OPTS_DUMMY,
1736 - NULL);
1737 -
1738 - buffer_rrdf_table_add_field(wb, field_id++, "type", "Unit Type",
1739 - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1740 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1741 - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
1742 - RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_EXPANDED_FILTER,
1743 - NULL);
1744 -
1745 - buffer_rrdf_table_add_field(wb, field_id++, "description", "Unit Description",
1746 - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1747 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1748 - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
1749 - RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_WRAP | RRDF_FIELD_OPTS_FULL_WIDTH,
1750 - NULL);
1751 -
1752 - buffer_rrdf_table_add_field(wb, field_id++, "loadState", "Unit Load State",
1753 - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1754 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1755 - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
1756 - RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_EXPANDED_FILTER,
1757 - NULL);
1758 -
1759 - buffer_rrdf_table_add_field(wb, field_id++, "activeState", "Unit Active State",
1760 - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1761 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1762 - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
1763 - RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_EXPANDED_FILTER,
1764 - NULL);
1765 -
1766 - buffer_rrdf_table_add_field(wb, field_id++, "subState", "Unit Sub State",
1767 - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1768 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1769 - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
1770 - RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_EXPANDED_FILTER,
1771 - NULL);
1772 -
1773 - buffer_rrdf_table_add_field(wb, field_id++, "following", "Unit Following",
1774 - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1775 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1776 - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
1777 - RRDF_FIELD_OPTS_WRAP,
1778 - NULL);
1779 -
1780 - buffer_rrdf_table_add_field(wb, field_id++, "path", "Unit Path",
1781 - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1782 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1783 - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
1784 - RRDF_FIELD_OPTS_WRAP | RRDF_FIELD_OPTS_FULL_WIDTH,
1785 - NULL);
1786 -
1787 - buffer_rrdf_table_add_field(wb, field_id++, "jobId", "Unit Job ID",
1788 - RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1789 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1790 - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
1791 - RRDF_FIELD_OPTS_NONE,
1792 - NULL);
1793 -
1794 - buffer_rrdf_table_add_field(wb, field_id++, "jobType", "Unit Job Type",
1795 - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1796 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1797 - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
1798 - RRDF_FIELD_OPTS_NONE,
1799 - NULL);
1800 -
1801 - buffer_rrdf_table_add_field(wb, field_id++, "jobPath", "Unit Job Path",
1802 - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1803 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1804 - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
1805 - RRDF_FIELD_OPTS_WRAP | RRDF_FIELD_OPTS_FULL_WIDTH,
1806 - NULL);
1807 -
1808 - for(ssize_t i = 0; i < (ssize_t)_UNIT_ATTRIBUTE_MAX ;i++) {
1770 + wb,
1771 + field_id++,
1772 + "type",
1773 + "Unit Type",
1774 + RRDF_FIELD_TYPE_STRING,
1775 + RRDF_FIELD_VISUAL_VALUE,
1776 + RRDF_FIELD_TRANSFORM_NONE,
1777 + 0,
1778 + NULL,
1779 + NAN,
1780 + RRDF_FIELD_SORT_ASCENDING,
1781 + NULL,
1782 + RRDF_FIELD_SUMMARY_COUNT,
1783 + RRDF_FIELD_FILTER_MULTISELECT,
1784 + RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_EXPANDED_FILTER,
1785 + NULL);
1786 +
1787 + buffer_rrdf_table_add_field(
1788 + wb,
1789 + field_id++,
1790 + "description",
1791 + "Unit Description",
1792 + RRDF_FIELD_TYPE_STRING,
1793 + RRDF_FIELD_VISUAL_VALUE,
1794 + RRDF_FIELD_TRANSFORM_NONE,
1795 + 0,
1796 + NULL,
1797 + NAN,
1798 + RRDF_FIELD_SORT_ASCENDING,
1799 + NULL,
1800 + RRDF_FIELD_SUMMARY_COUNT,
1801 + RRDF_FIELD_FILTER_NONE,
1802 + RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_WRAP | RRDF_FIELD_OPTS_FULL_WIDTH,
1803 + NULL);
1804 +
1805 + buffer_rrdf_table_add_field(
1806 + wb,
1807 + field_id++,
1808 + "loadState",
1809 + "Unit Load State",
1810 + RRDF_FIELD_TYPE_STRING,
1811 + RRDF_FIELD_VISUAL_VALUE,
1812 + RRDF_FIELD_TRANSFORM_NONE,
1813 + 0,
1814 + NULL,
1815 + NAN,
1816 + RRDF_FIELD_SORT_ASCENDING,
1817 + NULL,
1818 + RRDF_FIELD_SUMMARY_COUNT,
1819 + RRDF_FIELD_FILTER_MULTISELECT,
1820 + RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_EXPANDED_FILTER,
1821 + NULL);
1822 +
1823 + buffer_rrdf_table_add_field(
1824 + wb,
1825 + field_id++,
1826 + "activeState",
1827 + "Unit Active State",
1828 + RRDF_FIELD_TYPE_STRING,
1829 + RRDF_FIELD_VISUAL_VALUE,
1830 + RRDF_FIELD_TRANSFORM_NONE,
1831 + 0,
1832 + NULL,
1833 + NAN,
1834 + RRDF_FIELD_SORT_ASCENDING,
1835 + NULL,
1836 + RRDF_FIELD_SUMMARY_COUNT,
1837 + RRDF_FIELD_FILTER_MULTISELECT,
1838 + RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_EXPANDED_FILTER,
1839 + NULL);
1840 +
1841 + buffer_rrdf_table_add_field(
1842 + wb,
1843 + field_id++,
1844 + "subState",
1845 + "Unit Sub State",
1846 + RRDF_FIELD_TYPE_STRING,
1847 + RRDF_FIELD_VISUAL_VALUE,
1848 + RRDF_FIELD_TRANSFORM_NONE,
1849 + 0,
1850 + NULL,
1851 + NAN,
1852 + RRDF_FIELD_SORT_ASCENDING,
1853 + NULL,
1854 + RRDF_FIELD_SUMMARY_COUNT,
1855 + RRDF_FIELD_FILTER_MULTISELECT,
1856 + RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_EXPANDED_FILTER,
1857 + NULL);
1858 +
1859 + buffer_rrdf_table_add_field(
1860 + wb,
1861 + field_id++,
1862 + "following",
1863 + "Unit Following",
1864 + RRDF_FIELD_TYPE_STRING,
1865 + RRDF_FIELD_VISUAL_VALUE,
1866 + RRDF_FIELD_TRANSFORM_NONE,
1867 + 0,
1868 + NULL,
1869 + NAN,
1870 + RRDF_FIELD_SORT_ASCENDING,
1871 + NULL,
1872 + RRDF_FIELD_SUMMARY_COUNT,
1873 + RRDF_FIELD_FILTER_NONE,
1874 + RRDF_FIELD_OPTS_WRAP,
1875 + NULL);
1876 +
1877 + buffer_rrdf_table_add_field(
1878 + wb,
1879 + field_id++,
1880 + "path",
1881 + "Unit Path",
1882 + RRDF_FIELD_TYPE_STRING,
1883 + RRDF_FIELD_VISUAL_VALUE,
1884 + RRDF_FIELD_TRANSFORM_NONE,
1885 + 0,
1886 + NULL,
1887 + NAN,
1888 + RRDF_FIELD_SORT_ASCENDING,
1889 + NULL,
1890 + RRDF_FIELD_SUMMARY_COUNT,
1891 + RRDF_FIELD_FILTER_NONE,
1892 + RRDF_FIELD_OPTS_WRAP | RRDF_FIELD_OPTS_FULL_WIDTH,
1893 + NULL);
1894 +
1895 + buffer_rrdf_table_add_field(
1896 + wb,
1897 + field_id++,
1898 + "jobId",
1899 + "Unit Job ID",
1900 + RRDF_FIELD_TYPE_INTEGER,
1901 + RRDF_FIELD_VISUAL_VALUE,
1902 + RRDF_FIELD_TRANSFORM_NONE,
1903 + 0,
1904 + NULL,
1905 + NAN,
1906 + RRDF_FIELD_SORT_ASCENDING,
1907 + NULL,
1908 + RRDF_FIELD_SUMMARY_COUNT,
1909 + RRDF_FIELD_FILTER_NONE,
1910 + RRDF_FIELD_OPTS_NONE,
1911 + NULL);
1912 +
1913 + buffer_rrdf_table_add_field(
1914 + wb,
1915 + field_id++,
1916 + "jobType",
1917 + "Unit Job Type",
1918 + RRDF_FIELD_TYPE_STRING,
1919 + RRDF_FIELD_VISUAL_VALUE,
1920 + RRDF_FIELD_TRANSFORM_NONE,
1921 + 0,
1922 + NULL,
1923 + NAN,
1924 + RRDF_FIELD_SORT_ASCENDING,
1925 + NULL,
1926 + RRDF_FIELD_SUMMARY_COUNT,
1927 + RRDF_FIELD_FILTER_MULTISELECT,
1928 + RRDF_FIELD_OPTS_NONE,
1929 + NULL);
1930 +
1931 + buffer_rrdf_table_add_field(
1932 + wb,
1933 + field_id++,
1934 + "jobPath",
1935 + "Unit Job Path",
1936 + RRDF_FIELD_TYPE_STRING,
1937 + RRDF_FIELD_VISUAL_VALUE,
1938 + RRDF_FIELD_TRANSFORM_NONE,
1939 + 0,
1940 + NULL,
1941 + NAN,
1942 + RRDF_FIELD_SORT_ASCENDING,
1943 + NULL,
1944 + RRDF_FIELD_SUMMARY_COUNT,
1945 + RRDF_FIELD_FILTER_NONE,
1946 + RRDF_FIELD_OPTS_WRAP | RRDF_FIELD_OPTS_FULL_WIDTH,
1947 + NULL);
1948 +
1949 + for (ssize_t i = 0; i < (ssize_t)_UNIT_ATTRIBUTE_MAX; i++) {
1950 char key[256], name[256];
1951
1811 - if(unit_attributes[i].show_as)
1952 + if (unit_attributes[i].show_as)
1953 snprintfz(key, sizeof(key), "%s", unit_attributes[i].show_as);
1954 else
1955 snprintfz(key, sizeof(key), "attribute%s", unit_property_name_to_string_from_slot(i));
1956
1816 - if(unit_attributes[i].info)
1957 + if (unit_attributes[i].info)
1958 snprintfz(name, sizeof(name), "%s", unit_attributes[i].info);
1959 else
1960 snprintfz(name, sizeof(name), "Attribute %s", unit_property_name_to_string_from_slot(i));
@@ -1821,15 +1962,26 @@ void function_systemd_units(const char *transaction, char *function,
1962 RRDF_FIELD_OPTIONS options = unit_attributes[i].options;
1963 RRDF_FIELD_FILTER filter = unit_attributes[i].filter;
1964
1824 - switch(unit_attributes[i].value_type) {
1965 + switch (unit_attributes[i].value_type) {
1966 case SD_BUS_TYPE_OBJECT_PATH:
1967 case SD_BUS_TYPE_STRING:
1827 - buffer_rrdf_table_add_field(wb, field_id++, key, name,
1828 - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1829 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1830 - RRDF_FIELD_SUMMARY_COUNT, filter,
1831 - RRDF_FIELD_OPTS_WRAP | options,
1832 - NULL);
1968 + buffer_rrdf_table_add_field(
1969 + wb,
1970 + field_id++,
1971 + key,
1972 + name,
1973 + RRDF_FIELD_TYPE_STRING,
1974 + RRDF_FIELD_VISUAL_VALUE,
1975 + RRDF_FIELD_TRANSFORM_NONE,
1976 + 0,
1977 + NULL,
1978 + NAN,
1979 + RRDF_FIELD_SORT_ASCENDING,
1980 + NULL,
1981 + RRDF_FIELD_SUMMARY_COUNT,
1982 + filter,
1983 + RRDF_FIELD_OPTS_WRAP | options,
1984 + NULL);
1985 break;
1986
1987 case SD_BUS_TYPE_INT32:
@@ -1837,61 +1989,114 @@ void function_systemd_units(const char *transaction, char *function,
1989 case SD_BUS_TYPE_INT64:
1990 case SD_BUS_TYPE_UINT64: {
1991 double m = 0.0;
1840 - if(unit_attributes[i].value_type == SD_BUS_TYPE_UINT64)
1992 + if (unit_attributes[i].value_type == SD_BUS_TYPE_UINT64)
1993 m = (double)max[i].uint64;
1842 - else if(unit_attributes[i].value_type == SD_BUS_TYPE_INT64)
1994 + else if (unit_attributes[i].value_type == SD_BUS_TYPE_INT64)
1995 m = (double)max[i].int64;
1844 - else if(unit_attributes[i].value_type == SD_BUS_TYPE_UINT32)
1996 + else if (unit_attributes[i].value_type == SD_BUS_TYPE_UINT32)
1997 m = (double)max[i].uint32;
1846 - else if(unit_attributes[i].value_type == SD_BUS_TYPE_INT32)
1998 + else if (unit_attributes[i].value_type == SD_BUS_TYPE_INT32)
1999 m = (double)max[i].int32;
2000
1849 - buffer_rrdf_table_add_field(wb, field_id++, key, name,
1850 - RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1851 - 0, NULL, m, RRDF_FIELD_SORT_ASCENDING, NULL,
1852 - RRDF_FIELD_SUMMARY_SUM, filter,
1853 - RRDF_FIELD_OPTS_WRAP | options,
1854 - NULL);
1855 - }
1856 - break;
2001 + buffer_rrdf_table_add_field(
2002 + wb,
2003 + field_id++,
2004 + key,
2005 + name,
2006 + RRDF_FIELD_TYPE_INTEGER,
2007 + RRDF_FIELD_VISUAL_VALUE,
2008 + RRDF_FIELD_TRANSFORM_NONE,
2009 + 0,
2010 + NULL,
2011 + m,
2012 + RRDF_FIELD_SORT_ASCENDING,
2013 + NULL,
2014 + RRDF_FIELD_SUMMARY_SUM,
2015 + filter,
2016 + RRDF_FIELD_OPTS_WRAP | options,
2017 + NULL);
2018 + } break;
2019
2020 case SD_BUS_TYPE_DOUBLE:
1859 - buffer_rrdf_table_add_field(wb, field_id++, key, name,
1860 - RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1861 - 2, NULL, max[i].dbl, RRDF_FIELD_SORT_ASCENDING, NULL,
1862 - RRDF_FIELD_SUMMARY_SUM, filter,
1863 - RRDF_FIELD_OPTS_WRAP | options,
1864 - NULL);
2021 + buffer_rrdf_table_add_field(
2022 + wb,
2023 + field_id++,
2024 + key,
2025 + name,
2026 + RRDF_FIELD_TYPE_INTEGER,
2027 + RRDF_FIELD_VISUAL_VALUE,
2028 + RRDF_FIELD_TRANSFORM_NONE,
2029 + 2,
2030 + NULL,
2031 + max[i].dbl,
2032 + RRDF_FIELD_SORT_ASCENDING,
2033 + NULL,
2034 + RRDF_FIELD_SUMMARY_SUM,
2035 + filter,
2036 + RRDF_FIELD_OPTS_WRAP | options,
2037 + NULL);
2038 break;
2039
2040 case SD_BUS_TYPE_BOOLEAN:
1868 - buffer_rrdf_table_add_field(wb, field_id++, key, name,
1869 - RRDF_FIELD_TYPE_BOOLEAN, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1870 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1871 - RRDF_FIELD_SUMMARY_COUNT, filter,
1872 - RRDF_FIELD_OPTS_WRAP | options,
1873 - NULL);
2041 + buffer_rrdf_table_add_field(
2042 + wb,
2043 + field_id++,
2044 + key,
2045 + name,
2046 + RRDF_FIELD_TYPE_BOOLEAN,
2047 + RRDF_FIELD_VISUAL_VALUE,
2048 + RRDF_FIELD_TRANSFORM_NONE,
2049 + 0,
2050 + NULL,
2051 + NAN,
2052 + RRDF_FIELD_SORT_ASCENDING,
2053 + NULL,
2054 + RRDF_FIELD_SUMMARY_COUNT,
2055 + filter,
2056 + RRDF_FIELD_OPTS_WRAP | options,
2057 + NULL);
2058 break;
2059
2060 default:
2061 break;
2062 }
1879 -
2063 }
2064
1882 - buffer_rrdf_table_add_field(wb, field_id++, "priority", "Priority",
1883 - RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1884 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1885 - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
1886 - RRDF_FIELD_OPTS_NONE,
1887 - NULL);
1888 -
1889 - buffer_rrdf_table_add_field(wb, field_id++, "count", "Count",
1890 - RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
1891 - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
1892 - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
1893 - RRDF_FIELD_OPTS_NONE,
1894 - NULL);
2065 + buffer_rrdf_table_add_field(
2066 + wb,
2067 + field_id++,
2068 + "priority",
2069 + "Priority",
2070 + RRDF_FIELD_TYPE_INTEGER,
2071 + RRDF_FIELD_VISUAL_VALUE,
2072 + RRDF_FIELD_TRANSFORM_NONE,
2073 + 0,
2074 + NULL,
2075 + NAN,
2076 + RRDF_FIELD_SORT_ASCENDING,
2077 + NULL,
2078 + RRDF_FIELD_SUMMARY_COUNT,
2079 + RRDF_FIELD_FILTER_NONE,
2080 + RRDF_FIELD_OPTS_NONE,
2081 + NULL);
2082 +
2083 + buffer_rrdf_table_add_field(
2084 + wb,
2085 + field_id++,
2086 + "count",
2087 + "Count",
2088 + RRDF_FIELD_TYPE_INTEGER,
2089 + RRDF_FIELD_VISUAL_VALUE,
2090 + RRDF_FIELD_TRANSFORM_NONE,
2091 + 0,
2092 + NULL,
2093 + NAN,
2094 + RRDF_FIELD_SORT_ASCENDING,
2095 + NULL,
2096 + RRDF_FIELD_SUMMARY_COUNT,
2097 + RRDF_FIELD_FILTER_NONE,
2098 + RRDF_FIELD_OPTS_NONE,
2099 + NULL);
2100 }
2101
2102 buffer_json_object_close(wb); // columns
src/libnetdata/libjudy/judyl-typed.h
+9 -9
@@ -14,12 +14,12 @@
14 } NAME##_JudyLSet; \
15 \
16 ALWAYS_INLINE \
17 - static void NAME##_INIT(NAME##_JudyLSet *set) { \
17 + static __attribute__((unused)) void NAME##_INIT(NAME##_JudyLSet *set) { \
18 set->judyl = NULL; \
19 } \
20 \
21 ALWAYS_INLINE \
22 - static bool NAME##_SET(NAME##_JudyLSet *set, Word_t index, TYPE value) { \
22 + static bool __attribute__((unused)) NAME##_SET(NAME##_JudyLSet *set, Word_t index, TYPE value) { \
23 Pvoid_t *pValue = JudyLIns(&set->judyl, index, PJE0); \
24 if (pValue == PJERR) return false; \
25 *pValue = (void *)PACK_MACRO(value); \
@@ -27,42 +27,42 @@
27 } \
28 \
29 ALWAYS_INLINE \
30 - static TYPE NAME##_GET(NAME##_JudyLSet *set, Word_t index) { \
30 + static TYPE __attribute__((unused)) NAME##_GET(NAME##_JudyLSet *set, Word_t index) { \
31 Pvoid_t *pValue = JudyLGet(set->judyl, index, PJE0); \
32 return (pValue != NULL) ? (TYPE)UNPACK_MACRO(*pValue) : (TYPE){0}; \
33 } \
34 \
35 ALWAYS_INLINE \
36 - static bool NAME##_DEL(NAME##_JudyLSet *set, Word_t index) { \
36 + static bool __attribute__((unused)) NAME##_DEL(NAME##_JudyLSet *set, Word_t index) { \
37 return JudyLDel(&set->judyl, index, PJE0) == 1; \
38 } \
39 \
40 ALWAYS_INLINE \
41 - static TYPE NAME##_FIRST(NAME##_JudyLSet *set, Word_t *index) { \
41 + static TYPE __attribute__((unused)) NAME##_FIRST(NAME##_JudyLSet *set, Word_t *index) { \
42 Pvoid_t *pValue = JudyLFirst(set->judyl, index, PJE0); \
43 return (pValue != NULL) ? (TYPE)UNPACK_MACRO(*pValue) : (TYPE){0}; \
44 } \
45 \
46 ALWAYS_INLINE \
47 - static TYPE NAME##_NEXT(NAME##_JudyLSet *set, Word_t *index) { \
47 + static TYPE __attribute__((unused)) NAME##_NEXT(NAME##_JudyLSet *set, Word_t *index) { \
48 Pvoid_t *pValue = JudyLNext(set->judyl, index, PJE0); \
49 return (pValue != NULL) ? (TYPE)UNPACK_MACRO(*pValue) : (TYPE){0}; \
50 } \
51 \
52 ALWAYS_INLINE \
53 - static TYPE NAME##_LAST(NAME##_JudyLSet *set, Word_t *index) { \
53 + static TYPE __attribute__((unused)) NAME##_LAST(NAME##_JudyLSet *set, Word_t *index) { \
54 Pvoid_t *pValue = JudyLLast(set->judyl, index, PJE0); \
55 return (pValue != NULL) ? (TYPE)UNPACK_MACRO(*pValue) : (TYPE){0}; \
56 } \
57 \
58 ALWAYS_INLINE \
59 - static TYPE NAME##_PREV(NAME##_JudyLSet *set, Word_t *index) { \
59 + static TYPE __attribute__((unused)) NAME##_PREV(NAME##_JudyLSet *set, Word_t *index) { \
60 Pvoid_t *pValue = JudyLPrev(set->judyl, index, PJE0); \
61 return (pValue != NULL) ? (TYPE)UNPACK_MACRO(*pValue) : (TYPE){0}; \
62 } \
63 \
64 ALWAYS_INLINE \
65 - static void NAME##_FREE(NAME##_JudyLSet *set, void (*callback)(Word_t, TYPE, void *), void *data) { \
65 + static void __attribute__((unused)) NAME##_FREE(NAME##_JudyLSet *set, void (*callback)(Word_t, TYPE, void *), void *data) { \
66 Word_t index = 0; \
67 Pvoid_t *pValue; \
68 if (callback) { \