Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Filtering revisited

Boost , Chapter 1. Boost.Log v2 , Tutorial

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Мы уже касались фильтрации в предыдущих секциях, но едва поцарапали поверхность. Теперь, когда мы можем добавлять атрибуты к записям журналов и настраивать раковины, мы можем создавать любую сложную фильтрацию, которая нам нужна. Рассмотрим этот пример:

BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(tag_attr, "Tag", std::string)
void init()
{
    // Setup the common formatter for all sinks
    logging::formatter fmt = expr::stream
        << std::setw(6) << std::setfill('0') << line_id << std::setfill(' ')
        << ": <" << severity << ">\t"
        << expr::if_(expr::has_attr(tag_attr))
           [
               expr::stream << "[" << tag_attr << "] "
           ]
        << expr::smessage;
    // Initialize sinks
    typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
    boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
    sink->locked_backend()->add_stream(
        boost::make_shared< std::ofstream >("full.log"));
    sink->set_formatter(fmt);
    logging::core::get()->add_sink(sink);
    sink = boost::make_shared< text_sink >();
    sink->locked_backend()->add_stream(
        boost::make_shared< std::ofstream >("important.log"));
    sink->set_formatter(fmt);
    sink->set_filter(severity >= warning || (expr::has_attr(tag_attr) && tag_attr == "IMPORTANT_MESSAGE"));
    logging::core::get()->add_sink(sink);
    // Add attributes
    logging::add_common_attributes();
}

См. полный код .

В этом образце мы инициализируем две раковины - одну для полного файла журнала, а другую только для важных сообщений. Обе раковины будут записывать в текстовые файлы с одинаковым форматом записи журнала, который мы сначала инициализируем и сохраняем в переменной fmt. Тип формататор является стертым по типу функциональным объектом с подписью вызова форматтера; во многих отношениях его можно рассматривать как boost::функция или std::функция, за исключением того, что он никогда не бывает пустым. Существует также аналогичный объект функции для фильтров.

Примечательно, что сам форматтер содержит здесь фильтр. Как видите, формат содержит условную часть, которая присутствует только тогда, когда записи журнала содержат атрибут «Tag». Предикат has_attr проверяет, содержит ли запись значение атрибута "Tag" и контролирует, помещается ли она в файл или нет. Мы использовали ключевое слово атрибута, чтобы указать имя и тип атрибута для предиката, но также можно указать их на сайте вызова has_attr. Условные формататоры объясняются более подробно здесь .

Далее идет инициализация двух раковин. Первая раковина не имеет фильтра, что означает, что она сохранит каждую запись журнала в файл. Мы называем set_filter на второй раковине только для сохранения записей журнала с тяжестью не менее предупреждение или с атрибутом "Tag" со значением "IMPORTANT_MESSAGE". Как видите, синтаксис фильтра очень напоминает обычный C++, особенно при использовании ключевых слов атрибутов.

Как и в случае с формататорами, можно также использовать пользовательские функции в качестве фильтров. Boost.Phoenix может быть очень полезен в этом случае, поскольку его реализация bind совместима с заполнителями атрибутов. Предыдущий пример может быть изменен следующим образом:

bool my_filter(logging::value_ref< severity_level, tag::severity > const& level,
               logging::value_ref< std::string, tag::tag_attr > const& tag)
{
    return level >= warning || tag == "IMPORTANT_MESSAGE";
}
void init()
{
    // ...
    namespace phoenix = boost::phoenix;
    sink->set_filter(phoenix::bind(&my_filter, severity.or_none(), tag_attr.or_none()));
    // ...
}

Как видите, пользовательский формататор получает значения атрибутов, завернутые в шаблон value_ref. Эта обертка содержит необязательную ссылку на значение атрибута указанного типа; ссылка действительна, если запись журнала содержит значение атрибута требуемого типа. Реляционные операторы, используемые в my_filter, могут применяться безоговорочно, поскольку они автоматически возвращают фальсифицированные, если ссылка недействительна. Остальное делается с помощью выражения bind, которое распознает ключевые слова severity и tag_attr и извлекает соответствующие значения перед их передачей в my_filter.

[Note]Note

Из-за ограничений, связанных с интеграцией с Boost.Phoenix (см. #7996), требуется явно указать политику резервного копирования в случае, если значение атрибута отсутствует, при использовании ключевых слов атрибута с phoenix::bind или phoenix::function. В приведенном выше примере это делается путем вызова or_none, что приводит к пустому value_ref, если значение не найдено. В других случаях эта политика является дефолтом. Вместо этого можно использовать другие политики .

Вы можете попробовать, как это работает, составив и запустив test.


PrevUpHomeNext

Статья Filtering revisited раздела Chapter 1. Boost.Log v2 Tutorial может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Tutorial ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 18:25:36/0.029262065887451/1