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