boost.log教程:core facilities

Logging records

logging record中的所有信息,包括message text,都會被filters, formatters 和 sinks處理。
logging record特性:

  • 不能複製,只能被移動boost::move()。它由logging core在filter之後創建,此時內容爲空,隨後attribute value會由attribute生成並添加到log record
  • logging record可在formatting和sink時繼續添加attributes
  • 多線程環境中,logging record與創建它的線程綁定,所以logging record不能在線程中移動。

讀取這些信息的方式有幾種:

通過 logging::visitlogging::value_ref

更詳細參見網頁

enum severity_level { ... };
std::ostream& operator<< (std::ostream& strm, severity_level level);

struct print_visitor
{
    typedef void result_type;
    result_type operator() (severity_level level) const
    {
        std::cout << level << std::endl;
    };
};

// Prints severity level through visitation API
void print_severity_visitation(logging::record const& rec)
{
    logging::visit< severity_level >("Severity", rec, print_visitor());
}

// Prints severity level through extraction API
void print_severity_extraction(logging::record const& rec)
{
    logging::value_ref< severity_level > level = logging::extract< severity_level >("Severity", rec);
    std::cout << level << std::endl;
}

通過 attribute_values訪問所有屬性

更詳細參見網頁

// Prints severity level by searching the attribute values
void print_severity_lookup(logging::record const& rec)
{
    logging::attribute_value_set const& values = rec.attribute_values();
    logging::attribute_value_set::const_iterator it = values.find("Severity");
    if (it != values.end())
    {
        logging::attribute_value const& value = it->second;

        // A single attribute value can also be visited or extracted
        std::cout << value.extract< severity_level >() << std::endl;
    }
}

直接通過下標方式訪問

BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)

// Prints severity level by using the subscript operator
void print_severity_subscript(logging::record const& rec)
{
    // Use the attribute keyword to communicate the name and type of the value
    logging::value_ref< severity_level, tag::severity > level = rec[severity];
    std::cout << level << std::endl;
}

Record view

與logging record相似, record用來填充信息,record view用來後續處理:

  • record view不可變,可防止formatter及sink修改它
  • record view可複製,因爲內容不可改,使用淺複製成本很低

boost會自動在lock函數被調用時,爲record創建record view:

  • record view不會綁定到線程
  • record 會在lock結束後變空值,因爲record只被處理一次

Logging core

logging core是庫的核心,提供:

  • 維護全局和各線程的attribute sets
  • 處理log record的全局過濾
  • 應用sink的filter在sink間傳遞log record
  • 提供全局的exception handler
  • 提供全局的log record輸入口
  • 提供flush強制輸出

訪問方式

boost::shared_ptr< logging::core > core = logging::core::get();

Attribute sets

添加/刪除全局屬性add_global_attributeremove_global_attribute
添加/刪除線程屬性add_thread_attributeremove_thread_attribute

void foo()
{
    boost::shared_ptr< logging::core > core = logging::core::get();

    // Add a global attribute
	// 返回值第一個參數是其被添加後的索引,bool代表是否添加成功
    std::pair< logging::attribute_set::iterator, bool > res =
        core->add_global_attribute("LineID", attrs::counter< unsigned int >());
    // Do something ...
    // Remove the added attribute
    core->remove_global_attribute(res.first);
}

logging::core的所有方法都是線程安全的,但索引不能保證線程安全
獲取/設置全局屬性get_global_attributesset_global_attributes
獲取/設置線程屬性get_thread_attributesset_thread_attributes


Global filtering

filter讀入一組參數,返回此record是否通過
設置/清除filter的函數set_filter/ reset_filter,filter沒有設置,相當於所有log record可通過
通過set_logging_enabled,可設置filter是否生效,比較設置filter更高效。


Sink management

添加/刪除sink的函數,add_sinkremove_sink。添加的sink會保存到logging core中,但sink的執行順序是不確定的。

void foo()
{
    boost::shared_ptr< logging::core > core = logging::core::get();

    // Set a sink that will write log records to the console
    boost::shared_ptr< sinks::text_ostream_backend > backend =
        boost::make_shared< sinks::text_ostream_backend >();
    backend->add_stream(
        boost::shared_ptr< std::ostream >(&std::clog, boost::null_deleter()));

    typedef sinks::unlocked_sink< sinks::text_ostream_backend > sink_t;
    boost::shared_ptr< sink_t > sink = boost::make_shared< sink_t >(backend);
    core->add_sink(sink);

    // ...

    // Remove the sink
    core->remove_sink(sink);
}

sink的詳細說明見frontendbackend


Exception handling

添加異常處理類,通過set_exception_handler設置,其參數是無參數函數,在catch語句中被調用。
logging core中的異常處理類只應該處理通用錯誤。
Logging sinks 和 sources 可做更細緻的異常處理,參見
sink異常處理source異常處理

struct my_handler
{
    typedef void result_type;

    void operator() (std::runtime_error const& e) const
    {
        std::cout << "std::runtime_error: " << e.what() << std::endl;
    }
    void operator() (std::logic_error const& e) const
    {
        std::cout << "std::logic_error: " << e.what() << std::endl;
        throw;
    }
};

void init_exception_handler()
{
    // Setup a global exception handler that will call my_handler::operator()
    // for the specified exception types
    logging::core::get()->set_exception_handler(logging::make_exception_handler<
        std::runtime_error,  /*處理的錯誤類型*/
        std::logic_error
    >(my_handler()));
}

Feeding log records

logging core最重要的功能之一就是創建和推送log record,實現函數分別爲open_recordpush_record.

  • open_record收集global, thread-specific 和 source-specific的屬性,判斷是否會被filter掉,如果沒有被filter掉(至少有一個sink接收這個record),函數會返回一個log record對象
  • push_record在由open_record獲得的record對象填寫完內容後調用。之後record view對象會從record對象中生成,並傳給接收它的多個sink,這個過程中會發生formatting及保存到文件等操作,視情況而不同。隨後record對象被銷燬。
void logging_function(logging::attribute_set const& attrs)
{
    boost::shared_ptr< logging::core > core = logging::core::get();

    // Attempt to open a log record
    logging::record rec = core->open_record(attrs);
    if (rec)
    {
        // Ok, the record is accepted. Compose the message now.
        logging::record_ostream strm(rec);
        strm << "Hello, World!";
        strm.flush();

        // Deliver the record to the sinks.
        core->push_record(boost::move(rec));
    }
}

官方說明

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章