| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #ifndef NETDATA_ND_LOG_INTERNALS_H |
| 4 | #define NETDATA_ND_LOG_INTERNALS_H |
| 5 | |
| 6 | #include "../libnetdata.h" |
| 7 | |
| 8 | #ifdef __FreeBSD__ |
| 9 | #include <sys/endian.h> |
| 10 | #endif |
| 11 | |
| 12 | #ifdef __APPLE__ |
| 13 | #include <machine/endian.h> |
| 14 | #endif |
| 15 | |
| 16 | #if !defined(ENABLE_SENTRY) && defined(HAVE_BACKTRACE) |
| 17 | #include <execinfo.h> |
| 18 | #endif |
| 19 | |
| 20 | #ifdef HAVE_SYSTEMD |
| 21 | #include <systemd/sd-journal.h> |
| 22 | #endif |
| 23 | |
| 24 | const char *errno2str(int errnum, char *buf, size_t size); |
| 25 | |
| 26 | // -------------------------------------------------------------------------------------------------------------------- |
| 27 | // ND_LOG_METHOD |
| 28 | |
| 29 | typedef enum __attribute__((__packed__)) { |
| 30 | NDLM_DISABLED = 0, |
| 31 | NDLM_DEVNULL, |
| 32 | NDLM_DEFAULT, |
| 33 | NDLM_JOURNAL, |
| 34 | NDLM_SYSLOG, |
| 35 | NDLM_STDOUT, |
| 36 | NDLM_STDERR, |
| 37 | NDLM_FILE, |
| 38 | #if defined(OS_WINDOWS) |
| 39 | #if defined(HAVE_ETW) |
| 40 | NDLM_ETW, |
| 41 | #endif |
| 42 | #if defined(HAVE_WEL) |
| 43 | NDLM_WEL, |
| 44 | #endif |
| 45 | #endif |
| 46 | } ND_LOG_METHOD; |
| 47 | |
| 48 | // all the log methods are finally mapped to these |
| 49 | #if defined(HAVE_ETW) |
| 50 | #define ETW_CONDITION(ndlo) ((ndlo) == NDLM_ETW) |
| 51 | #else |
| 52 | #define ETW_CONDITION(ndlo) (false) |
| 53 | #endif |
| 54 | |
| 55 | #if defined(HAVE_WEL) |
| 56 | #define WEL_CONDITION(ndlo) ((ndlo) == NDLM_WEL) |
| 57 | #else |
| 58 | #define WEL_CONDITION(ndlo) (false) |
| 59 | #endif |
| 60 | |
| 61 | #define IS_VALID_LOG_METHOD_FOR_EXTERNAL_PLUGINS(ndlo) ((ndlo) == NDLM_JOURNAL || (ndlo) == NDLM_SYSLOG || (ndlo) == NDLM_STDERR || ETW_CONDITION(ndlo) || WEL_CONDITION(ndlo)) |
| 62 | #define IS_FINAL_LOG_METHOD(ndlo) ((ndlo) == NDLM_FILE || (ndlo) == NDLM_JOURNAL || (ndlo) == NDLM_SYSLOG || ETW_CONDITION(ndlo) || WEL_CONDITION(ndlo)) |
| 63 | |
| 64 | ND_LOG_METHOD nd_log_method2id(const char *method); |
| 65 | const char *nd_log_id2method(ND_LOG_METHOD method); |
| 66 | |
| 67 | // -------------------------------------------------------------------------------------------------------------------- |
| 68 | // ND_LOG_FORMAT |
| 69 | |
| 70 | typedef enum __attribute__((__packed__)) { |
| 71 | NDLF_JOURNAL, |
| 72 | NDLF_LOGFMT, |
| 73 | NDLF_JSON, |
| 74 | #if defined(OS_WINDOWS) |
| 75 | #if defined(HAVE_ETW) |
| 76 | NDLF_ETW, // Event Tracing for Windows |
| 77 | #endif |
| 78 | #if defined(HAVE_WEL) |
| 79 | NDLF_WEL, // Windows Event Log |
| 80 | #endif |
| 81 | #endif |
| 82 | } ND_LOG_FORMAT; |
| 83 | |
| 84 | #define ETW_NAME "etw" |
| 85 | #define WEL_NAME "wel" |
| 86 | |
| 87 | const char *nd_log_id2format(ND_LOG_FORMAT format); |
| 88 | ND_LOG_FORMAT nd_log_format2id(const char *format); |
| 89 | |
| 90 | size_t nd_log_source2id(const char *source, ND_LOG_SOURCES def); |
| 91 | const char *nd_log_id2source(ND_LOG_SOURCES source); |
| 92 | |
| 93 | const char *nd_log_id2priority(ND_LOG_FIELD_PRIORITY priority); |
| 94 | int nd_log_priority2id(const char *priority); |
| 95 | |
| 96 | const char *nd_log_id2facility(int facility); |
| 97 | int nd_log_facility2id(const char *facility); |
| 98 | |
| 99 | #include "nd_log_limit.h" |
| 100 | |
| 101 | struct nd_log_source { |
| 102 | netdata_mutex_t mutex; // protects write() serialization for FILE* output |
| 103 | ND_LOG_METHOD method; |
| 104 | ND_LOG_FORMAT format; |
| 105 | const char *filename; |
| 106 | int fd; |
| 107 | FILE *fp; |
| 108 | |
| 109 | ND_LOG_FIELD_PRIORITY min_priority; |
| 110 | const nd_uuid_t *pending_msgid; |
| 111 | const char *pending_msg; |
| 112 | struct nd_log_limit limits; |
| 113 | |
| 114 | #if defined(OS_WINDOWS) |
| 115 | ND_LOG_SOURCES source; |
| 116 | HANDLE hEventLog; |
| 117 | USHORT channelID; |
| 118 | UCHAR Opcode; |
| 119 | USHORT Task; |
| 120 | ULONGLONG Keyword; |
| 121 | #endif |
| 122 | }; |
| 123 | |
| 124 | struct nd_log { |
| 125 | nd_uuid_t invocation_id; |
| 126 | |
| 127 | ND_LOG_SOURCES overwrite_process_source; |
| 128 | bool mutexes_initialized; |
| 129 | // Only set in post-fork nofork spawn-server children, which stay single-threaded in-tree. |
| 130 | bool single_threaded_child; |
| 131 | log_event_t fatal_hook_cb; |
| 132 | fatal_event_t fatal_final_cb; |
| 133 | |
| 134 | struct nd_log_source sources[_NDLS_MAX]; |
| 135 | |
| 136 | struct { |
| 137 | bool initialized; |
| 138 | bool first_msg; |
| 139 | int fd; // we don't control this, we just detect it to keep it open |
| 140 | } journal; |
| 141 | |
| 142 | struct { |
| 143 | bool initialized; |
| 144 | int fd; |
| 145 | char filename[FILENAME_MAX]; |
| 146 | } journal_direct; |
| 147 | |
| 148 | struct { |
| 149 | bool initialized; |
| 150 | int facility; |
| 151 | } syslog; |
| 152 | |
| 153 | struct { |
| 154 | bool etw; // when set use etw, otherwise wel |
| 155 | bool initialized; |
| 156 | bool provider_enabled; // track etw provider state |
| 157 | SPINLOCK provider_lock; // Protect etw provider state access |
| 158 | } eventlog; |
| 159 | |
| 160 | struct { |
| 161 | netdata_mutex_t mutex; // protects write() serialization for stdout |
| 162 | bool initialized; |
| 163 | } std_output; |
| 164 | |
| 165 | struct { |
| 166 | netdata_mutex_t mutex; // protects write() serialization for stderr |
| 167 | bool initialized; |
| 168 | } std_error; |
| 169 | |
| 170 | }; |
| 171 | |
| 172 | // -------------------------------------------------------------------------------------------------------------------- |
| 173 | |
| 174 | struct log_field; |
| 175 | typedef const char *(*annotator_t)(struct log_field *lf); |
| 176 | |
| 177 | struct log_field { |
| 178 | const char *journal; |
| 179 | const char *logfmt; |
| 180 | const char *eventlog; |
| 181 | annotator_t logfmt_annotator; |
| 182 | struct log_stack_entry entry; |
| 183 | }; |
| 184 | |
| 185 | #define THREAD_LOG_STACK_MAX 50 |
| 186 | #define THREAD_FIELDS_MAX (sizeof(thread_log_fields) / sizeof(thread_log_fields[0])) |
| 187 | |
| 188 | extern __thread struct log_stack_entry *thread_log_stack_base[THREAD_LOG_STACK_MAX]; |
| 189 | extern __thread size_t thread_log_stack_next; |
| 190 | extern __thread struct log_field thread_log_fields[_NDF_MAX]; |
| 191 | |
| 192 | // -------------------------------------------------------------------------------------------------------------------- |
| 193 | |
| 194 | extern struct nd_log nd_log; |
| 195 | bool nd_log_replace_existing_fd(struct nd_log_source *e, int new_fd); |
| 196 | void nd_log_open(struct nd_log_source *e, ND_LOG_SOURCES source); |
| 197 | void nd_log_stdin_init(int fd, const char *filename); |
| 198 | |
| 199 | // -------------------------------------------------------------------------------------------------------------------- |
| 200 | // annotators |
| 201 | |
| 202 | struct log_field; |
| 203 | const char *errno_annotator(struct log_field *lf); |
| 204 | const char *priority_annotator(struct log_field *lf); |
| 205 | const char *timestamp_usec_annotator(struct log_field *lf); |
| 206 | |
| 207 | #if defined(OS_WINDOWS) |
| 208 | const char *winerror_annotator(struct log_field *lf); |
| 209 | #endif |
| 210 | |
| 211 | // -------------------------------------------------------------------------------------------------------------------- |
| 212 | // field formatters |
| 213 | |
| 214 | uint64_t log_field_to_uint64(struct log_field *lf); |
| 215 | int64_t log_field_to_int64(struct log_field *lf); |
| 216 | const char *log_field_strdupz(struct log_field *lf); |
| 217 | |
| 218 | // -------------------------------------------------------------------------------------------------------------------- |
| 219 | // common text formatters |
| 220 | |
| 221 | void nd_logger_logfmt(BUFFER *wb, struct log_field *fields, size_t fields_max); |
| 222 | void nd_logger_json(BUFFER *wb, struct log_field *fields, size_t fields_max); |
| 223 | |
| 224 | // -------------------------------------------------------------------------------------------------------------------- |
| 225 | // output to syslog |
| 226 | |
| 227 | void nd_log_init_syslog(void); |
| 228 | void nd_log_reset_syslog(void); |
| 229 | bool nd_logger_syslog(int priority, ND_LOG_FORMAT format, struct log_field *fields, size_t fields_max); |
| 230 | |
| 231 | // -------------------------------------------------------------------------------------------------------------------- |
| 232 | // output to systemd-journal |
| 233 | |
| 234 | bool nd_log_journal_systemd_init(void); |
| 235 | bool nd_log_journal_direct_init(const char *path); |
| 236 | bool nd_logger_journal_direct(struct log_field *fields, size_t fields_max); |
| 237 | bool nd_logger_journal_libsystemd(struct log_field *fields, size_t fields_max); |
| 238 | |
| 239 | // -------------------------------------------------------------------------------------------------------------------- |
| 240 | // output to file |
| 241 | |
| 242 | bool nd_logger_file(int fd, FILE *fp, netdata_mutex_t *mutex, ND_LOG_FORMAT format, struct log_field *fields, size_t fields_max); |
| 243 | |
| 244 | // -------------------------------------------------------------------------------------------------------------------- |
| 245 | // output to windows events log |
| 246 | |
| 247 | #if defined(OS_WINDOWS) |
| 248 | #if defined(HAVE_ETW) |
| 249 | bool nd_log_init_etw(void); |
| 250 | bool nd_logger_etw(struct nd_log_source *source, struct log_field *fields, size_t fields_max); |
| 251 | #endif |
| 252 | #if defined(HAVE_WEL) |
| 253 | bool nd_log_init_wel(void); |
| 254 | bool nd_logger_wel(struct nd_log_source *source, struct log_field *fields, size_t fields_max); |
| 255 | #endif |
| 256 | #endif |
| 257 | |
| 258 | #endif //NETDATA_ND_LOG_INTERNALS_H |