summaryrefslogtreecommitdiffstats
path: root/src/libnetdata/log/nd_log-internals.h
blob: 7bebf5a4a6277a84041dc4f61674cbb33116137a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef NETDATA_ND_LOG_INTERNALS_H
#define NETDATA_ND_LOG_INTERNALS_H

#include "../libnetdata.h"

#ifdef __FreeBSD__
#include <sys/endian.h>
#endif

#ifdef __APPLE__
#include <machine/endian.h>
#endif

#if !defined(ENABLE_SENTRY) && defined(HAVE_BACKTRACE)
#include <execinfo.h>
#endif

#ifdef HAVE_SYSTEMD
#include <systemd/sd-journal.h>
#endif

const char *errno2str(int errnum, char *buf, size_t size);

// --------------------------------------------------------------------------------------------------------------------
// ND_LOG_METHOD

typedef enum  __attribute__((__packed__)) {
    NDLM_DISABLED = 0,
    NDLM_DEVNULL,
    NDLM_DEFAULT,
    NDLM_JOURNAL,
    NDLM_SYSLOG,
    NDLM_STDOUT,
    NDLM_STDERR,
    NDLM_FILE,
#if defined(OS_WINDOWS)
#if defined(HAVE_ETW)
    NDLM_ETW,
#endif
#if defined(HAVE_WEL)
    NDLM_WEL,
#endif
#endif
} ND_LOG_METHOD;

// all the log methods are finally mapped to these
#if defined(HAVE_ETW)
#define ETW_CONDITION(ndlo) ((ndlo) == NDLM_ETW)
#else
#define ETW_CONDITION(ndlo) (false)
#endif

#if defined(HAVE_WEL)
#define WEL_CONDITION(ndlo) ((ndlo) == NDLM_WEL)
#else
#define WEL_CONDITION(ndlo) (false)
#endif

#define IS_VALID_LOG_METHOD_FOR_EXTERNAL_PLUGINS(ndlo) ((ndlo) == NDLM_JOURNAL || (ndlo) == NDLM_SYSLOG || (ndlo) == NDLM_STDERR || ETW_CONDITION(ndlo) || WEL_CONDITION(ndlo))
#define IS_FINAL_LOG_METHOD(ndlo) ((ndlo) == NDLM_FILE || (ndlo) == NDLM_JOURNAL || (ndlo) == NDLM_SYSLOG || ETW_CONDITION(ndlo) || WEL_CONDITION(ndlo))

ND_LOG_METHOD nd_log_method2id(const char *method);
const char *nd_log_id2method(ND_LOG_METHOD method);

// --------------------------------------------------------------------------------------------------------------------
// ND_LOG_FORMAT

typedef enum __attribute__((__packed__)) {
    NDLF_JOURNAL,
    NDLF_LOGFMT,
    NDLF_JSON,
#if defined(OS_WINDOWS)
#if defined(HAVE_ETW)
    NDLF_ETW, // Event Tracing for Windows
#endif
#if defined(HAVE_WEL)
    NDLF_WEL, // Windows Event Log
#endif
#endif
} ND_LOG_FORMAT;

#define ETW_NAME "etw"
#define WEL_NAME "wel"

const char *nd_log_id2format(ND_LOG_FORMAT format);
ND_LOG_FORMAT nd_log_format2id(const char *format);

size_t nd_log_source2id(const char *source, ND_LOG_SOURCES def);
const char *nd_log_id2source(ND_LOG_SOURCES source);

const char *nd_log_id2priority(ND_LOG_FIELD_PRIORITY priority);
int nd_log_priority2id(const char *priority);

const char *nd_log_id2facility(int facility);
int nd_log_facility2id(const char *facility);

#include "nd_log_limit.h"

struct nd_log_source {
    SPINLOCK spinlock;
    ND_LOG_METHOD method;
    ND_LOG_FORMAT format;
    const char *filename;
    int fd;
    FILE *fp;

    ND_LOG_FIELD_PRIORITY min_priority;
    const char *pending_msg;
    struct nd_log_limit limits;

#if defined(OS_WINDOWS)
    ND_LOG_SOURCES source;
    HANDLE hEventLog;
    USHORT channelID;
    UCHAR Opcode;
    USHORT Task;
    ULONGLONG Keyword;
#endif
};

