Boost C++ Libraries

PrevUpHomeNext

Step 2: Creating loggers and writing logs

Creating loggers: Object oriented programming style

Now that we defined where the log is to be stored it's time to go on and try logging. In order to do this one has to create a logging source. This would be a logger object in our case and it is as simple as that:

src::logger lg;

Note that unlike sinks sources need not to be registered anywhere since they interact directly with logging core. Also note that there are two versions of loggers provided by the library: the thread-safe ones and not thread-safe. For the not thread-safe loggers it is safe for different threads to write logs through different instances of loggers and thus there should be a separate logger for each thread that writes logs. The thread-safe counterparts may be accessed from different threads concurrently, but this would involve locking and may slow things down in case of intense logging. The thread-safe logger types have the _mt suffix in their name.

Regardless of the thread safety, all loggers provided by the library are default and copy-constructible and support swapping, so there should be no problem in making a logger a member of your class. As you will see later, such approach can give you additional benefits.

Creating loggers: Function-oriented programming style

In case if you cannot put a logger into your class (suppose you don't have one), the library provides a way of declaring global loggers like this:

BOOST_LOG_DECLARE_GLOBAL_LOGGER(my_logger, src::logger_mt)

Here my_logger is a user-defined tag name that will be used later to retrieve the logger instance and logger_mt is the logger type. Any logger type provided by the library or defined by user can be used in such declaration. However, since the logger will have a single instance, you will normally want to use thread-safe loggers in a multithreaded application as global ones.

In case if you want to pass some arguments to the logger on construction, you can use the following macro:

BOOST_LOG_DECLARE_GLOBAL_LOGGER_CTOR_ARGS(my_logger, src::logger_mt, (arg1)(arg2)(arg3))

or even write the initialization code yourself:

BOOST_LOG_DECLARE_GLOBAL_LOGGER_INIT(my_logger, src::logger_mt)
{
    // do something on logger initialization and return logger instance
    return src::logger_mt();
}

You may have such declaration in either a header or a compiled cpp unit. You may even have it in different modules of your application, however, the declaration should be exactly the same in all places, including the definition of the logger type (logger_mt in this case) and all symbol bindings within the logger initialization body.

Later on you can acquire the logger like this:

src::logger_mt& lg = get_my_logger();

or like this:

src::logger_mt& lg = my_logger::get();

In any case, the lg will reference to the one and only instance of the logger throughout the application, even if the application consists of multiple modules.

Writing logs

No matter what kind of logger you use (class member or global, thread-safe or not), to write a log record into a logger you could write something like this:

if (lg.open_record())
    lg.strm() << "Hello world!";

Here the open_record function call determines if the record to be constructed is going to be consumed by at least one sink. Filtering is applied at this stage. Then the strm function returns an object with a defined operator << that can be used to form the logging record message. You may output to log everything that has a well-defined output operator to an STL stream.

Of course, the above syntax can easily be wrapped into a macro and, in fact, users are encouraged to write their own macros instead of direct C++ logger interface usage. The log record above can be written like this:

BOOST_LOG(lg) << "Hello, World!";

Looks a bit nicer, doesn't it? The BOOST_LOG macro, along with other similar ones, is defined by the library. Having all that code written, compiled and executed you should be able to see the "Hello, World!" record in the "sample.log" file and/or on your console if you added the clog stream in the Step 1 of this tutorial.


PrevUpHomeNext