Logging framework tutorial

Introduction

Here we will show how to use the Logging framework. If you just want to use the logger, the next two sections (Error levels and Quick HOWTO) should explain it to you in no time. If you want to know more about the logger, read the Logger manual further below.

What do all those levels mean?

Error levels

Reporting levels

Quick HOWTO

This section is intended to be a simple explanation on how to use the logger, for more detailed information see below.

The main class is called Logger, and you can create a logger of the type FastLogger with something like:

#include <Logger.hpp>
using namespace mermaid::support::logging;
...
CountedPtr<Logger> logger = FastLogger::build();

The FastLogger is thread unsafe, if you need thread safety use the ThreadSafeLogger. The header name changes accordingly.

Then, tell it where to send the output:

logger->enableAllLogLevels(TerminalOutput::build());

Besides the TerminalOutput there is a FileOutput and a DataFeedOutput. The header names change accordingly.

Using the logger is also very simple. To log a simple std::sting:

logger->step("The string to log. You can use the other levels, also in lowercase.");

To log anything that is not a string, like numbers:

LSTEP(logger, "(4.0/6)=" << (4.0/6));

The << operator works just like the stringstream's because it is the stringstream's. In fact, LSTEP is a macro that uses a ostringstream to create a string for the method described above, but this implementation might change in the future.

To log in any other level, just replace step by the name of the level, as listed above.

The output of the above would be:

17:18:56 The string to log. You can use the other levels, also in lowercase.
17:18:56 (4.0/6)=0.666667

Logger manual

Objectives

The logger is intended to be used for three main purposes:

Instatiation

Loggers are always objects of type CountedPtr<Logger>. However, Logger is the abstract base class of the logger, and you have instatiate a concrete logger. You can choose from a fast logger type, or a slightly slower but thread safe one. Create the fast one using:

#include <Logger.hpp>
using namespace mermaid::support::logging;
...
CountedPtr<Logger> logger = FastLogger::build();

And the thread safe one:

#include <Logger.hpp>
using namespace mermaid::support::logging;
...
CountedPtr<Logger> logger = ThreadSafeLogger::build();

Outputs

You can think of the logger as having two parts. The logger itself is no more than a router that sends the messages you give it to the right outputs. The outputs themselves are the ones responsible to put the messages in the right place. You can associate a LogOutput with a logger for a specific set of LogLevels. You have several types of outputs.

To output to a terminal use a TerminalOutput. The TerminalOutput is a singleton and already comes with thread safety.

#include <Logger.hpp>
using namespace mermaid::support::logging;
...
CountedPtr<LogOutput> output = TerminalOutput::build();

To output to a file use a FileOutput. It is your responsability to make sure that at any given moment there is only one FileOutput for each file. If you create two or more, the results are undefined.

#include <Logger.hpp>
using namespace mermaid::support::logging;
...
CountedPtr<LogOutput> output = FileOutput::build("file_output.txt");

If you need to output to this file from several threads, decorate it with a ThreadSafeOutput. Do this whether your loggers are thread safe or not.

#include <Logger.hpp>
using namespace mermaid::support::logging;
...
CountedPtr<LogOutput> output2 = ThreadSafeOutput::build(output);

You can use the ThreadSafeOutput for anything that inherits from LogOutput. These scenarios are possible:

The DataFeedOutput is not yet implemented.

Now you need to associate the logger with the output. You usually do this for all log levels:

logger->enableAllLogLevels(output);

You can also do this only for error or reporting levels:

logger->enableErrorLogLevels(output);
logger->enableReportingLogLevels(output);

Alternatively, you can enable it just for some specific level:

logger->enableLogLevel(LOG_ERROR, output);

For the inverse operation, you also have several options. You can disable all log levels. This is the only way to explicitly halt the logger.

logger->disableAllLogLevels();

You can also completely disable a specific output, all outputs for a level or a specific output just for a specifil level.

logger->disableAllLogLevels(output);
logger->disableAllLogLevel(LOG_ERROR);
logger->disableAllLogLevel(LOG_ERROR, output);

Using a prefix

Using the scope helper

morelevels

Source code organization

The Logger Framework is divided in three parts:

Logger examples

Generated on Fri Mar 4 22:15:37 2011 for MeRMaID::support by  doxygen 1.6.3