struct nd_log {
    nd_uuid_t invocation_id;

    ND_LOG_SOURCES overwrite_process_source;

    struct nd_log_source sources[_NDLS_MAX];

    struct {
        bool initialized;
        bool first_msg;
        int fd;             // we don't control this, we just detect it to keep it open
    } journal;

    struct {
        bool initialized;
        int fd;
        char filename[FILENAME_MAX];
    } journal_direct;

    struct {
        bool initialized;
        int facility;
    } syslog;

    struct {
        bool etw; // when set use etw, otherwise wel
        bool initialized;
    } eventlog;

    struct {
        SPINLOCK spinlock;
        bool initialized;
    } std_output;

    struct {
        SPINLOCK spinlock;
        bool initialized;
    } std_error;

};

// --------------------------------------------------------------------------------------------------------------------

struct log_field;
typedef const char *(*annotator_t)(struct log_field *lf);

struct log_field {
    const char *journal;
    const char *logfmt;
    const char *eventlog;
    annotator_t annotator;
    struct log_stack_entry entry;
};

#define THREAD_LOG_STACK_MAX 50
#define THREAD_FIELDS_MAX (sizeof(thread_log_fields) / sizeof(thread_log_fields[0]))

extern __thread struct log_stack_entry *thread_log_stack_base[THREAD_LOG_STACK_MAX];
extern __thread size_t thread_log_stack_next;
extern __thread struct log_field thread_log_fields[_NDF_MAX];

// --------------------------------------------------------------------------------------------------------------------

extern struct nd_log nd_log;
bool nd_log_replace_existing_fd(struct nd_log_source *e, int new_fd);
void nd_log_open(struct nd_log_source *e, ND_LOG_SOURCES source);
void nd_log_stdin_init(int fd, const char *filename);

// --------------------------------------------------------------------------------------------------------------------
// annotators

struct log_field;
const char *errno_annotator(struct log_field *lf);
const char *priority_annotator(struct log_field *lf);
const char *timestamp_usec_annotator(struct log_field *lf);

#if defined(OS_WINDOWS)
const char *winerror_annotator(struct log_field *lf);
#endif

// --------------------------------------------------------------------------------------------------------------------
// field formatters

uint64_t log_field_to_uint64(struct log_field *lf);
int64_t log_field_to_int64(struct log_field *lf);

// --------------------------------------------------------------------------------------------------------------------
// common text formatters

void nd_logger_logfmt(BUFFER *wb, struct log_field *fields, size_t fields_max);
void nd_logger_json(BUFFER *wb, struct log_field *fields, size_t fields_max);

// --------------------------------------------------------------------------------------------------------------------
// output to syslog

void nd_log_init_syslog(void);
void nd_log_reset_syslog(void);
bool nd_logger_syslog(int priority, ND_LOG_FORMAT format, struct log_field *fields, size_t fields_max);

// --------------------------------------------------------------------------------------------------------------------
// output to systemd-journal

bool nd_log_journal_systemd_init(void);
bool nd_log_journal_direct_init(const char *path);
bool nd_logger_journal_direct(struct log_field *fields, size_t fields_max);
bool nd_logger_journal_libsystemd(struct log_field *fields, size_t fields_max);

// --------------------------------------------------------------------------------------------------------------------
// output to file

bool nd_logger_file(FILE *fp, ND_LOG_FORMAT format, struct log_field *fields, size_t fields_max);

// --------------------------------------------------------------------------------------------------------------------
// output to windows events log

#if defined(OS_WINDOWS)
#if defined(HAVE_ETW)
bool nd_log_init_etw(void);
bool nd_logger_etw(struct nd_log_source *source, struct log_field *fields, size_t fields_max);
#endif
#if defined(HAVE_WEL)
bool nd_log_init_wel(void);
bool nd_logger_wel(struct nd_log_source *source, struct log_field *fields, size_t fields_max);
#endif
#endif

#endif //NETDATA_ND_LOG_INTERNALS_H