]>
git.proxmox.com Git - mirror_frr.git/blob - lib/zlog.h
1 // SPDX-License-Identifier: ISC
3 * Copyright (c) 2015-19 David Lamparter, for NetDEF, Inc.
31 extern char zlog_prefix
[];
32 extern size_t zlog_prefixsz
;
33 extern int zlog_tmpdirfd
;
34 extern int zlog_instance
;
35 extern const char *zlog_progname
;
40 const char *fmtstring
;
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)
50 struct xrefdata_logmsg
{
51 struct xrefdata xrefdata
;
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 whether something is a log message or something else.
63 extern void vzlogx(const struct xref_logmsg
*xref
, int prio
, const char *fmt
,
64 va_list ap
) PRINTFRR(3, 0);
65 #define vzlog(prio, ...) vzlogx(NULL, prio, __VA_ARGS__)
68 static inline void zlog(int prio
, const char *fmt
, ...)
78 static inline void zlog_ref(const struct xref_logmsg
*xref
,
84 vzlogx(xref
, xref
->priority
, fmt
, ap
);
88 #define _zlog_ecref(ec_, prio, msg, ...) \
90 static struct xrefdata_logmsg _xrefdata = { \
96 .hashu32 = {(prio), (ec_)}, \
99 static const struct xref_logmsg _xref __attribute__( \
101 .xref = XREF_INIT(XREFT_LOGMSG, &_xrefdata.xrefdata, \
103 .fmtstring = (msg), \
104 .priority = (prio), \
106 .args = (#__VA_ARGS__), \
108 XREF_LINK(_xref.xref); \
109 zlog_ref(&_xref, (msg), ##__VA_ARGS__); \
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__)
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__)
123 #define flog_err_sys(ferr_id, format, ...) \
124 _zlog_ecref(ferr_id, LOG_ERR, format, ## __VA_ARGS__)
126 extern void zlog_sigsafe(const char *text
, size_t len
);
128 /* extra priority value to disable a target without deleting it */
129 #define ZLOG_DISABLED (LOG_EMERG-1)
131 /* zlog_msg encapsulates a particular logging call from somewhere in the code.
132 * The same struct is passed around to all zlog_targets.
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.
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
145 extern int zlog_msg_prio(struct zlog_msg
*msg
);
146 extern const struct xref_logmsg
*zlog_msg_xref(struct zlog_msg
*msg
);
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)
152 * calling this with NULL textlen is likely wrong.
153 * use "%.*s", (int)textlen, text when passing to printf-like functions
155 extern const char *zlog_msg_text(struct zlog_msg
*msg
, size_t *textlen
);
157 extern void zlog_msg_args(struct zlog_msg
*msg
, size_t *hdrlen
,
158 size_t *n_argpos
, const struct fmt_outpos
**argpos
);
160 /* timestamp formatting control flags */
162 /* sub-second digit count */
163 #define ZLOG_TS_PREC 0xfU
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!)
169 #define ZLOG_TS_ISO8601 (1 << 8)
170 #define ZLOG_TS_LEGACY (1 << 9)
172 /* default is local time zone */
173 #define ZLOG_TS_UTC (1 << 10)
177 extern size_t zlog_msg_ts(struct zlog_msg
*msg
, struct fbuf
*out
,
179 extern void zlog_msg_tsraw(struct zlog_msg
*msg
, struct timespec
*ts
);
181 /* "mmm dd hh:mm:ss" for RFC3164 syslog. Only ZLOG_TS_UTC for flags. */
182 extern size_t zlog_msg_ts_3164(struct zlog_msg
*msg
, struct fbuf
*out
,
185 /* currently just returns the current PID/TID since we never write another
188 extern void zlog_msg_pid(struct zlog_msg
*msg
, intmax_t *pid
, intmax_t *tid
);
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.
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
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").
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.
210 PREDECL_ATOMLIST(zlog_targets
);
212 struct zlog_targets_item head
;
216 void (*logfn
)(struct zlog_target
*zt
, struct zlog_msg
*msg
[],
219 /* for crash handlers, set to NULL if log target can't write crash logs
220 * without possibly deadlocking (AS-Safe)
222 * text is not \0 terminated & split up into lines (e.g. no \n)
224 void (*logfn_sigsafe
)(struct zlog_target
*zt
, const char *text
,
227 struct rcu_head rcu_head
;
230 /* make a copy for RCUpdating. oldzt may be NULL to allocate a fresh one. */
231 extern struct zlog_target
*zlog_target_clone(struct memtype
*mt
,
232 struct zlog_target
*oldzt
,
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
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.)
243 extern struct zlog_target
*zlog_target_replace(struct zlog_target
*oldzt
,
244 struct zlog_target
*newzt
);
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)
250 extern void zlog_init(const char *progname
, const char *protoname
,
251 unsigned short instance
, uid_t uid
, gid_t gid
);
252 DECLARE_HOOK(zlog_init
, (const char *progname
, const char *protoname
,
253 unsigned short instance
, uid_t uid
, gid_t gid
),
254 (progname
, protoname
, instance
, uid
, gid
));
256 extern void zlog_fini(void);
257 DECLARE_KOOH(zlog_fini
, (), ());
259 extern void zlog_set_prefix_ec(bool enable
);
260 extern bool zlog_get_prefix_ec(void);
261 extern void zlog_set_prefix_xid(bool enable
);
262 extern bool zlog_get_prefix_xid(void);
264 /* for tools & test programs, i.e. anything not a daemon.
265 * (no cleanup needed at exit)
267 extern void zlog_aux_init(const char *prefix
, int prio_min
);
268 DECLARE_HOOK(zlog_aux_init
, (const char *prefix
, int prio_min
),
271 extern void zlog_startup_end(void);
273 extern void zlog_tls_buffer_init(void);
274 extern void zlog_tls_buffer_flush(void);
275 extern void zlog_tls_buffer_fini(void);
277 /* Enable or disable 'immediate' output - default is to buffer messages. */
278 extern void zlog_set_immediate(bool set_p
);
280 extern const char *zlog_priority_str(int priority
);
286 #endif /* _FRR_ZLOG_H */