Logging
Introduction
The header <utilities/log.h>
supplies a couple of macros for simple logging and debugging messages.
- 1
-
These messages are dispatched unless the
NO_LOGS
flag is set at compile time. - 2
-
These messages are dispatched only if the
DEBUG
flag is set at compile time.
These macros create and dispatch utilities::message
objects, which hold the user-supplied message and location information specifying the message’s creation location. The LOG
and DBG
macros automatically pass the correct source code location information to the message.
The message payload can be anything that works for the facilities in std::format
. The default message handler prints the source code location if there is no payload.
Microsoft’s old traditional preprocessor is not happy with these macros, but their newer cross-platform compatible one is fine. Add the /Zc:preprocessor flag to use that upgrade at compile time. Our CMake module compiler_init does that automatically for you.
|
Message Handling
The macros create and immediately dispatch messages to a message handler. The default handler prints the message and the location information to a default stream std::cout
. You can change that default stream, for example:
= std::ofstream("log.txt");
log_file ::message::stream = &log_file; utilities
For fancier usage, you can interpose your message handler
void my_handler(const utilities::message& msg) { ... }
::message::handler() = my_handler; utilities
Your handler can do whatever it likes with the messages it receives. You can revert to the default handler by calling the class method utilities::message::use_default_handler()
.
Everything here is deliberately rudimentary, and there is no consideration for rotating log files, etc., or for streaming efficiencies. The primary use case for the macros above and the underlying utilities::message class is easily printing useful messages during the development cycle. The emphasis is on ease of use as opposed to great generality or speed. During the development cycle, the typical output is going to be small anyway.
|
Example (source file named example.cpp
)
#include <utilities/log.h>
int add(int x, int y)
{
("The DEBUG flag was set at compile time.");
DBG("x = {}, y = {}", x, y);
LOGreturn x + y;
}
int main()
{
1();
LOGreturn add(10, 11);
}
- 1
-
A call to
LOG
without any message will print the source location.
Output
[LOG] function 'main' (example.cpp, line 11)
[DBG] function 'add' (example.cpp, line 4): The DEBUG flag was set at compile time.
[LOG] function 'add' (example.cpp, line 5): x = 10, y = 11