]> git.proxmox.com Git - mirror_frr.git/blame - lib/zlog.h
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / lib / zlog.h
CommitLineData
acddc0ed 1// SPDX-License-Identifier: ISC
0bdeb5e5
DL
2/*
3 * Copyright (c) 2015-19 David Lamparter, for NetDEF, Inc.
0bdeb5e5
DL
4 */
5
6#ifndef _FRR_ZLOG_H
7#define _FRR_ZLOG_H
8
9#include <stdarg.h>
10#include <stdbool.h>
11#include <stdint.h>
12#include <string.h>
13#include <syslog.h>
14#include <unistd.h>
15#include <sys/uio.h>
16
6a0eb688
DL
17#include <assert.h>
18
0bdeb5e5
DL
19#include "atomlist.h"
20#include "frrcu.h"
21#include "memory.h"
22#include "hook.h"
e3daa82c 23#include "printfrr.h"
0bdeb5e5 24
17e38209
RW
25#ifdef __cplusplus
26extern "C" {
27#endif
28
c6610ea9
DL
29DECLARE_MGROUP(LOG);
30
0bdeb5e5
DL
31extern char zlog_prefix[];
32extern size_t zlog_prefixsz;
33extern int zlog_tmpdirfd;
5c58f5d3 34extern int zlog_instance;
c6610ea9 35extern const char *zlog_progname;
0bdeb5e5 36
131879fb
DL
37struct xref_logmsg {
38 struct xref xref;
39
40 const char *fmtstring;
41 uint32_t priority;
42 uint32_t ec;
2621bb8b 43 const char *args;
131879fb
DL
44};
45
ef990bd9
DL
46/* whether flag was added in config mode or enable mode */
47#define LOGMSG_FLAG_EPHEMERAL (1 << 0)
48#define LOGMSG_FLAG_PERSISTENT (1 << 1)
49
131879fb
DL
50struct xrefdata_logmsg {
51 struct xrefdata xrefdata;
52
ef990bd9 53 uint8_t fl_print_bt;
131879fb
DL
54};
55
0bdeb5e5
DL
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
f89c0aed 60 * determine whether something is a log message or something else.
0bdeb5e5
DL
61 */
62
c695bdbe
DL
63extern void vzlogx(const struct xref_logmsg *xref, int prio, const char *fmt,
64 va_list ap) PRINTFRR(3, 0);
131879fb 65#define vzlog(prio, ...) vzlogx(NULL, prio, __VA_ARGS__)
0bdeb5e5 66
c2527ed2 67PRINTFRR(2, 3)
0bdeb5e5
DL
68static 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
131879fb
DL
77PRINTFRR(2, 3)
78static 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
c364a096
EDP
88#define _zlog_ecref(ec_, prio, msg, ...) \
89 do { \
ef990bd9
DL
90 static struct xrefdata_logmsg _xrefdata = { \
91 .xrefdata = \
92 { \
93 .xref = NULL, \
94 .uid = {}, \
95 .hashstr = (msg), \
96 .hashu32 = {(prio), (ec_)}, \
97 }, \
131879fb 98 }; \
c364a096
EDP
99 static const struct xref_logmsg _xref __attribute__( \
100 (used)) = { \
ef990bd9
DL
101 .xref = XREF_INIT(XREFT_LOGMSG, &_xrefdata.xrefdata, \
102 __func__), \
131879fb
DL
103 .fmtstring = (msg), \
104 .priority = (prio), \
105 .ec = (ec_), \
2621bb8b 106 .args = (#__VA_ARGS__), \
131879fb
DL
107 }; \
108 XREF_LINK(_xref.xref); \
a3c67498 109 zlog_ref(&_xref, (msg), ##__VA_ARGS__); \
131879fb
DL
110 } while (0)
111
a3c67498
DL
112#define zlog_err(...) _zlog_ecref(0, LOG_ERR, __VA_ARGS__)
113#define zlog_warn(...) _zlog_ecref(0, LOG_WARNING, __VA_ARGS__)
114#define zlog_info(...) _zlog_ecref(0, LOG_INFO, __VA_ARGS__)
115#define zlog_notice(...) _zlog_ecref(0, LOG_NOTICE, __VA_ARGS__)
116#define zlog_debug(...) _zlog_ecref(0, LOG_DEBUG, __VA_ARGS__)
117
131879fb
DL
118#define flog_err(ferr_id, format, ...) \
119 _zlog_ecref(ferr_id, LOG_ERR, format, ## __VA_ARGS__)
120#define flog_warn(ferr_id, format, ...) \
121 _zlog_ecref(ferr_id, LOG_WARNING, format, ## __VA_ARGS__)
122
123#define flog_err_sys(ferr_id, format, ...) \
a3c67498 124 _zlog_ecref(ferr_id, LOG_ERR, format, ## __VA_ARGS__)
0bdeb5e5
DL
125
126extern void zlog_sigsafe(const char *text, size_t len);
127
128/* extra priority value to disable a target without deleting it */
129#define ZLOG_DISABLED (LOG_EMERG-1)
130
131/* zlog_msg encapsulates a particular logging call from somewhere in the code.
132 * The same struct is passed around to all zlog_targets.
133 *
134 * This is used to defer formatting the log message until it is actually
135 * requested by one of the targets. If none of the targets needs the message
136 * formatted, the formatting call is avoided entirely.
137 *
138 * This struct is opaque / private to the core zlog code. Logging targets
139 * should use zlog_msg_* functions to get text / timestamps / ... for a
140 * message.
141 */
142
143struct zlog_msg;
144
145extern int zlog_msg_prio(struct zlog_msg *msg);
131879fb 146extern const struct xref_logmsg *zlog_msg_xref(struct zlog_msg *msg);
0bdeb5e5 147
8b94cb43
DL
148/* text is NOT \0 terminated; instead there is a \n after textlen since the
149 * logging targets would jump extra hoops otherwise for a single byte. (the
150 * \n is not included in textlen)
151 *
152 * calling this with NULL textlen is likely wrong.
153 * use "%.*s", (int)textlen, text when passing to printf-like functions
154 */
0bdeb5e5
DL
155extern const char *zlog_msg_text(struct zlog_msg *msg, size_t *textlen);
156
e3daa82c
DL
157extern void zlog_msg_args(struct zlog_msg *msg, size_t *hdrlen,
158 size_t *n_argpos, const struct fmt_outpos **argpos);
159
0bdeb5e5
DL
160/* timestamp formatting control flags */
161
162/* sub-second digit count */
163#define ZLOG_TS_PREC 0xfU
164
165/* 8601: 0000-00-00T00:00:00Z (if used with ZLOG_TS_UTC)
166 * 0000-00-00T00:00:00+00:00 (otherwise)
167 * Legacy: 0000/00/00 00:00:00 (no TZ indicated!)
168 */
169#define ZLOG_TS_ISO8601 (1 << 8)
170#define ZLOG_TS_LEGACY (1 << 9)
171
172/* default is local time zone */
173#define ZLOG_TS_UTC (1 << 10)
174
df45017f
DL
175struct timespec;
176
f6caaa65 177extern size_t zlog_msg_ts(struct zlog_msg *msg, struct fbuf *out,
0bdeb5e5 178 uint32_t flags);
df45017f 179extern void zlog_msg_tsraw(struct zlog_msg *msg, struct timespec *ts);
0bdeb5e5 180
243ff228
DL
181/* "mmm dd hh:mm:ss" for RFC3164 syslog. Only ZLOG_TS_UTC for flags. */
182extern size_t zlog_msg_ts_3164(struct zlog_msg *msg, struct fbuf *out,
183 uint32_t flags);
184
78598fd0
DL
185/* currently just returns the current PID/TID since we never write another
186 * thread's messages
187 */
188extern void zlog_msg_pid(struct zlog_msg *msg, intmax_t *pid, intmax_t *tid);
189
0bdeb5e5
DL
190/* This list & struct implements the actual logging targets. It is accessed
191 * lock-free from all threads, and thus MUST only be changed atomically, i.e.
192 * RCU.
193 *
194 * Since there's no atomic replace, the replacement action is an add followed
195 * by a delete. This means that during logging config changes, log messages
196 * may be duplicated in the log target that is being changed. The old entry
197 * being changed MUST also at the very least not crash or do other stupid
198 * things.
199 *
200 * This list and struct are NOT related to config. Logging config is kept
201 * separately, and results in creating appropriate zlog_target(s) to realize
202 * the config. Log targets may also be created from varying sources, e.g.
203 * command line options, or VTY commands ("log monitor").
204 *
205 * struct zlog_target is intended to be embedded into a larger structure that
206 * contains additional field for the specific logging target, e.g. an fd or
207 * additional options. It MUST be the first field in that larger struct.
208 */
209
960b9a53 210PREDECL_ATOMLIST(zlog_targets);
0bdeb5e5
DL
211struct zlog_target {
212 struct zlog_targets_item head;
213
214 int prio_min;
215
216 void (*logfn)(struct zlog_target *zt, struct zlog_msg *msg[],
217 size_t nmsgs);
218
219 /* for crash handlers, set to NULL if log target can't write crash logs
220 * without possibly deadlocking (AS-Safe)
221 *
222 * text is not \0 terminated & split up into lines (e.g. no \n)
223 */
224 void (*logfn_sigsafe)(struct zlog_target *zt, const char *text,
225 size_t len);
226
227 struct rcu_head rcu_head;
228};
229
230/* make a copy for RCUpdating. oldzt may be NULL to allocate a fresh one. */
231extern struct zlog_target *zlog_target_clone(struct memtype *mt,
232 struct zlog_target *oldzt,
233 size_t size);
234
235/* update the zlog_targets list; both oldzt and newzt may be NULL. You
236 * still need to zlog_target_free() the old target afterwards if it wasn't
237 * NULL.
238 *
239 * Returns oldzt so you can zlog_target_free(zlog_target_replace(old, new));
240 * (Some log targets may need extra cleanup inbetween, but remember the old
241 * target MUST remain functional until the end of the current RCU cycle.)
242 */
243extern struct zlog_target *zlog_target_replace(struct zlog_target *oldzt,
244 struct zlog_target *newzt);
245
246/* Mostly for symmetry for zlog_target_clone(), just rcu_free() internally. */
247#define zlog_target_free(mt, zt) \
248 rcu_free(mt, zt, rcu_head)
249
250extern void zlog_init(const char *progname, const char *protoname,
251 unsigned short instance, uid_t uid, gid_t gid);
252DECLARE_HOOK(zlog_init, (const char *progname, const char *protoname,
253 unsigned short instance, uid_t uid, gid_t gid),
8451921b 254 (progname, protoname, instance, uid, gid));
0bdeb5e5
DL
255
256extern void zlog_fini(void);
8451921b 257DECLARE_KOOH(zlog_fini, (), ());
0bdeb5e5 258
a3c67498
DL
259extern void zlog_set_prefix_ec(bool enable);
260extern bool zlog_get_prefix_ec(void);
261extern void zlog_set_prefix_xid(bool enable);
262extern bool zlog_get_prefix_xid(void);
263
0bdeb5e5
DL
264/* for tools & test programs, i.e. anything not a daemon.
265 * (no cleanup needed at exit)
266 */
267extern void zlog_aux_init(const char *prefix, int prio_min);
268DECLARE_HOOK(zlog_aux_init, (const char *prefix, int prio_min),
8451921b 269 (prefix, prio_min));
0bdeb5e5
DL
270
271extern void zlog_startup_end(void);
272
273extern void zlog_tls_buffer_init(void);
274extern void zlog_tls_buffer_flush(void);
275extern void zlog_tls_buffer_fini(void);
276
42ddefe8
MS
277/* Enable or disable 'immediate' output - default is to buffer messages. */
278extern void zlog_set_immediate(bool set_p);
279
c6610ea9
DL
280extern const char *zlog_priority_str(int priority);
281
17e38209
RW
282#ifdef __cplusplus
283}
284#endif
285
0bdeb5e5 286#endif /* _FRR_ZLOG_H */