Fixposition SDK 0.0.0-heads/main-0-g7b59b93
Collection of c++ libraries and apps for use with Fixposition products
Loading...
Searching...
No Matches
logging.hpp
Go to the documentation of this file.
1/**
2 * \verbatim
3 * ___ ___
4 * \ \ / /
5 * \ \/ / Copyright (c) Fixposition AG (www.fixposition.com) and contributors
6 * / /\ \ License: see the LICENSE file
7 * /__/ \__\
8 * \endverbatim
9 *
10 * @file
11 * @brief Fixposition SDK: Logging
12 *
13 * @page FPSDK_COMMON_LOGGING Logging
14 *
15 * **API**: fpsdk_common/logging.hpp and fpsdk::common::logging
16 *
17 */
18#ifndef __FPSDK_COMMON_LOGGING_HPP__
19#define __FPSDK_COMMON_LOGGING_HPP__
20
21/* LIBC/STL */
22#include <cinttypes> // PRI.. macros, often used with formats
23#include <cstdarg>
24#include <sstream>
25
26/* EXTERNAL */
27
28/* PACKAGE */
29#include "string.hpp"
30
31namespace fpsdk {
32namespace common {
33/**
34 * @brief Logging
35 */
36namespace logging {
37/* ****************************************************************************************************************** */
38
39/**
40 * @name Printf() style logging
41 *
42 * For example: `INFO("Hello world, the number is %d", 42);`
43 *
44 * @{
45 */
46// clang-format off
47/**
48 * @brief Print a fatal message @hideinitializer
49 */
50#define FATAL(fmt, ...) fpsdk::common::logging::LoggingPrint(fpsdk::common::logging::LoggingLevel::FATAL, "Fatal: " fmt, ## __VA_ARGS__)
51/**
52 * @brief Print a error message @hideinitializer
53 */
54#define ERROR(fmt, ...) fpsdk::common::logging::LoggingPrint(fpsdk::common::logging::LoggingLevel::ERROR, "Error: " fmt, ## __VA_ARGS__)
55/**
56 * @brief Print a warning message @hideinitializer
57 */
58#define WARNING(fmt, ...) fpsdk::common::logging::LoggingPrint(fpsdk::common::logging::LoggingLevel::WARNING, "Warning: " fmt, ## __VA_ARGS__)
59/**
60 * @brief Print a notice message @hideinitializer
61 */
62#define NOTICE(fmt, ...) fpsdk::common::logging::LoggingPrint(fpsdk::common::logging::LoggingLevel::NOTICE, fmt, ## __VA_ARGS__)
63/**
64 * @brief Print a info message @hideinitializer
65 */
66#define INFO(fmt, ...) fpsdk::common::logging::LoggingPrint(fpsdk::common::logging::LoggingLevel::INFO, fmt, ## __VA_ARGS__)
67/**
68 * @brief Print a debug message @hideinitializer
69 */
70#define DEBUG(fmt, ...) fpsdk::common::logging::LoggingPrint(fpsdk::common::logging::LoggingLevel::DEBUG, fmt, ## __VA_ARGS__)
71/**
72 * @brief Print a debug hexdump @hideinitializer
73 */
74#define DEBUG_HEXDUMP(data, size, prefix, fmt, ...) fpsdk::common::logging::LoggingHexdump(fpsdk::common::logging::LoggingLevel::DEBUG, data, size, prefix, fmt, ## __VA_ARGS__)
75#if !defined(NDEBUG) || defined(_DOXYGEN_) // Only for non-Release builds
76/**
77 * @brief Print a trace message (only debug builds, compiled out in release builds) @hideinitializer
78 */
79# define TRACE(fmt, ...) fpsdk::common::logging::LoggingPrint(fpsdk::common::logging::LoggingLevel::TRACE, fmt, ## __VA_ARGS__)
80/**
81 * @brief Print a trace hexdump (only debug builds, compiled out in release builds) @hideinitializer
82 */
83# define TRACE_HEXDUMP(data, size, prefix, fmt, ...) fpsdk::common::logging::LoggingHexdump(fpsdk::common::logging::LoggingLevel::TRACE, data, size, prefix, fmt, ## __VA_ARGS__)
84#else
85# define TRACE(...) /* nothing */
86# define TRACE_HEXDUMP(...) /* nothing */
87#endif
88// clang-format on
89///@}
90
91/**
92 * @name C++ style logging
93 *
94 * For example, `INFO_S("Hello world, the number is " << 42);`
95 *
96 * @{
97 */
98// clang-format off
99/**
100 * @brief Print a fatal message @hideinitializer
101 */
102#define FATAL_S(expr) if (fpsdk::common::logging::LoggingIsLevel(fpsdk::common::logging::LoggingLevel::FATAL)) { \
103 std::stringstream ss; ss << expr; FATAL("%s", ss.str().c_str()); }
104/**
105 * @brief Print a error message @hideinitializer
106 */
107#define ERROR_S(expr) if (fpsdk::common::logging::LoggingIsLevel(fpsdk::common::logging::LoggingLevel::ERROR)) { \
108 std::stringstream ss; ss << expr; ERROR("%s", ss.str().c_str()); }
109/**
110 * @brief Print a warning message @hideinitializer
111 */
112#define WARNING_S(expr) if (fpsdk::common::logging::LoggingIsLevel(fpsdk::common::logging::LoggingLevel::WARNING)) { \
113 std::stringstream ss; ss << expr; WARNING("%s", ss.str().c_str()); }
114/**
115 * @brief Print a debug message @hideinitializer
116 */
117#define DEBUG_S(expr) if (fpsdk::common::logging::LoggingIsLevel(fpsdk::common::logging::LoggingLevel::DEBUG)) { \
118 std::stringstream ss; ss << expr; DEBUG("%s", ss.str().c_str()); }
119/**
120 * @brief Print a notice message @hideinitializer
121 */
122#define NOTICE_S(expr) if (fpsdk::common::logging::LoggingIsLevel(fpsdk::common::logging::LoggingLevel::NOTICE)) { \
123 std::stringstream ss; ss << expr; NOTICE("%s", ss.str().c_str()); }
124/**
125 * @brief Print a info message @hideinitializer
126 */
127#define INFO_S(expr) if (fpsdk::common::logging::LoggingIsLevel(fpsdk::common::logging::LoggingLevel::INFO)) { \
128 std::stringstream ss; ss << expr; INFO("%s", ss.str().c_str()); }
129#if !defined(NDEBUG) || defined(_DOXYGEN_) // Only for non-Release builds
130/**
131 * @brief Print a trace message (only debug builds, compiled out in release builds) @hideinitializer
132 */
133# define TRACE_S(expr) if (fpsdk::common::logging::LoggingIsLevel(fpsdk::common::logging::LoggingLevel::TRACE)) { \
134 std::stringstream ss; ss << expr; TRACE("%s", ss.str().c_str()); }
135#else
136# define TRACE_S(...) /* nothing */
137#endif
138// clang-format on
139///@}
140
141// ---------------------------------------------------------------------------------------------------------------------
142
143/**
144 * @brief Logging verbosity levels, default is INFO
145 *
146 * The logging levels loosely follow syslog levels (indicated in [] below, see also
147 * https://en.wikipedia.org/wiki/Syslog)
148 *
149 * Libraries (fpsdk_common, fpsdk_ros1, ...) code shall only use WARNING and DEBUG.
150 */
151enum class LoggingLevel
152{
153 FATAL, //!< [2/crit] Hard errors, critical conditions (for apps). Cannot be silenced.
154 ERROR, //!< [3/err] Errors (for apps)
155 WARNING, //!< [4/warning] Warnings (for libs and apps)
156 NOTICE, //!< [5/notice] Significant stuff, for example headings (for apps)
157 INFO, //!< [6/info] Interesting stuff, the default level (for apps)
158 DEBUG, //!< [7/debug] Debugging (for libs and apps)
159 TRACE //!< [7/debug] Extra debugging, only compiled-in in non-Release builds
160};
161
162LoggingLevel& operator++(LoggingLevel& level); //!< Increase verbosity (pre-increment)
163LoggingLevel& operator--(LoggingLevel& level); //!< Decrease verbosity (pre-decrement)
164LoggingLevel operator++(LoggingLevel& level, int); //!< Increase verbosity (post-increment)
165LoggingLevel operator--(LoggingLevel& level, int); //!< Decrease verbosity (post-decrement)
166
167/**
168 * @brief Stringify log level
169 *
170 * @param[in] level The logging level
171 *
172 * @returns a unique string identifying the level
173 */
174const char* LoggingLevelStr(const LoggingLevel level);
175
176/**
177 * @brief Check if given level would print
178 *
179 * @param[in] level The logging level in question
180 *
181 * @returns true if the given level would print, false otherwise
182 */
183bool LoggingIsLevel(const LoggingLevel level);
184
185/**
186 * @brief Logging "colours"
187 */
189{
190 AUTO = 0, //!< Automatic (default), use colours if stderr is an interactive terminal
191 YES, //!< Use colours (terminal escape sequences)
192 NO, //!< Do not use colours
193 JOURNAL, //!< Use systemd journal level indicators (instead of terminal colours), useful for systemd services
194};
195
196struct LoggingParams; // forward declaration
197
198/**
199 * @brief Custom logging print function signature
200 */
201using LoggingPrintFunc = void (*)(const LoggingParams&, const LoggingLevel, const char*);
202
203/**
204 * @brief Logging parameters
205 */
207{
208 /**
209 * @brief Constructor
210 *
211 * @param[in] level Logging level
212 * @param[in] colour Logging colours
213 */
215 LoggingLevel level_; //!< Logging level
216 LoggingColour colour_; //!< Level colours
217 LoggingPrintFunc fn_; //!< Custom logging print function
218};
219
220/**
221 * @brief Configure logging
222 *
223 * @param[in] params Logging parameters
224 *
225 * Examples:
226 *
227 * @code{.cpp}
228 * LoggingSetParams({LoggingLevel::DEBUG});
229 * LoggingSetParams({LoggingLevel::DEBUG, LoggingColour::YES});
230 * @endcode
231 *
232 * @returns a copy of the applied logging parameters
233 */
235
236/**
237 * @brief Get current logging params
238 *
239 * @returns a copy of the current logging params
240 */
242
243/**
244 * @brief Print a log message
245 *
246 * @note Use INFO(), DEBUG(), WARNING() etc. instead of this function.
247 *
248 * @param[in] level Logging level
249 * @param[in] fmt printf() style format string
250 * @param[in] ... arguments to the format string
251 */
252void LoggingPrint(const LoggingLevel level, const char* fmt, ...) PRINTF_ATTR(2);
253
254/**
255 * @brief Print a hexdump
256 *
257 * @note Typically, use DEBUG_HEXDUMP() or TRACE_HEXDUMP() instead of this function.
258 *
259 * @param[in] level Logging level
260 * @param[in] data Pointer to start of data to dump
261 * @param[in] size Size of data to dump
262 * @param[in] prefix Prefix to add to each line, can be NULL to omit
263 * @param[in] fmt printf() style format string (for a first line to print), can be NULL to omit
264 * @param[in] ... Arguments to the format string
265 */
266void LoggingHexdump(const LoggingLevel level, const uint8_t* data, const uint64_t size, const char* prefix,
267 const char* fmt, ...) PRINTF_ATTR(5);
268
269/* ****************************************************************************************************************** */
270} // namespace logging
271} // namespace common
272} // namespace fpsdk
273#endif // __FPSDK_COMMON_LOGGING_HPP__
void LoggingHexdump(const LoggingLevel level, const uint8_t *data, const uint64_t size, const char *prefix, const char *fmt,...) PRINTF_ATTR(5)
Print a hexdump.
LoggingLevel
Logging verbosity levels, default is INFO.
Definition logging.hpp:152
@ WARNING
[4/warning] Warnings (for libs and apps)
@ FATAL
[2/crit] Hard errors, critical conditions (for apps). Cannot be silenced.
@ TRACE
[7/debug] Extra debugging, only compiled-in in non-Release builds
@ INFO
[6/info] Interesting stuff, the default level (for apps)
@ NOTICE
[5/notice] Significant stuff, for example headings (for apps)
@ ERROR
[3/err] Errors (for apps)
@ DEBUG
[7/debug] Debugging (for libs and apps)
LoggingParams LoggingGetParams()
Get current logging params.
void(*)(const LoggingParams &, const LoggingLevel, const char *) LoggingPrintFunc
Custom logging print function signature.
Definition logging.hpp:201
LoggingParams LoggingSetParams(const LoggingParams &params)
Configure logging.
const char * LoggingLevelStr(const LoggingLevel level)
Stringify log level.
bool LoggingIsLevel(const LoggingLevel level)
Check if given level would print.
LoggingLevel & operator++(LoggingLevel &level)
Increase verbosity (pre-increment)
void LoggingPrint(const LoggingLevel level, const char *fmt,...) PRINTF_ATTR(2)
Print a log message.
LoggingLevel & operator--(LoggingLevel &level)
Decrease verbosity (pre-decrement)
LoggingColour
Logging "colours".
Definition logging.hpp:189
@ JOURNAL
Use systemd journal level indicators (instead of terminal colours), useful for systemd services.
@ YES
Use colours (terminal escape sequences)
@ AUTO
Automatic (default), use colours if stderr is an interactive terminal.
Fixposition SDK.
Definition fpsdk_doc.hpp:20
Fixposition SDK: String utilities.
#define PRINTF_ATTR(n)
Helper macro for marking functions as taking printf() style formatting strings.
Definition string.hpp:46
LoggingParams(const LoggingLevel level=LoggingLevel::INFO, const LoggingColour colour=LoggingColour::AUTO)
Constructor.
LoggingColour colour_
Level colours.
Definition logging.hpp:216
LoggingLevel level_
Logging level.
Definition logging.hpp:215
LoggingPrintFunc fn_
Custom logging print function.
Definition logging.hpp:217