@cryptotaxi247 / netdata-1 / commits / d477387b9

log alarm notifications to health.log (#16476)

Costa Tsaousis committed Nov 30, 2023 at 14:46 UTC d477387b985aa90e64292ddc3fe210aa44c4cc0b
4 files changed +44 -10
libnetdata/log/README.md
+1 -1
@@ -18,7 +18,7 @@ Netdata supports the following log sources:
18 1. **daemon**, logs generated by Netdata daemon.
19 2. **collector**, logs generated by Netdata collectors, including internal and external ones.
20 3. **access**, API requests received by Netdata
21 -4. **health**, logs all alert transitions
21 +4. **health**, all alert transitions and notifications
22
23 ## Log outputs
24
libnetdata/log/log.c
+41 -8
@@ -245,7 +245,7 @@ const char *nd_log_id2priority(ND_LOG_FIELD_PRIORITY priority) {
245 // ----------------------------------------------------------------------------
246 // log sources
247
248 -const char *log_sources_str[] = {
248 +const char *nd_log_sources[] = {
249 [NDLS_UNSET] = "UNSET",
250 [NDLS_ACCESS] = "access",
251 [NDLS_ACLK] = "aclk",
@@ -255,12 +255,23 @@ const char *log_sources_str[] = {
255 [NDLS_DEBUG] = "debug",
256 };
257
258 -static const char *nd_log_source2str(ND_LOG_SOURCES source) {
259 - size_t entries = sizeof(log_sources_str) / sizeof(log_sources_str[0]);
258 +size_t nd_log_source2id(const char *source, ND_LOG_SOURCES def) {
259 + size_t entries = sizeof(nd_log_sources) / sizeof(nd_log_sources[0]);
260 + for(size_t i = 0; i < entries ;i++) {
261 + if(strcmp(nd_log_sources[i], source) == 0)
262 + return i;
263 + }
264 +
265 + return def;
266 +}
267 +
268 +
269 +static const char *nd_log_id2source(ND_LOG_SOURCES source) {
270 + size_t entries = sizeof(nd_log_sources) / sizeof(nd_log_sources[0]);
271 if(source < entries)
261 - return log_sources_str[source];
272 + return nd_log_sources[source];
273
263 - return "UNKNOWN";
274 + return nd_log_sources[NDLS_COLLECTORS];
275 }
276
277 // ----------------------------------------------------------------------------
@@ -503,6 +514,13 @@ __attribute__((constructor)) void initialize_invocation_id(void) {
514 setenv("NETDATA_INVOCATION_ID", uuid, 1);
515 }
516
517 +int nd_log_health_fd(void) {
518 + if(nd_log.sources[NDLS_HEALTH].method == NDLM_FILE && nd_log.sources[NDLS_HEALTH].fd != -1)
519 + return nd_log.sources[NDLS_HEALTH].fd;
520 +
521 + return STDERR_FILENO;
522 +}
523 +
524 void nd_log_set_user_settings(ND_LOG_SOURCES source, const char *setting) {
525 char buf[FILENAME_MAX + 100];
526 if(setting && *setting)
@@ -563,7 +581,7 @@ void nd_log_set_user_settings(ND_LOG_SOURCES source, const char *setting) {
581 else
582 nd_log(NDLS_DAEMON, NDLP_ERR, "Error while parsing configuration of log source '%s'. "
583 "In config '%s', '%s' is not understood.",
566 - nd_log_source2str(source), setting, name);
584 + nd_log_id2source(source), setting, name);
585 }
586 }
587
@@ -2079,7 +2097,22 @@ static void nd_logger(const char *file, const char *function, const unsigned lon
2097 thread_log_fields[NDF_INVOCATION_ID].entry = ND_LOG_FIELD_UUID(NDF_INVOCATION_ID, &nd_log.invocation_id);
2098
2099 if(likely(!thread_log_fields[NDF_LOG_SOURCE].entry.set))
2082 - thread_log_fields[NDF_LOG_SOURCE].entry = ND_LOG_FIELD_TXT(NDF_LOG_SOURCE, nd_log_source2str(source));
2100 + thread_log_fields[NDF_LOG_SOURCE].entry = ND_LOG_FIELD_TXT(NDF_LOG_SOURCE, nd_log_id2source(source));
2101 + else {
2102 + ND_LOG_SOURCES src = source;
2103 +
2104 + if(thread_log_fields[NDF_LOG_SOURCE].entry.type == NDFT_TXT)
2105 + src = nd_log_source2id(thread_log_fields[NDF_LOG_SOURCE].entry.txt, source);
2106 + else if(thread_log_fields[NDF_LOG_SOURCE].entry.type == NDFT_U64)
2107 + src = thread_log_fields[NDF_LOG_SOURCE].entry.u64;
2108 +
2109 + if(src != source && src >= 0 && src < _NDLS_MAX) {
2110 + source = src;
2111 + output = nd_logger_select_output(source, &fp, &spinlock);
2112 + if(output != NDLM_FILE && output != NDLM_JOURNAL && output != NDLM_SYSLOG)
2113 + return;
2114 + }
2115 + }
2116
2117 if(likely(!thread_log_fields[NDF_SYSLOG_IDENTIFIER].entry.set))
2118 thread_log_fields[NDF_SYSLOG_IDENTIFIER].entry = ND_LOG_FIELD_TXT(NDF_SYSLOG_IDENTIFIER, program_name);
@@ -2145,7 +2178,7 @@ static void nd_logger(const char *file, const char *function, const unsigned lon
2178 thread_log_fields[NDF_LOG_SOURCE].entry = (struct log_stack_entry){
2179 .set = true,
2180 .type = NDFT_TXT,
2148 - .txt = nd_log_source2str(source),
2181 + .txt = nd_log_id2source(source),
2182 };
2183
2184 thread_log_fields[NDF_SYSLOG_IDENTIFIER].entry = (struct log_stack_entry){
libnetdata/log/log.h
+1
@@ -149,6 +149,7 @@ int nd_log_priority2id(const char *priority);
149 const char *nd_log_id2priority(ND_LOG_FIELD_PRIORITY priority);
150 const char *nd_log_method_for_external_plugins(const char *s);
151
152 +int nd_log_health_fd(void);
153 typedef bool (*log_formatter_callback_t)(BUFFER *wb, void *data);
154
155 struct log_stack_entry {
spawn/spawn.c
+1 -1
@@ -215,7 +215,7 @@ int create_spawn_server(uv_loop_t *loop, uv_pipe_t *spawn_channel, uv_process_t
215 stdio[1].flags = UV_INHERIT_FD;
216 stdio[1].data.fd = 1 /* UV_STDOUT_FD */;
217 stdio[2].flags = UV_INHERIT_FD;
218 - stdio[2].data.fd = 2 /* UV_STDERR_FD */;
218 + stdio[2].data.fd = nd_log_health_fd() /* UV_STDERR_FD */;
219
220 ret = uv_spawn(loop, process, &options); /* execute the netdata binary again as the netdata user */
221 if (0 != ret) {