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