Monado OpenXR Runtime
u_logging.h
Go to the documentation of this file.
1// Copyright 2020-2025, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Basic logging functionality.
6 * @author Jakob Bornecrantz <jakob@collabora.com>
7 * @author Simon Zeni <simon.zeni@collabora.com>
8 * @ingroup aux_log
9 */
10
11
12#pragma once
13
14#include "xrt/xrt_compiler.h"
15#include "xrt/xrt_results.h"
16
17#include "util/u_pretty_print.h"
18
19#include <stdarg.h>
20
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26
27struct xrt_device;
28
29
30/*!
31 * @defgroup aux_log Logging functions
32 * @ingroup aux_util
33 */
34
35/*!
36 * @addtogroup aux_log
37 * @{
38 */
39
40/*!
41 * @brief Logging level enum
42 */
44{
45 U_LOGGING_TRACE, //!< Trace messages, highly verbose.
46 U_LOGGING_DEBUG, //!< Debug messages, verbose.
47 U_LOGGING_INFO, //!< Info messages: not very verbose, not indicating a problem.
48 U_LOGGING_WARN, //!< Warning messages: indicating a potential problem
49 U_LOGGING_ERROR, //!< Error messages: indicating a problem
50 U_LOGGING_RAW, //!< Special level for raw printing, prints a new-line.
51};
52
53/*!
54 * Function typedef for setting the logging sink.
55 *
56 * @param file Source file name associated with a message.
57 * @param line Source file line associated with a message.
58 * @param func Function name associated with a message.
59 * @param level Message level: used for formatting or forwarding to native log functions.
60 * @param format Format string.
61 * @param args Format parameters.
62 * @param data User data.
63 */
64typedef void (*u_log_sink_func_t)(const char *file,
65 int line,
66 const char *func,
67 enum u_logging_level level,
68 const char *format,
69 va_list args,
70 void *data);
71
72/*!
73 * For places where you really want printf, prints a new-line.
74 */
75#define U_LOG_RAW(...) \
76 do { \
77 u_log(__FILE__, __LINE__, __func__, U_LOGGING_RAW, __VA_ARGS__); \
78 } while (false)
79
80/*!
81 * @name Base Logging Utilities
82 * In most cases, you will want to use another macro from this file, or a module/driver-local macro, to do your logging.
83 * @{
84 */
85/*!
86 * @brief Log a message at @p level , with file, line, and function context (always logs) - typically wrapped
87 * in a helper macro.
88 *
89 * @param level A @ref u_logging_level value for this message.
90 * @param ... Format string and optional format arguments.
91 */
92#define U_LOG(level, ...) \
93 do { \
94 u_log(__FILE__, __LINE__, __func__, level, __VA_ARGS__); \
95 } while (false)
96
97/*!
98 * @brief Log at @p level only if the level is at least @p cond_level - typically wrapped in a helper macro.
99 *
100 * Adds file, line, and function context. Like U_LOG() but conditional.
101 *
102 * @param level A @ref u_logging_level value for this message.
103 * @param cond_level The minimum @ref u_logging_level that will be actually output.
104 * @param ... Format string and optional format arguments.
105 */
106#define U_LOG_IFL(level, cond_level, ...) \
107 do { \
108 if (cond_level <= level) { \
109 u_log(__FILE__, __LINE__, __func__, level, __VA_ARGS__); \
110 } \
111 } while (false)
112/*!
113 * @brief Log at @p level for a given @ref xrt_device - typically wrapped in a helper macro.
114 *
115 * Adds file, line, and function context, and forwards device context from provided @p xdev .
116 *
117 * Like U_LOG() but calling u_log_xdev() (which takes a device) instead.
118 *
119 * @param level A @ref u_logging_level value for this message.
120 * @param xdev The @ref xrt_device pointer associated with this message.
121 * @param ... Format string and optional format arguments.
122 */
123#define U_LOG_XDEV(level, xdev, ...) \
124 do { \
125 u_log_xdev(__FILE__, __LINE__, __func__, level, xdev, __VA_ARGS__); \
126 } while (false)
127/*!
128 * @brief Log at @p level for a given @ref xrt_device, only if the level is at least @p cond_level - typically wrapped
129 * in a helper macro.
130 *
131 * Adds file, line, and function context, and forwards device context from provided @p xdev .
132 * @param level A @ref u_logging_level value for this message.
133 * @param cond_level The minimum @ref u_logging_level that will be actually output.
134 * @param xdev The @ref xrt_device pointer associated with this message.
135 * @param ... Format string and optional format arguments.
136 */
137#define U_LOG_XDEV_IFL(level, cond_level, xdev, ...) \
138 do { \
139 if (cond_level <= level) { \
140 u_log_xdev(__FILE__, __LINE__, __func__, level, xdev, __VA_ARGS__); \
141 } \
142 } while (false)
143
144/*!
145 * @brief Log a memory hexdump at @p level only if the level is at least @p cond_level - typically wrapped in a helper
146 * macro.
147 *
148 * Adds file, line, and function context. Like U_LOG_IFL()
149 *
150 * @param level A @ref u_logging_level value for this message.
151 * @param cond_level The minimum @ref u_logging_level that will be actually output.
152 * @param data The data to print in hexdump format
153 * @param data_size The size (in bytes) of the data block
154 */
155#define U_LOG_IFL_HEX(level, cond_level, data, data_size) \
156 do { \
157 if (cond_level <= level) { \
158 u_log_hex(__FILE__, __LINE__, __func__, level, data, data_size); \
159 } \
160 } while (false)
161
162/*!
163 * @brief Log a memory hexdump at @p level for a given @ref xrt_device, only if the level is at least @p cond_level -
164 * typically wrapped in a helper macro.
165 *
166 * Adds file, line, and function context, and forwards device context from provided @p xdev .
167 * @param level A @ref u_logging_level value for this message.
168 * @param cond_level The minimum @ref u_logging_level that will be actually output.
169 * @param xdev The @ref xrt_device pointer associated with this message.
170 * @param data The data to print in hexdump format
171 * @param data_size The size (in bytes) of the data block
172 */
173#define U_LOG_XDEV_IFL_HEX(level, cond_level, xdev, data, data_size) \
174 do { \
175 if (cond_level <= level) { \
176 u_log_xdev_hex(__FILE__, __LINE__, __func__, level, xdev, data, data_size); \
177 } \
178 } while (false)
179
180/*!
181 * This define will error if `XRET` is not `XRT_SUCCESS`, printing out that the
182 * @p FUNC_STR string has failed, then returns @p XRET.
183 *
184 * @param COND_LEVEL Log level used for @p cond_level, in logging helpers.
185 * @param XRET The @p xrt_result_t to check.
186 * @param FUNC_STR String literal with the function name, used for logging.
187 */
188#define U_LOG_CHK_AND_RET(COND_LEVEL, XRET, FUNC_STR) \
189 do { \
190 xrt_result_t _ret = XRET; \
191 if (_ret != XRT_SUCCESS) { \
192 u_log_print_result(COND_LEVEL, __FILE__, __LINE__, __func__, _ret, FUNC_STR); \
193 return _ret; \
194 } \
195 } while (false)
196
197/*!
198 * This define will error if `XRET` is not `XRT_SUCCESS`, printing out that the
199 * @p FUNC_STR string has failed, then gotos @p GOTO.
200 *
201 * @param COND_LEVEL Log level used for @p cond_level, in logging helpers.
202 * @param XRET The @p xrt_result_t to check.
203 * @param FUNC_STR String literal with the function name, used for logging.
204 * @param GOTO Goto label to jump to on error.
205 */
206#define U_LOG_CHK_WITH_GOTO(COND_LEVEL, XRET, FUNC_STR, GOTO) \
207 do { \
208 xrt_result_t _ret = XRET; \
209 if (_ret != XRT_SUCCESS) { \
210 u_log_print_result(COND_LEVEL, __FILE__, __LINE__, __func__, _ret, FUNC_STR); \
211 goto GOTO; \
212 } \
213 } while (false)
214
215/*!
216 * This define will error if `XRET` is not `XRT_SUCCESS`, printing out that the
217 * @p FUNC_STR string has failed, then returns @p RET.
218 *
219 * @param COND_LEVEL Log level used for @p cond_level, in logging helpers.
220 * @param XRET The @p xrt_result_t to check.
221 * @param FUNC_STR String literal with the function name, used for logging.
222 * @param RET The value that is returned on error.
223 */
224#define U_LOG_CHK_WITH_RET(COND_LEVEL, XRET, FUNC_STR, RET) \
225 do { \
226 xrt_result_t _ret = XRET; \
227 if (_ret != XRT_SUCCESS) { \
228 u_log_print_result(COND_LEVEL, __FILE__, __LINE__, __func__, _ret, FUNC_STR); \
229 return RET; \
230 } \
231 } while (false)
232
233/*!
234 * This define will error if `XRET` is not `XRT_SUCCESS`, printing out that the
235 * @p FUNC_STR string has failed, it only prints and does nothing else.
236 *
237 * @param COND_LEVEL Log level used for @p cond_level, in logging helpers.
238 * @param XRET The @p xrt_result_t to check.
239 * @param FUNC_STR String literal with the function name, used for logging.
240 */
241#define U_LOG_CHK_ONLY_PRINT(COND_LEVEL, XRET, FUNC_STR) \
242 do { \
243 xrt_result_t _ret = XRET; \
244 if (_ret != XRT_SUCCESS) { \
245 u_log_print_result(COND_LEVEL, __FILE__, __LINE__, __func__, _ret, FUNC_STR); \
246 } \
247 } while (false)
248
249/*!
250 * This define will error if `XRET` is not `XRT_SUCCESS`, printing out that the
251 * @p FUNC_STR string has failed, then it will always return the value.
252 *
253 * @param COND_LEVEL Log level used for @p cond_level, in logging helpers.
254 * @param XRET The @p xrt_result_t to check and always return.
255 * @param FUNC_STR String literal with the function name, used for logging.
256 */
257#define U_LOG_CHK_ALWAYS_RET(COND_LEVEL, XRET, FUNC_STR) \
258 do { \
259 xrt_result_t _ret = XRET; \
260 if (_ret != XRT_SUCCESS) { \
261 u_log_print_result(COND_LEVEL, __FILE__, __LINE__, __func__, _ret, FUNC_STR); \
262 } \
263 return _ret; \
264 } while (false)
265
266/*!
267 * Returns the global logging level, subsystems own logging level take precedence.
268 */
271
272/*!
273 * @brief Main non-device-related log implementation function: do not call directly, use a macro that wraps it.
274 *
275 * This function always logs: level is used for printing or passed to native logging functions.
276 *
277 * @param file Source file name associated with a message
278 * @param line Source file line associated with a message
279 * @param func Function name associated with a message
280 * @param level Message level: used for formatting or forwarding to native log functions
281 * @param format Format string
282 * @param ... Format parameters
283 */
284void
285u_log(const char *file, int line, const char *func, enum u_logging_level level, const char *format, ...)
286 XRT_PRINTF_FORMAT(5, 6);
287
288/*!
289 * @brief Main device-related log implementation function: do not call directly, use a macro that wraps it.
290 *
291 * This function always logs: level is used for printing or passed to native logging functions.
292 * @param file Source file name associated with a message
293 * @param line Source file line associated with a message
294 * @param func Function name associated with a message
295 * @param level Message level: used for formatting or forwarding to native log functions
296 * @param xdev The associated @ref xrt_device
297 * @param format Format string
298 * @param ... Format parameters
299 */
300void
301u_log_xdev(const char *file,
302 int line,
303 const char *func,
304 enum u_logging_level level,
305 struct xrt_device *xdev,
306 const char *format,
307 ...) XRT_PRINTF_FORMAT(6, 7);
308
309/*!
310 * @brief Log implementation for dumping memory buffers as hex: do not call directly, use a macro that wraps it.
311 *
312 * This function always logs: level is used for printing or passed to native logging functions.
313 *
314 * @param file Source file name associated with a message
315 * @param line Source file line associated with a message
316 * @param func Function name associated with a message
317 * @param level Message level: used for formatting or forwarding to native log functions
318 * @param data Data buffer to dump
319 * @param data_size Size of the data buffer in bytes
320 */
321void
322u_log_hex(const char *file,
323 int line,
324 const char *func,
325 enum u_logging_level level,
326 const uint8_t *data,
327 const size_t data_size);
328
329/*!
330 * @brief Device-related log implementation for dumping memory buffers as hex: do not call directly, use a macro that
331 * wraps it.
332 *
333 * This function always logs: level is used for printing or passed to native logging functions.
334 * @param file Source file name associated with a message
335 * @param line Source file line associated with a message
336 * @param func Function name associated with a message
337 * @param level Message level: used for formatting or forwarding to native log functions
338 * @param xdev The associated @ref xrt_device
339 * @param data Data buffer to dump
340 * @param data_size Size of the data buffer in bytes
341 */
342void
343u_log_xdev_hex(const char *file,
344 int line,
345 const char *func,
346 enum u_logging_level level,
347 struct xrt_device *xdev,
348 const uint8_t *data,
349 const size_t data_size);
350
351/*!
352 * Sets the logging sink, log is still passed on to the platform defined output
353 * as well as the sink.
354 *
355 * @param func Logging function for the calls to be sent to.
356 * @param data User data to be passed into @p func.
357 */
358void
359u_log_set_sink(u_log_sink_func_t func, void *data);
360
361/*!
362 * Helper to print the results of called functions that return xret results, if
363 * the result is @p XRT_SUCCESS will log with info, otherwise error. Will also
364 * check if logging should be done with @p cond_level.
365 *
366 * @param cond_level What the current logging level is.
367 * @param file Callee site (__FILE__).
368 * @param line Callee site (__LINE__).
369 * @param calling_fn Callee site (__func__).
370 * @param xret Result from the called function.
371 * @param called_fn Which function that this return is from.
372 */
373void
374u_log_print_result(enum u_logging_level cond_level,
375 const char *file,
376 int line,
377 const char *calling_fn,
378 xrt_result_t xret,
379 const char *called_fn);
380
381/*!
382 * @}
383 */
384
385
386/*!
387 * @name Logging macros conditional on global log level
388 *
389 * These each imply a log level, and will only log if the global log level is equal or lower.
390 * They are often used for one-off logging in a module with few other logging needs,
391 * where having a module-specific log level would be unnecessary.
392 *
393 * @see U_LOG_IFL, u_log_get_global_level()
394 * @param ... Format string and optional format arguments.
395 * @{
396 */
397//! Log a message at U_LOGGING_TRACE level, conditional on the global log level
398#define U_LOG_T(...) U_LOG_IFL_T(u_log_get_global_level(), __VA_ARGS__)
399
400//! Log a message at U_LOGGING_DEBUG level, conditional on the global log level
401#define U_LOG_D(...) U_LOG_IFL_D(u_log_get_global_level(), __VA_ARGS__)
402
403//! Log a message at U_LOGGING_INFO level, conditional on the global log level
404#define U_LOG_I(...) U_LOG_IFL_I(u_log_get_global_level(), __VA_ARGS__)
405
406//! Log a message at U_LOGGING_WARN level, conditional on the global log level
407#define U_LOG_W(...) U_LOG_IFL_W(u_log_get_global_level(), __VA_ARGS__)
408
409//! Log a message at U_LOGGING_ERROR level, conditional on the global log level
410#define U_LOG_E(...) U_LOG_IFL_E(u_log_get_global_level(), __VA_ARGS__)
411
412/*!
413 * @}
414 */
415
416/*!
417 * @name Logging macros conditional on provided log level
418 *
419 * These are often wrapped within a module, to automatically supply
420 * @p cond_level as appropriate for that module.
421 *
422 * @see U_LOG_IFL
423 * @param cond_level The minimum @ref u_logging_level that will be actually output.
424 * @param ... Format string and optional format arguments.
425 *
426 * @{
427 */
428//! Conditionally log a message at U_LOGGING_TRACE level.
429#define U_LOG_IFL_T(cond_level, ...) U_LOG_IFL(U_LOGGING_TRACE, cond_level, __VA_ARGS__)
430//! Conditionally log a message at U_LOGGING_DEBUG level.
431#define U_LOG_IFL_D(cond_level, ...) U_LOG_IFL(U_LOGGING_DEBUG, cond_level, __VA_ARGS__)
432//! Conditionally log a message at U_LOGGING_INFO level.
433#define U_LOG_IFL_I(cond_level, ...) U_LOG_IFL(U_LOGGING_INFO, cond_level, __VA_ARGS__)
434//! Conditionally log a message at U_LOGGING_WARN level.
435#define U_LOG_IFL_W(cond_level, ...) U_LOG_IFL(U_LOGGING_WARN, cond_level, __VA_ARGS__)
436//! Conditionally log a message at U_LOGGING_ERROR level.
437#define U_LOG_IFL_E(cond_level, ...) U_LOG_IFL(U_LOGGING_ERROR, cond_level, __VA_ARGS__)
438
439//! Conditionally log a memory hexdump at U_LOGGING_TRACE level.
440#define U_LOG_IFL_T_HEX(cond_level, data, data_size) U_LOG_IFL_HEX(U_LOGGING_TRACE, cond_level, data, data_size)
441//! Conditionally log a memory hexdump at U_LOGGING_DEBUG level.
442#define U_LOG_IFL_D_HEX(cond_level, data, data_size) U_LOG_IFL_HEX(U_LOGGING_DEBUG, cond_level, data, data_size)
443/*!
444 * @}
445 */
446
447
448
449/*!
450 * @name Device-related logging macros conditional on provided log level
451 *
452 * These are often wrapped within a driver, to automatically supply @p xdev and
453 * @p cond_level from their conventional names and log level member variable.
454 *
455 * @param level A @ref u_logging_level value for this message.
456 * @param cond_level The minimum @ref u_logging_level that will be actually output.
457 * @param xdev The @ref xrt_device pointer associated with this message.
458 * @param ... Format string and optional format arguments.
459 *
460 * @{
461 */
462//! Conditionally log a device-related message at U_LOGGING_TRACE level.
463#define U_LOG_XDEV_IFL_T(xdev, cond_level, ...) U_LOG_XDEV_IFL(U_LOGGING_TRACE, cond_level, xdev, __VA_ARGS__)
464//! Conditionally log a device-related message at U_LOGGING_DEBUG level.
465#define U_LOG_XDEV_IFL_D(xdev, cond_level, ...) U_LOG_XDEV_IFL(U_LOGGING_DEBUG, cond_level, xdev, __VA_ARGS__)
466//! Conditionally log a device-related message at U_LOGGING_INFO level.
467#define U_LOG_XDEV_IFL_I(xdev, cond_level, ...) U_LOG_XDEV_IFL(U_LOGGING_INFO, cond_level, xdev, __VA_ARGS__)
468//! Conditionally log a device-related message at U_LOGGING_WARN level.
469#define U_LOG_XDEV_IFL_W(xdev, cond_level, ...) U_LOG_XDEV_IFL(U_LOGGING_WARN, cond_level, xdev, __VA_ARGS__)
470//! Conditionally log a device-related message at U_LOGGING_ERROR level.
471#define U_LOG_XDEV_IFL_E(xdev, cond_level, ...) U_LOG_XDEV_IFL(U_LOGGING_ERROR, cond_level, xdev, __VA_ARGS__)
472
473//! Conditionally log a device-related memory hexdump at U_LOGGING_TRACE level.
474#define U_LOG_XDEV_IFL_T_HEX(xdev, cond_level, data, data_size) \
475 U_LOG_XDEV_IFL_HEX(U_LOGGING_TRACE, cond_level, xdev, data, data_size)
476//! Conditionally log a device-related memory hexdump message at U_LOGGING_DEBUG level.
477#define U_LOG_XDEV_IFL_D_HEX(xdev, cond_level, data, data_size) \
478 U_LOG_XDEV_IFL_HEX(U_LOGGING_DEBUG, cond_level, xdev, data, data_size)
479/*!
480 * @}
481 */
482
483/*!
484 * @name Device-related error logging macros
485 *
486 * These are printed from a driver at error level.
487 *
488 * @param xdev The @ref xrt_device pointer associated with this message
489 *
490 * @{
491 */
492#define U_LOG_XDEV_UNSUPPORTED_INPUT(xdev, cond_level, name) \
493 do { \
494 struct u_pp_sink_stack_only sink; \
495 u_pp_delegate_t dg = u_pp_sink_stack_only_init(&sink); \
496 u_pp_xrt_input_name(dg, name); \
497 U_LOG_XDEV_IFL_E(xdev, cond_level, "Unsupported input: %s", sink.buffer); \
498 } while (false);
499
500/*!
501 * @}
502 */
503
504/*!
505 * @name Device-related logging macros that always log.
506 *
507 * These wrap U_LOG_XDEV() to supply the @p level - which is only used for formatting the output, these macros always
508 * log regardless of level.
509 *
510 * @param xdev The @ref xrt_device pointer associated with this message.
511 * @param ... Format string and optional format arguments.
512 * @{
513 */
514//! Log a device-related message at U_LOGGING_TRACE level (always logs).
515#define U_LOG_XDEV_T(xdev, ...) U_LOG_XDEV(U_LOGGING_TRACE, xdev, __VA_ARGS__)
516//! Log a device-related message at U_LOGGING_DEBUG level (always logs).
517#define U_LOG_XDEV_D(xdev, ...) U_LOG_XDEV(U_LOGGING_DEBUG, xdev, __VA_ARGS__)
518//! Log a device-related message at U_LOGGING_INFO level (always logs).
519#define U_LOG_XDEV_I(xdev, ...) U_LOG_XDEV(U_LOGGING_INFO, xdev, __VA_ARGS__)
520//! Log a device-related message at U_LOGGING_WARN level (always logs).
521#define U_LOG_XDEV_W(xdev, ...) U_LOG_XDEV(U_LOGGING_WARN, xdev, __VA_ARGS__)
522//! Log a device-related message at U_LOGGING_ERROR level (always logs).
523#define U_LOG_XDEV_E(xdev, ...) U_LOG_XDEV(U_LOGGING_ERROR, xdev, __VA_ARGS__)
524/*!
525 * @}
526 */
527
528/*!
529 * @}
530 */
531
532
533#ifdef __cplusplus
534}
535#endif
u_logging_level
Logging level enum.
Definition: u_logging.h:44
void u_log(const char *file, int line, const char *func, enum u_logging_level level, const char *format,...) XRT_PRINTF_FORMAT(5
Main non-device-related log implementation function: do not call directly, use a macro that wraps it.
enum u_logging_level u_log_get_global_level(void)
Returns the global logging level, subsystems own logging level take precedence.
Definition: u_logging.c:69
void u_log_print_result(enum u_logging_level cond_level, const char *file, int line, const char *calling_fn, xrt_result_t xret, const char *called_fn)
Helper to print the results of called functions that return xret results, if the result is XRT_SUCCES...
Definition: u_logging.c:427
void(* u_log_sink_func_t)(const char *file, int line, const char *func, enum u_logging_level level, const char *format, va_list args, void *data)
Function typedef for setting the logging sink.
Definition: u_logging.h:64
void void void u_log_hex(const char *file, int line, const char *func, enum u_logging_level level, const uint8_t *data, const size_t data_size)
Log implementation for dumping memory buffers as hex: do not call directly, use a macro that wraps it...
Definition: u_logging.c:142
void void u_log_xdev(const char *file, int line, const char *func, enum u_logging_level level, struct xrt_device *xdev, const char *format,...) XRT_PRINTF_FORMAT(6
Main device-related log implementation function: do not call directly, use a macro that wraps it.
void u_log_set_sink(u_log_sink_func_t func, void *data)
Sets the logging sink, log is still passed on to the platform defined output as well as the sink.
Definition: u_logging.c:86
void u_log_xdev_hex(const char *file, int line, const char *func, enum u_logging_level level, struct xrt_device *xdev, const uint8_t *data, const size_t data_size)
Device-related log implementation for dumping memory buffers as hex: do not call directly,...
Definition: u_logging.c:170
@ U_LOGGING_WARN
Warning messages: indicating a potential problem.
Definition: u_logging.h:48
@ U_LOGGING_DEBUG
Debug messages, verbose.
Definition: u_logging.h:46
@ U_LOGGING_TRACE
Trace messages, highly verbose.
Definition: u_logging.h:45
@ U_LOGGING_RAW
Special level for raw printing, prints a new-line.
Definition: u_logging.h:50
@ U_LOGGING_ERROR
Error messages: indicating a problem.
Definition: u_logging.h:49
@ U_LOGGING_INFO
Info messages: not very verbose, not indicating a problem.
Definition: u_logging.h:47
enum xrt_result xrt_result_t
Result type used across Monado.
A single HMD or input device.
Definition: xrt_device.h:281
Pretty printing various Monado things.
Header holding common defines.
Internal result type for XRT.