]>
Commit | Line | Data |
---|---|---|
1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ | |
2 | #pragma once | |
3 | ||
4 | #include <stdarg.h> | |
5 | #include <stdbool.h> | |
6 | #include <stdlib.h> | |
7 | #include <string.h> | |
8 | #include <syslog.h> | |
9 | ||
10 | #include "list.h" | |
11 | #include "macro.h" | |
12 | #include "ratelimit.h" | |
13 | #include "stdio-util.h" | |
14 | ||
15 | /* Some structures we reference but don't want to pull in headers for */ | |
16 | struct iovec; | |
17 | struct signalfd_siginfo; | |
18 | ||
19 | typedef enum LogTarget{ | |
20 | LOG_TARGET_CONSOLE, | |
21 | LOG_TARGET_KMSG, | |
22 | LOG_TARGET_JOURNAL, | |
23 | LOG_TARGET_SYSLOG, | |
24 | LOG_TARGET_CONSOLE_PREFIXED, | |
25 | LOG_TARGET_JOURNAL_OR_KMSG, | |
26 | LOG_TARGET_SYSLOG_OR_KMSG, | |
27 | LOG_TARGET_AUTO, /* console if stderr is not journal, JOURNAL_OR_KMSG otherwise */ | |
28 | LOG_TARGET_NULL, | |
29 | _LOG_TARGET_SINGLE_MAX = LOG_TARGET_SYSLOG + 1, | |
30 | _LOG_TARGET_MAX = LOG_TARGET_NULL + 1, | |
31 | _LOG_TARGET_INVALID = -EINVAL, | |
32 | } LogTarget; | |
33 | ||
34 | /* This log level disables logging completely. It can only be passed to log_set_max_level() and cannot be | |
35 | * used as a regular log level. */ | |
36 | #define LOG_NULL (LOG_EMERG - 1) | |
37 | ||
38 | #define SYNTHETIC_ERRNO(num) (abs(num) | (1 << 30)) | |
39 | #define IS_SYNTHETIC_ERRNO(val) (((val) >> 30) == 1) | |
40 | #define ERRNO_VALUE(val) (abs(val) & ~(1 << 30)) | |
41 | ||
42 | /* The callback function to be invoked when syntax warnings are seen | |
43 | * in the unit files. */ | |
44 | typedef void (*log_syntax_callback_t)(const char *unit, int level, void *userdata); | |
45 | void set_log_syntax_callback(log_syntax_callback_t cb, void *userdata); | |
46 | ||
47 | static inline void clear_log_syntax_callback(dummy_t *dummy) { | |
48 | set_log_syntax_callback(/* cb= */ NULL, /* userdata= */ NULL); | |
49 | } | |
50 | ||
51 | const char* log_target_to_string(LogTarget target) _const_; | |
52 | LogTarget log_target_from_string(const char *s) _pure_; | |
53 | void log_set_target(LogTarget target); | |
54 | void log_set_target_and_open(LogTarget target); | |
55 | int log_set_target_from_string(const char *e); | |
56 | LogTarget log_get_target(void) _pure_; | |
57 | void log_settle_target(void); | |
58 | ||
59 | int log_set_max_level(int level); | |
60 | int log_set_max_level_from_string(const char *e); | |
61 | int log_get_max_level(void) _pure_; | |
62 | int log_max_levels_to_string(int level, char **ret); | |
63 | ||
64 | void log_set_facility(int facility); | |
65 | ||
66 | void log_show_color(bool b); | |
67 | bool log_get_show_color(void) _pure_; | |
68 | void log_show_location(bool b); | |
69 | bool log_get_show_location(void) _pure_; | |
70 | void log_show_time(bool b); | |
71 | bool log_get_show_time(void) _pure_; | |
72 | void log_show_tid(bool b); | |
73 | bool log_get_show_tid(void) _pure_; | |
74 | ||
75 | int log_show_color_from_string(const char *e); | |
76 | int log_show_location_from_string(const char *e); | |
77 | int log_show_time_from_string(const char *e); | |
78 | int log_show_tid_from_string(const char *e); | |
79 | ||
80 | /* Functions below that open and close logs or configure logging based on the | |
81 | * environment should not be called from library code — this is always a job | |
82 | * for the application itself. */ | |
83 | ||
84 | assert_cc(STRLEN(__FILE__) > STRLEN(RELATIVE_SOURCE_PATH) + 1); | |
85 | #define PROJECT_FILE (&__FILE__[STRLEN(RELATIVE_SOURCE_PATH) + 1]) | |
86 | ||
87 | bool stderr_is_journal(void); | |
88 | int log_open(void); | |
89 | void log_close(void); | |
90 | void log_forget_fds(void); | |
91 | ||
92 | void log_parse_environment_variables(void); | |
93 | void log_parse_environment(void); | |
94 | ||
95 | int log_dispatch_internal( | |
96 | int level, | |
97 | int error, | |
98 | const char *file, | |
99 | int line, | |
100 | const char *func, | |
101 | const char *object_field, | |
102 | const char *object, | |
103 | const char *extra, | |
104 | const char *extra_field, | |
105 | char *buffer); | |
106 | ||
107 | int log_internal( | |
108 | int level, | |
109 | int error, | |
110 | const char *file, | |
111 | int line, | |
112 | const char *func, | |
113 | const char *format, ...) _printf_(6,7); | |
114 | ||
115 | int log_internalv( | |
116 | int level, | |
117 | int error, | |
118 | const char *file, | |
119 | int line, | |
120 | const char *func, | |
121 | const char *format, | |
122 | va_list ap) _printf_(6,0); | |
123 | ||
124 | int log_object_internalv( | |
125 | int level, | |
126 | int error, | |
127 | const char *file, | |
128 | int line, | |
129 | const char *func, | |
130 | const char *object_field, | |
131 | const char *object, | |
132 | const char *extra_field, | |
133 | const char *extra, | |
134 | const char *format, | |
135 | va_list ap) _printf_(10,0); | |
136 | ||
137 | int log_object_internal( | |
138 | int level, | |
139 | int error, | |
140 | const char *file, | |
141 | int line, | |
142 | const char *func, | |
143 | const char *object_field, | |
144 | const char *object, | |
145 | const char *extra_field, | |
146 | const char *extra, | |
147 | const char *format, ...) _printf_(10,11); | |
148 | ||
149 | int log_struct_internal( | |
150 | int level, | |
151 | int error, | |
152 | const char *file, | |
153 | int line, | |
154 | const char *func, | |
155 | const char *format, ...) _printf_(6,0) _sentinel_; | |
156 | ||
157 | int log_oom_internal( | |
158 | int level, | |
159 | const char *file, | |
160 | int line, | |
161 | const char *func); | |
162 | ||
163 | int log_format_iovec( | |
164 | struct iovec *iovec, | |
165 | size_t iovec_len, | |
166 | size_t *n, | |
167 | bool newline_separator, | |
168 | int error, | |
169 | const char *format, | |
170 | va_list ap) _printf_(6, 0); | |
171 | ||
172 | int log_struct_iovec_internal( | |
173 | int level, | |
174 | int error, | |
175 | const char *file, | |
176 | int line, | |
177 | const char *func, | |
178 | const struct iovec *input_iovec, | |
179 | size_t n_input_iovec); | |
180 | ||
181 | /* This modifies the buffer passed! */ | |
182 | int log_dump_internal( | |
183 | int level, | |
184 | int error, | |
185 | const char *file, | |
186 | int line, | |
187 | const char *func, | |
188 | char *buffer); | |
189 | ||
190 | /* Logging for various assertions */ | |
191 | _noreturn_ void log_assert_failed( | |
192 | const char *text, | |
193 | const char *file, | |
194 | int line, | |
195 | const char *func); | |
196 | ||
197 | _noreturn_ void log_assert_failed_unreachable( | |
198 | const char *file, | |
199 | int line, | |
200 | const char *func); | |
201 | ||
202 | void log_assert_failed_return( | |
203 | const char *text, | |
204 | const char *file, | |
205 | int line, | |
206 | const char *func); | |
207 | ||
208 | #define log_dispatch(level, error, buffer) \ | |
209 | log_dispatch_internal(level, error, PROJECT_FILE, __LINE__, __func__, NULL, NULL, NULL, NULL, buffer) | |
210 | ||
211 | /* Logging with level */ | |
212 | #define log_full_errno_zerook(level, error, ...) \ | |
213 | ({ \ | |
214 | int _level = (level), _e = (error); \ | |
215 | _e = (log_get_max_level() >= LOG_PRI(_level)) \ | |
216 | ? log_internal(_level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \ | |
217 | : -ERRNO_VALUE(_e); \ | |
218 | _e < 0 ? _e : -ESTRPIPE; \ | |
219 | }) | |
220 | ||
221 | #if BUILD_MODE_DEVELOPER && !defined(TEST_CODE) | |
222 | # define ASSERT_NON_ZERO(x) assert((x) != 0) | |
223 | #else | |
224 | # define ASSERT_NON_ZERO(x) | |
225 | #endif | |
226 | ||
227 | #define log_full_errno(level, error, ...) \ | |
228 | ({ \ | |
229 | int _error = (error); \ | |
230 | ASSERT_NON_ZERO(_error); \ | |
231 | log_full_errno_zerook(level, _error, __VA_ARGS__); \ | |
232 | }) | |
233 | ||
234 | #define log_full(level, fmt, ...) \ | |
235 | ({ \ | |
236 | if (BUILD_MODE_DEVELOPER) \ | |
237 | assert(!strstr(fmt, "%m")); \ | |
238 | (void) log_full_errno_zerook(level, 0, fmt, ##__VA_ARGS__); \ | |
239 | }) | |
240 | ||
241 | int log_emergency_level(void); | |
242 | ||
243 | /* Normal logging */ | |
244 | #define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__) | |
245 | #define log_info(...) log_full(LOG_INFO, __VA_ARGS__) | |
246 | #define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__) | |
247 | #define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__) | |
248 | #define log_error(...) log_full(LOG_ERR, __VA_ARGS__) | |
249 | #define log_emergency(...) log_full(log_emergency_level(), __VA_ARGS__) | |
250 | ||
251 | /* Logging triggered by an errno-like error */ | |
252 | #define log_debug_errno(error, ...) log_full_errno(LOG_DEBUG, error, __VA_ARGS__) | |
253 | #define log_info_errno(error, ...) log_full_errno(LOG_INFO, error, __VA_ARGS__) | |
254 | #define log_notice_errno(error, ...) log_full_errno(LOG_NOTICE, error, __VA_ARGS__) | |
255 | #define log_warning_errno(error, ...) log_full_errno(LOG_WARNING, error, __VA_ARGS__) | |
256 | #define log_error_errno(error, ...) log_full_errno(LOG_ERR, error, __VA_ARGS__) | |
257 | #define log_emergency_errno(error, ...) log_full_errno(log_emergency_level(), error, __VA_ARGS__) | |
258 | ||
259 | /* This logs at the specified level the first time it is called, and then | |
260 | * logs at debug. If the specified level is debug, this logs only the first | |
261 | * time it is called. */ | |
262 | #define log_once(level, ...) \ | |
263 | ({ \ | |
264 | if (ONCE) \ | |
265 | log_full(level, __VA_ARGS__); \ | |
266 | else if (LOG_PRI(level) != LOG_DEBUG) \ | |
267 | log_debug(__VA_ARGS__); \ | |
268 | }) | |
269 | ||
270 | #define log_once_errno(level, error, ...) \ | |
271 | ({ \ | |
272 | int _err = (error); \ | |
273 | if (ONCE) \ | |
274 | _err = log_full_errno(level, _err, __VA_ARGS__); \ | |
275 | else if (LOG_PRI(level) != LOG_DEBUG) \ | |
276 | _err = log_debug_errno(_err, __VA_ARGS__); \ | |
277 | else \ | |
278 | _err = -ERRNO_VALUE(_err); \ | |
279 | _err; \ | |
280 | }) | |
281 | ||
282 | #if LOG_TRACE | |
283 | # define log_trace(...) log_debug(__VA_ARGS__) | |
284 | # define log_trace_errno(...) log_debug_errno(__VA_ARGS__) | |
285 | #else | |
286 | # define log_trace(...) do {} while (0) | |
287 | # define log_trace_errno(e, ...) (-ERRNO_VALUE(e)) | |
288 | #endif | |
289 | ||
290 | /* Structured logging */ | |
291 | #define log_struct_errno(level, error, ...) \ | |
292 | log_struct_internal(level, error, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__, NULL) | |
293 | #define log_struct(level, ...) log_struct_errno(level, 0, __VA_ARGS__) | |
294 | ||
295 | #define log_struct_iovec_errno(level, error, iovec, n_iovec) \ | |
296 | log_struct_iovec_internal(level, error, PROJECT_FILE, __LINE__, __func__, iovec, n_iovec) | |
297 | #define log_struct_iovec(level, iovec, n_iovec) log_struct_iovec_errno(level, 0, iovec, n_iovec) | |
298 | ||
299 | /* This modifies the buffer passed! */ | |
300 | #define log_dump(level, buffer) \ | |
301 | log_dump_internal(level, 0, PROJECT_FILE, __LINE__, __func__, buffer) | |
302 | ||
303 | #define log_oom_full(level) log_oom_internal(level, PROJECT_FILE, __LINE__, __func__) | |
304 | #define log_oom() log_oom_full(LOG_ERR) | |
305 | #define log_oom_debug() log_oom_full(LOG_DEBUG) | |
306 | #define log_oom_warning() log_oom_full(LOG_WARNING) | |
307 | ||
308 | bool log_on_console(void) _pure_; | |
309 | ||
310 | /* Helper to wrap the main message in structured logging. The macro doesn't do much, | |
311 | * except to provide visual grouping of the format string and its arguments. */ | |
312 | #if LOG_MESSAGE_VERIFICATION || defined(__COVERITY__) | |
313 | /* Do a fake formatting of the message string to let the scanner verify the arguments against the format | |
314 | * message. The variable will never be set to true, but we don't tell the compiler that :) */ | |
315 | extern bool _log_message_dummy; | |
316 | # define LOG_MESSAGE(fmt, ...) "MESSAGE=%.0d" fmt, (_log_message_dummy && printf(fmt, ##__VA_ARGS__)), ##__VA_ARGS__ | |
317 | #else | |
318 | # define LOG_MESSAGE(fmt, ...) "MESSAGE=" fmt, ##__VA_ARGS__ | |
319 | #endif | |
320 | ||
321 | void log_received_signal(int level, const struct signalfd_siginfo *si); | |
322 | ||
323 | /* If turned on, any requests for a log target involving "syslog" will be implicitly upgraded to the equivalent journal target */ | |
324 | void log_set_upgrade_syslog_to_journal(bool b); | |
325 | ||
326 | /* If turned on, and log_open() is called, we'll not use STDERR_FILENO for logging ever, but rather open /dev/console */ | |
327 | void log_set_always_reopen_console(bool b); | |
328 | ||
329 | /* If turned on, we'll open the log stream implicitly if needed on each individual log call. This is normally not | |
330 | * desired as we want to reuse our logging streams. It is useful however */ | |
331 | void log_set_open_when_needed(bool b); | |
332 | ||
333 | /* If turned on, then we'll never use IPC-based logging, i.e. never log to syslog or the journal. We'll only log to | |
334 | * stderr, the console or kmsg */ | |
335 | void log_set_prohibit_ipc(bool b); | |
336 | ||
337 | void log_set_assert_return_is_critical(bool b); | |
338 | bool log_get_assert_return_is_critical(void) _pure_; | |
339 | ||
340 | int log_dup_console(void); | |
341 | ||
342 | int log_syntax_internal( | |
343 | const char *unit, | |
344 | int level, | |
345 | const char *config_file, | |
346 | unsigned config_line, | |
347 | int error, | |
348 | const char *file, | |
349 | int line, | |
350 | const char *func, | |
351 | const char *format, ...) _printf_(9, 10); | |
352 | ||
353 | int log_syntax_invalid_utf8_internal( | |
354 | const char *unit, | |
355 | int level, | |
356 | const char *config_file, | |
357 | unsigned config_line, | |
358 | const char *file, | |
359 | int line, | |
360 | const char *func, | |
361 | const char *rvalue); | |
362 | ||
363 | int log_syntax_parse_error_internal( | |
364 | const char *unit, | |
365 | const char *config_file, | |
366 | unsigned config_line, | |
367 | int error, | |
368 | bool critical, /* When true, propagate the passed error, otherwise this always returns 0. */ | |
369 | const char *file, | |
370 | int line, | |
371 | const char *func, | |
372 | const char *lvalue, | |
373 | const char *rvalue); | |
374 | ||
375 | #define log_syntax(unit, level, config_file, config_line, error, ...) \ | |
376 | ({ \ | |
377 | int _level = (level), _e = (error); \ | |
378 | (log_get_max_level() >= LOG_PRI(_level)) \ | |
379 | ? log_syntax_internal(unit, _level, config_file, config_line, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \ | |
380 | : -ERRNO_VALUE(_e); \ | |
381 | }) | |
382 | ||
383 | #define log_syntax_invalid_utf8(unit, level, config_file, config_line, rvalue) \ | |
384 | ({ \ | |
385 | int _level = (level); \ | |
386 | (log_get_max_level() >= LOG_PRI(_level)) \ | |
387 | ? log_syntax_invalid_utf8_internal(unit, _level, config_file, config_line, PROJECT_FILE, __LINE__, __func__, rvalue) \ | |
388 | : -EINVAL; \ | |
389 | }) | |
390 | ||
391 | #define log_syntax_parse_error_full(unit, config_file, config_line, error, critical, lvalue, rvalue) \ | |
392 | log_syntax_parse_error_internal(unit, config_file, config_line, error, critical, PROJECT_FILE, __LINE__, __func__, lvalue, rvalue) | |
393 | ||
394 | #define log_syntax_parse_error(unit, config_file, config_line, error, lvalue, rvalue) \ | |
395 | log_syntax_parse_error_full(unit, config_file, config_line, error, /* critical = */ false, lvalue, rvalue) | |
396 | ||
397 | #define DEBUG_LOGGING _unlikely_(log_get_max_level() >= LOG_DEBUG) | |
398 | ||
399 | void log_setup(void); | |
400 | ||
401 | typedef struct LogRateLimit { | |
402 | int error; | |
403 | int level; | |
404 | RateLimit ratelimit; | |
405 | } LogRateLimit; | |
406 | ||
407 | #define log_ratelimit_internal(_level, _error, _ratelimit, _file, _line, _func, _format, ...) \ | |
408 | ({ \ | |
409 | int _log_ratelimit_error = (_error); \ | |
410 | int _log_ratelimit_level = (_level); \ | |
411 | static LogRateLimit _log_ratelimit = { \ | |
412 | .ratelimit = (_ratelimit), \ | |
413 | }; \ | |
414 | unsigned _num_dropped_errors = ratelimit_num_dropped(&_log_ratelimit.ratelimit); \ | |
415 | if (_log_ratelimit_error != _log_ratelimit.error || _log_ratelimit_level != _log_ratelimit.level) { \ | |
416 | ratelimit_reset(&_log_ratelimit.ratelimit); \ | |
417 | _log_ratelimit.error = _log_ratelimit_error; \ | |
418 | _log_ratelimit.level = _log_ratelimit_level; \ | |
419 | } \ | |
420 | if (log_get_max_level() == LOG_DEBUG || ratelimit_below(&_log_ratelimit.ratelimit)) \ | |
421 | _log_ratelimit_error = _num_dropped_errors > 0 \ | |
422 | ? log_internal(_log_ratelimit_level, _log_ratelimit_error, _file, _line, _func, _format " (Dropped %u similar message(s))", ##__VA_ARGS__, _num_dropped_errors) \ | |
423 | : log_internal(_log_ratelimit_level, _log_ratelimit_error, _file, _line, _func, _format, ##__VA_ARGS__); \ | |
424 | _log_ratelimit_error; \ | |
425 | }) | |
426 | ||
427 | #define log_ratelimit_full_errno(level, error, _ratelimit, format, ...) \ | |
428 | ({ \ | |
429 | int _level = (level), _e = (error); \ | |
430 | _e = (log_get_max_level() >= LOG_PRI(_level)) \ | |
431 | ? log_ratelimit_internal(_level, _e, _ratelimit, PROJECT_FILE, __LINE__, __func__, format, ##__VA_ARGS__) \ | |
432 | : -ERRNO_VALUE(_e); \ | |
433 | _e < 0 ? _e : -ESTRPIPE; \ | |
434 | }) | |
435 | ||
436 | #define log_ratelimit_full(level, _ratelimit, format, ...) \ | |
437 | log_ratelimit_full_errno(level, 0, _ratelimit, format, ##__VA_ARGS__) | |
438 | ||
439 | /* Normal logging */ | |
440 | #define log_ratelimit_info(...) log_ratelimit_full(LOG_INFO, __VA_ARGS__) | |
441 | #define log_ratelimit_notice(...) log_ratelimit_full(LOG_NOTICE, __VA_ARGS__) | |
442 | #define log_ratelimit_warning(...) log_ratelimit_full(LOG_WARNING, __VA_ARGS__) | |
443 | #define log_ratelimit_error(...) log_ratelimit_full(LOG_ERR, __VA_ARGS__) | |
444 | #define log_ratelimit_emergency(...) log_ratelimit_full(log_emergency_level(), __VA_ARGS__) | |
445 | ||
446 | /* Logging triggered by an errno-like error */ | |
447 | #define log_ratelimit_info_errno(error, ...) log_ratelimit_full_errno(LOG_INFO, error, __VA_ARGS__) | |
448 | #define log_ratelimit_notice_errno(error, ...) log_ratelimit_full_errno(LOG_NOTICE, error, __VA_ARGS__) | |
449 | #define log_ratelimit_warning_errno(error, ...) log_ratelimit_full_errno(LOG_WARNING, error, __VA_ARGS__) | |
450 | #define log_ratelimit_error_errno(error, ...) log_ratelimit_full_errno(LOG_ERR, error, __VA_ARGS__) | |
451 | #define log_ratelimit_emergency_errno(error, ...) log_ratelimit_full_errno(log_emergency_level(), error, __VA_ARGS__) | |
452 | ||
453 | const char* _log_set_prefix(const char *prefix, bool force); | |
454 | static inline const char* _log_unset_prefixp(const char **p) { | |
455 | assert(p); | |
456 | _log_set_prefix(*p, true); | |
457 | return NULL; | |
458 | } | |
459 | ||
460 | #define LOG_SET_PREFIX(prefix) \ | |
461 | _cleanup_(_log_unset_prefixp) _unused_ const char *CONCATENATE(_cleanup_log_unset_prefix_, UNIQ) = _log_set_prefix(prefix, false); | |
462 | ||
463 | /* | |
464 | * The log context allows attaching extra metadata to log messages written to the journal via log.h. We keep | |
465 | * track of a thread local log context onto which we can push extra metadata fields that should be logged. | |
466 | * | |
467 | * LOG_CONTEXT_PUSH() will add the provided field to the log context and will remove it again when the | |
468 | * current block ends. LOG_CONTEXT_PUSH_STRV() will do the same but for all fields in the given strv. | |
469 | * LOG_CONTEXT_PUSHF() is like LOG_CONTEXT_PUSH() but takes a format string and arguments. | |
470 | * | |
471 | * Using the macros is as simple as putting them anywhere inside a block to add a field to all following log | |
472 | * messages logged from inside that block. | |
473 | * | |
474 | * void myfunction(...) { | |
475 | * ... | |
476 | * | |
477 | * LOG_CONTEXT_PUSHF("MYMETADATA=%s", "abc"); | |
478 | * | |
479 | * // Every journal message logged will now have the MYMETADATA=abc | |
480 | * // field included. | |
481 | * } | |
482 | * | |
483 | * One special case to note is async code, where we use callbacks that are invoked to continue processing | |
484 | * when some event occurs. For async code, there's usually an associated "userdata" struct containing all the | |
485 | * information associated with the async operation. In this "userdata" struct, we can store a log context | |
486 | * allocated with log_context_new() and freed with log_context_free(). We can then add and remove fields to | |
487 | * the `fields` member of the log context object and all those fields will be logged along with each log | |
488 | * message. | |
489 | */ | |
490 | ||
491 | typedef struct LogContext LogContext; | |
492 | ||
493 | bool log_context_enabled(void); | |
494 | ||
495 | LogContext* log_context_new(const char *key, const char *value); | |
496 | LogContext* log_context_new_strv(char **fields, bool owned); | |
497 | LogContext* log_context_new_iov(struct iovec *input_iovec, size_t n_input_iovec, bool owned); | |
498 | ||
499 | /* Same as log_context_new(), but frees the given fields strv/iovec on failure. */ | |
500 | LogContext* log_context_new_strv_consume(char **fields); | |
501 | LogContext* log_context_new_iov_consume(struct iovec *input_iovec, size_t n_input_iovec); | |
502 | ||
503 | LogContext *log_context_ref(LogContext *c); | |
504 | LogContext *log_context_unref(LogContext *c); | |
505 | ||
506 | DEFINE_TRIVIAL_CLEANUP_FUNC(LogContext*, log_context_unref); | |
507 | ||
508 | /* Returns the number of attached log context objects. */ | |
509 | size_t log_context_num_contexts(void); | |
510 | /* Returns the number of fields in all attached log contexts. */ | |
511 | size_t log_context_num_fields(void); | |
512 | ||
513 | static inline void _reset_log_level(int *saved_log_level) { | |
514 | assert(saved_log_level); | |
515 | ||
516 | log_set_max_level(*saved_log_level); | |
517 | } | |
518 | ||
519 | #define LOG_CONTEXT_SET_LOG_LEVEL(level) \ | |
520 | _cleanup_(_reset_log_level) _unused_ int _saved_log_level_ = log_set_max_level(level); | |
521 | ||
522 | #define LOG_CONTEXT_PUSH(...) \ | |
523 | LOG_CONTEXT_PUSH_STRV(STRV_MAKE(__VA_ARGS__)) | |
524 | ||
525 | #define LOG_CONTEXT_PUSHF(...) \ | |
526 | LOG_CONTEXT_PUSH(snprintf_ok((char[LINE_MAX]) {}, LINE_MAX, __VA_ARGS__)) | |
527 | ||
528 | #define _LOG_CONTEXT_PUSH_KEY_VALUE(key, value, c) \ | |
529 | _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new(key, value); | |
530 | ||
531 | #define LOG_CONTEXT_PUSH_KEY_VALUE(key, value) \ | |
532 | _LOG_CONTEXT_PUSH_KEY_VALUE(key, value, UNIQ_T(c, UNIQ)) | |
533 | ||
534 | #define _LOG_CONTEXT_PUSH_STRV(strv, c) \ | |
535 | _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_strv(strv, /*owned=*/ false); | |
536 | ||
537 | #define LOG_CONTEXT_PUSH_STRV(strv) \ | |
538 | _LOG_CONTEXT_PUSH_STRV(strv, UNIQ_T(c, UNIQ)) | |
539 | ||
540 | #define _LOG_CONTEXT_PUSH_IOV(input_iovec, n_input_iovec, c) \ | |
541 | _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_iov(input_iovec, n_input_iovec, /*owned=*/ false); | |
542 | ||
543 | #define LOG_CONTEXT_PUSH_IOV(input_iovec, n_input_iovec) \ | |
544 | _LOG_CONTEXT_PUSH_IOV(input_iovec, n_input_iovec, UNIQ_T(c, UNIQ)) | |
545 | ||
546 | /* LOG_CONTEXT_CONSUME_STR()/LOG_CONTEXT_CONSUME_STRV()/LOG_CONTEXT_CONSUME_IOV() are identical to | |
547 | * LOG_CONTEXT_PUSH_STR()/LOG_CONTEXT_PUSH_STRV()/LOG_CONTEXT_PUSH_IOV() except they take ownership of the | |
548 | * given str/strv argument. | |
549 | */ | |
550 | ||
551 | #define _LOG_CONTEXT_CONSUME_STR(s, c, strv) \ | |
552 | _unused_ _cleanup_strv_free_ strv = strv_new(s); \ | |
553 | if (!strv) \ | |
554 | free(s); \ | |
555 | _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_strv_consume(TAKE_PTR(strv)) | |
556 | ||
557 | #define LOG_CONTEXT_CONSUME_STR(s) \ | |
558 | _LOG_CONTEXT_CONSUME_STR(s, UNIQ_T(c, UNIQ), UNIQ_T(sv, UNIQ)) | |
559 | ||
560 | #define _LOG_CONTEXT_CONSUME_STRV(strv, c) \ | |
561 | _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_strv_consume(strv); | |
562 | ||
563 | #define LOG_CONTEXT_CONSUME_STRV(strv) \ | |
564 | _LOG_CONTEXT_CONSUME_STRV(strv, UNIQ_T(c, UNIQ)) | |
565 | ||
566 | #define _LOG_CONTEXT_CONSUME_IOV(input_iovec, n_input_iovec, c) \ | |
567 | _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_iov_consume(input_iovec, n_input_iovec); | |
568 | ||
569 | #define LOG_CONTEXT_CONSUME_IOV(input_iovec, n_input_iovec) \ | |
570 | _LOG_CONTEXT_CONSUME_IOV(input_iovec, n_input_iovec, UNIQ_T(c, UNIQ)) |