Tomographer
v5.4
Tomographer C++ Framework Documentation
|
Tomographer provides a lightweight framework for logging, i.e. producing messages which inform the user and/or developer about what the program is doing. Objects who would like to log messages take a template type parameter Logger, and an instance of such a type usually provided to its constructor. The Logger type must be a subclass of Tomographer::Logger::LoggerBase.
Log messages have different levels of importance, which are Tomographer::Logger::ERROR, Tomographer::Logger::WARNING, Tomographer::Logger::INFO, Tomographer::Logger::DEBUG, and Tomographer::Logger::LONGDEBUG. Please read the documentation for these levels and make sure you choose the right level for your messages.
To log messages into a logger object logger
, one simply calls, depending on the level, one of for example:
As you see, for each level, you have a corresponding method to call. The first argument is a constant string literal which should specify where the message originated from. It need not be displayed by all loggers, but is really helpful to trace bugs and track down where the program actually is.
Your messages should not end in newlines. Newlines will automatically be added by loggers which log into files and/or the console.
Each of the above methods comes in different flavors, depending on whether you would like to print a message which is already formatted, to have your message formatted printf
-style, or to use C++ streams to display your message:
The last variant takes a callable argument and calls it with an std::ostream&
argument. The function should then stream whatever it wants into the stream. This is particularly useful with C++11 lambdas, for example:
This last idiom is also very useful if producing the log message itself is resource-consuming. Imagine you wish to pretty-print a histogram for debugging:
The call to the lambda, and thus to histogram.prettyPrint()
, will only be performed if the logger will indeed eventually print the message.
To avoid specifying the origin parameter for repeated calls within the same class or function, you may use a Tomographer::Logger::LocalLogger, where you set the origin once in the constructor and don't specify it later on. Also, you may use it recursively. In the following example, the origin of the log messages are automatically set to "my_function()"
and "my_function()/some_callback[lambda]"
, respectively:
A more complete example is provided on the documentation page for Tomographer::Logger::LocalLogger.
Most loggers store their own level. This might not be the case, however, for example for a proxy logger which relays calls to another logger. Such loggers don't "store" their runtime level but are capable of querying it. This is controlled by the logger traits, see Write a New Custom Logger.
Any logger may be directly queried whether a message at a given log level will be emitted or discarded:
The level of a logger, stored or queried, may be obtained with the Tomographer::Logger::LoggerBase<Derived>::level() method. But don't abuse of this, usually there is no need to query the level of a logger, and it is much preferable to see if the logger is enabled for a particular level with Tomographer::Logger::LoggerBase<Derived>::enabledFor().
Also, by default there is no public setLevel()
method, in case your logger's level is statically fixed or otherwise can't be changed, or if you need a thread-safe logger. Some classes provide however their own API for changing the logger level: For example, FileLogger provides a method setLevel(level).
Specific topics: