Boost Log : Creating loggers and writing logs

Dedicated logger objects

现在我们已经定义了日志存储的位置和方式,是时候继续尝试日志记录了。为了做到这一点,我们必须创建一个logging source。在我们的例子中,这是一个 logger 对象,它很简单:

src::logger lg;

注意
好奇的读者可能已经注意到,我们没有为 trivial logging创建任何loggers。事实上,logger是由库提供的,并在后台使用。

与 sinks 不同,sources 不需要在任何地方注册,因为它们直接与logging core交互。还要注意的是,库提供了两个版本的loggers:线程安全的和非线程安全的。对于非线程安全的loggers来说,在不同的线程中,通过不同的loggers实例来写日志是安全的。因此,每一个需要写日志的线程都应该有一个单独的logger。线程安全的logger可以同时从不同的线程访问,但这将涉及到锁,并可能导致在大量写日志时减慢速度。线程安全的logger 类型在它们的名称中有_mt后缀。

不管是否线程安全,Log库提供的所有loggers都是默认的、可复制的和支持交换的,因此,让一个logger成为的类的成员应该没有问题。正如稍后将看到的,这种方法可以给带来额外的好处。

Log库提供了许多具有不同特性的logger,比如对severity和channel的支持。这些特性可以组合在一起,构造更复杂的logger。详情请见这里

Global logger objects

如果你不能把一个 logger 放到你的类中(例如你没有类),Log库提供了一种声明全局logger 的方法:

BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, src::logger_mt)

在这里,my_logger是一个用户定义的标记(对象)名称,稍后将用于获取logger实例,而logger_mt则是logge 类型。由Log库提供或由用户定义的任何logger型都可以进行这样的声明。然而,由于logger会有一个单独的实例,所以通常会在多线程应用程序中使用线程安全的logger作为全局 logger。

Tip
还有其他的宏用于更复杂的情况。详细的描述在这里

稍后可以像这样获得logger:

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

lg将引用整个应用程序中唯一的 logger 实例,即使应用程序由多个模块组成。get函数本身是线程安全的,因此不需要额外的同步操作。

Writing logs

无论使用哪种类型的logger(类成员或全局,线程安全与否),要将一条日志记录写入logger,可以这样做:

logging::record rec = lg.open_record();
if (rec)
{
    logging::record_ostream strm(rec);
    strm << "Hello, World!";
    strm.flush();
    lg.push_record(boost::move(rec));
}

在这里,openrecord 函数用来确定,接下来将要被创建的记录是否至少要被一个sink所消费。过滤器会在这个阶段被应用。如果记录会被使用,函数返回一个有效的记录对象, 并且可以向记录中填入消息字符串。在此之后,记录处理可以通过对pushrecord的调用完成。

当然,上面的语法可以很容易地封装在一个宏中,事实上,我们鼓励用户编写自己的宏,而不是直接使用C++ logger接口。上面的日志记录可以这样写:

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

看起来很短,不是吗?BOOST_LOG宏和其他类似的宏都是由Log库定义的。它会自动提供一个类似STL的stream,以便用普通的插入表达式对消息进行格式化。将代码编写、编译和执行,应该能够在“sample.log”中看到“Hello,World!”的记录。下面本节的完整代码:

#include <boost/move/utility_core.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sources/global_logger_storage.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>

namespace logging = boost::log;
namespace src = boost::log::sources;
namespace keywords = boost::log::keywords;

BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, src::logger_mt)

void logging_function1()
{
    src::logger lg;

    logging::record rec = lg.open_record();
    if (rec)
    {
        logging::record_ostream strm(rec);
        strm << "Hello, World!";
        strm.flush();
        lg.push_record(boost::move(rec));
    }
}

void logging_function2()
{
    src::logger_mt& lg = my_logger::get();
    BOOST_LOG(lg) << "Greetings from the global logger!";
}

int main(int, char*[])
{
    logging::add_file_log("sample.log");
    logging::add_common_attributes();

    logging_function1();
    logging_function2();

    return 0;
}
原文地址:https://www.cnblogs.com/kohlrabi/p/9143631.html