]> git.proxmox.com Git - mirror_frr.git/blob - lib/zlog.h
Merge pull request #8008 from chiragshah6/yang_nb5
[mirror_frr.git] / lib / zlog.h
1 /*
2 * Copyright (c) 2015-19 David Lamparter, for NetDEF, Inc.
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #ifndef _FRR_ZLOG_H
18 #define _FRR_ZLOG_H
19
20 #include <stdarg.h>
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <string.h>
24 #include <syslog.h>
25 #include <unistd.h>
26 #include <sys/uio.h>
27
28 #include "atomlist.h"
29 #include "frrcu.h"
30 #include "memory.h"
31 #include "hook.h"
32
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36
37 extern char zlog_prefix[];
38 extern size_t zlog_prefixsz;
39 extern int zlog_tmpdirfd;
40
41 struct xref_logmsg {
42 struct xref xref;
43
44 const char *fmtstring;
45 uint32_t priority;
46 uint32_t ec;
47 const char *args;
48 };
49
50 struct xrefdata_logmsg {
51 struct xrefdata xrefdata;
52
53 /* nothing more here right now */
54 };
55
56 /* These functions are set up to write to stdout/stderr without explicit
57 * initialization and/or before config load. There is no need to call e.g.
58 * fprintf(stderr, ...) just because it's "too early" at startup. Depending
59 * on context, it may still be the right thing to use fprintf though -- try to
60 * determine wether something is a log message or something else.
61 */
62
63 extern void vzlogx(const struct xref_logmsg *xref, int prio,
64 const char *fmt, va_list ap);
65 #define vzlog(prio, ...) vzlogx(NULL, prio, __VA_ARGS__)
66
67 PRINTFRR(2, 3)
68 static inline void zlog(int prio, const char *fmt, ...)
69 {
70 va_list ap;
71
72 va_start(ap, fmt);
73 vzlog(prio, fmt, ap);
74 va_end(ap);
75 }
76
77 PRINTFRR(2, 3)
78 static inline void zlog_ref(const struct xref_logmsg *xref,
79 const char *fmt, ...)
80 {
81 va_list ap;
82
83 va_start(ap, fmt);
84 vzlogx(xref, xref->priority, fmt, ap);
85 va_end(ap);
86 }
87
88 #define _zlog_ref(prio, msg, ...) \
89 do { \
90 static struct xrefdata _xrefdata = { \
91 .xref = NULL, \
92 .uid = {}, \
93 .hashstr = (msg), \
94 .hashu32 = {(prio), 0}, \
95 }; \
96 static const struct xref_logmsg _xref __attribute__( \
97 (used)) = { \
98 .xref = XREF_INIT(XREFT_LOGMSG, &_xrefdata, __func__), \
99 .fmtstring = (msg), \
100 .priority = (prio), \
101 .args = (#__VA_ARGS__), \
102 }; \
103 XREF_LINK(_xref.xref); \
104 zlog_ref(&_xref, (msg), ##__VA_ARGS__); \
105 } while (0)
106
107 #define zlog_err(...) _zlog_ref(LOG_ERR, __VA_ARGS__)
108 #define zlog_warn(...) _zlog_ref(LOG_WARNING, __VA_ARGS__)
109 #define zlog_info(...) _zlog_ref(LOG_INFO, __VA_ARGS__)
110 #define zlog_notice(...) _zlog_ref(LOG_NOTICE, __VA_ARGS__)
111 #define zlog_debug(...) _zlog_ref(LOG_DEBUG, __VA_ARGS__)
112
113 #define _zlog_ecref(ec_, prio, msg, ...) \
114 do { \
115 static struct xrefdata _xrefdata = { \
116 .xref = NULL, \
117 .uid = {}, \
118 .hashstr = (msg), \
119 .hashu32 = {(prio), (ec_)}, \
120 }; \
121 static const struct xref_logmsg _xref __attribute__( \
122 (used)) = { \
123 .xref = XREF_INIT(XREFT_LOGMSG, &_xrefdata, __func__), \
124 .fmtstring = (msg), \
125 .priority = (prio), \
126 .ec = (ec_), \
127 .args = (#__VA_ARGS__), \
128 }; \
129 XREF_LINK(_xref.xref); \
130 zlog_ref(&_xref, "[EC %u] " msg, ec_, ##__VA_ARGS__); \
131 } while (0)
132
133 #define flog_err(ferr_id, format, ...) \
134 _zlog_ecref(ferr_id, LOG_ERR, format, ## __VA_ARGS__)
135 #define flog_warn(ferr_id, format, ...) \
136 _zlog_ecref(ferr_id, LOG_WARNING, format, ## __VA_ARGS__)
137
138 #define flog_err_sys(ferr_id, format, ...) \
139 flog_err(ferr_id, format, ##__VA_ARGS__)
140 #define flog(priority, ferr_id, format, ...) \
141 zlog(priority, "[EC %u] " format, ferr_id, ##__VA_ARGS__)
142
143 extern void zlog_sigsafe(const char *text, size_t len);
144
145 /* extra priority value to disable a target without deleting it */
146 #define ZLOG_DISABLED (LOG_EMERG-1)
147
148 /* zlog_msg encapsulates a particular logging call from somewhere in the code.
149 * The same struct is passed around to all zlog_targets.
150 *
151 * This is used to defer formatting the log message until it is actually
152 * requested by one of the targets. If none of the targets needs the message
153 * formatted, the formatting call is avoided entirely.
154 *
155 * This struct is opaque / private to the core zlog code. Logging targets
156 * should use zlog_msg_* functions to get text / timestamps / ... for a
157 * message.
158 */
159
160 struct zlog_msg;
161
162 extern int zlog_msg_prio(struct zlog_msg *msg);
163 extern const struct xref_logmsg *zlog_msg_xref(struct zlog_msg *msg);
164
165 /* pass NULL as textlen if you don't need it. */
166 extern const char *zlog_msg_text(struct zlog_msg *msg, size_t *textlen);
167
168 /* timestamp formatting control flags */
169
170 /* sub-second digit count */
171 #define ZLOG_TS_PREC 0xfU
172
173 /* 8601: 0000-00-00T00:00:00Z (if used with ZLOG_TS_UTC)
174 * 0000-00-00T00:00:00+00:00 (otherwise)
175 * Legacy: 0000/00/00 00:00:00 (no TZ indicated!)
176 */
177 #define ZLOG_TS_ISO8601 (1 << 8)
178 #define ZLOG_TS_LEGACY (1 << 9)
179
180 /* default is local time zone */
181 #define ZLOG_TS_UTC (1 << 10)
182
183 extern size_t zlog_msg_ts(struct zlog_msg *msg, char *out, size_t outsz,
184 uint32_t flags);
185
186 /* This list & struct implements the actual logging targets. It is accessed
187 * lock-free from all threads, and thus MUST only be changed atomically, i.e.
188 * RCU.
189 *
190 * Since there's no atomic replace, the replacement action is an add followed
191 * by a delete. This means that during logging config changes, log messages
192 * may be duplicated in the log target that is being changed. The old entry
193 * being changed MUST also at the very least not crash or do other stupid
194 * things.
195 *
196 * This list and struct are NOT related to config. Logging config is kept
197 * separately, and results in creating appropriate zlog_target(s) to realize
198 * the config. Log targets may also be created from varying sources, e.g.
199 * command line options, or VTY commands ("log monitor").
200 *
201 * struct zlog_target is intended to be embedded into a larger structure that
202 * contains additional field for the specific logging target, e.g. an fd or
203 * additional options. It MUST be the first field in that larger struct.
204 */
205
206 PREDECL_ATOMLIST(zlog_targets)
207 struct zlog_target {
208 struct zlog_targets_item head;
209
210 int prio_min;
211
212 void (*logfn)(struct zlog_target *zt, struct zlog_msg *msg[],
213 size_t nmsgs);
214
215 /* for crash handlers, set to NULL if log target can't write crash logs
216 * without possibly deadlocking (AS-Safe)
217 *
218 * text is not \0 terminated & split up into lines (e.g. no \n)
219 */
220 void (*logfn_sigsafe)(struct zlog_target *zt, const char *text,
221 size_t len);
222
223 struct rcu_head rcu_head;
224 };
225
226 /* make a copy for RCUpdating. oldzt may be NULL to allocate a fresh one. */
227 extern struct zlog_target *zlog_target_clone(struct memtype *mt,
228 struct zlog_target *oldzt,
229 size_t size);
230
231 /* update the zlog_targets list; both oldzt and newzt may be NULL. You
232 * still need to zlog_target_free() the old target afterwards if it wasn't
233 * NULL.
234 *
235 * Returns oldzt so you can zlog_target_free(zlog_target_replace(old, new));
236 * (Some log targets may need extra cleanup inbetween, but remember the old
237 * target MUST remain functional until the end of the current RCU cycle.)
238 */
239 extern struct zlog_target *zlog_target_replace(struct zlog_target *oldzt,
240 struct zlog_target *newzt);
241
242 /* Mostly for symmetry for zlog_target_clone(), just rcu_free() internally. */
243 #define zlog_target_free(mt, zt) \
244 rcu_free(mt, zt, rcu_head)
245
246 extern void zlog_init(const char *progname, const char *protoname,
247 unsigned short instance, uid_t uid, gid_t gid);
248 DECLARE_HOOK(zlog_init, (const char *progname, const char *protoname,
249 unsigned short instance, uid_t uid, gid_t gid),
250 (progname, protoname, instance, uid, gid))
251
252 extern void zlog_fini(void);
253 DECLARE_KOOH(zlog_fini, (), ())
254
255 /* for tools & test programs, i.e. anything not a daemon.
256 * (no cleanup needed at exit)
257 */
258 extern void zlog_aux_init(const char *prefix, int prio_min);
259 DECLARE_HOOK(zlog_aux_init, (const char *prefix, int prio_min),
260 (prefix, prio_min))
261
262 extern void zlog_startup_end(void);
263
264 extern void zlog_tls_buffer_init(void);
265 extern void zlog_tls_buffer_flush(void);
266 extern void zlog_tls_buffer_fini(void);
267
268 #ifdef __cplusplus
269 }
270 #endif
271
272 #endif /* _FRR_ZLOG_H */