![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Adding more information to log: AttributesBoost , Chapter 1. Boost.Log v2 , Tutorial
|
![]() | Note |
---|---|
В однопоточной сборке атрибут «ThreadID» не регистрируется. |
![]() | Tip |
---|---|
По умолчанию, когда приложение начинается, никакие атрибуты не регистрируются в библиотеке. Приложение должно зарегистрировать все необходимые атрибуты в библиотеке, прежде чем приступать к написанию журналов. Это можно сделать в рамках инициализации библиотеки. Любопытный читатель мог бы задаться вопросом, как тогда работает тривиальная лесозаготовка. Ответ заключается в том, что раковина по умолчанию на самом деле не использует никаких значений атрибутов, за исключением уровня серьезности, для составления своего вывода. Это делается во избежание необходимости какой-либо инициализации для тривиальной рубки. После того, как вы используете фильтры или формататоры и раковины без по умолчанию, вам нужно будет зарегистрировать необходимые атрибуты. |
Функция add_common_attributes
является одним из нескольких помощников удобства, описанных here.
Некоторые атрибуты автоматически регистрируются при строительстве лесозаготовителей. Например, severity_logger
регистрирует атрибут "Severity", который может быть использован для добавления уровня акцента для различных записей журнала. Например:
// We define our own severity levels enum severity_level { normal, notification, warning, error, critical }; void logging_function() { // The logger implicitly adds a source-specific attribute 'Severity' // of type 'severity_level' on construction src::severity_logger< severity_level > slg; BOOST_LOG_SEV(slg, normal) << "A regular message"; BOOST_LOG_SEV(slg, warning) << "Something bad is going on but I can handle it"; BOOST_LOG_SEV(slg, critical) << "Everything crumbles, shoot me now!"; }
![]() | Tip |
---|---|
Вы можете определить свои собственные правила форматирования для уровня серьезности, определив для этого типа |
BOOST_LOG_SEV
Макро действует очень похоже на BOOST_LOG
за исключением того, что для метода регистратора open_record
требуется дополнительный аргумент. Макрос BOOST_LOG_SEV
можно заменить следующим эквивалентом:
void manual_logging() { src::severity_logger< severity_level > slg; logging::record rec = slg.open_record(keywords::severity = normal); if (rec) { logging::record_ostream strm(rec); strm << "A regular message"; strm.flush(); slg.push_record(boost::move(rec)); } }
Здесь можно увидеть, что open_record
может принимать именованные аргументы. Некоторые типы регистраторов, предоставляемые библиотекой, поддерживают такие дополнительные параметры, и этот подход, безусловно, может использоваться пользователями при написании собственных регистраторов.
Давайте посмотрим, что находится под капотом этой функции add_common_attributes
, которую мы использовали в разделе простой формы. Это может выглядеть примерно так:
void add_common_attributes() { boost::shared_ptr< logging::core > core = logging::core::get(); core->add_global_attribute("LineID", attrs::counter< unsigned int >(1)); core->add_global_attribute("TimeStamp", attrs::local_clock()); // other attributes skipped for brevity }
Здесь компоненты counter
и local_clock
являются классами атрибутов, они происходят из общего интерфейса атрибутов attribute
. Библиотека предоставляет ряд других классов атрибутов , в том числе атрибут функция
, который вызывает некоторый объект функции на приобретение стоимости. Например, мы можем аналогичным образом зарегистрировать атрибут named_scope
:
core->add_global_attribute("Scope", attrs::named_scope());
Это даст нам возможность хранить имена областей в журнале для каждой записи журнала, которую делает приложение. Вот как он используется:
void named_scope_logging() { BOOST_LOG_NAMED_SCOPE("named_scope_logging"); src::severity_logger< severity_level > slg; BOOST_LOG_SEV(slg, normal) << "Hello from the function named_scope_logging!"; }
Специфические атрибуты логгера не менее полезны, чем глобальные. Уровни жесткости и названия каналов являются наиболее очевидными кандидатами для реализации на исходном уровне. Ничто не мешает вам добавлять больше атрибутов к вашим лесозаготовителям, например:
void tagged_logging() { src::severity_logger< severity_level > slg; slg.add_attribute("Tag", attrs::constant< std::string >("My tag value")); BOOST_LOG_SEV(slg, normal) << "Here goes the tagged record"; }
Теперь все записи журнала, сделанные через этого регистратора, будут помечены конкретным атрибутом. Это значение атрибута может быть использовано позже в фильтрации и форматировании.
Еще одним хорошим использованием атрибутов является возможность отмечать записи журнала, сделанные различными частями приложения, чтобы подчеркнуть активность, связанную с одним процессом. Можно даже реализовать грубый инструмент профилирования для обнаружения узких мест производительности. Например:
void timed_logging() { BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer()); src::severity_logger< severity_level > slg; BOOST_LOG_SEV(slg, normal) << "Starting to time nested functions"; logging_function(); BOOST_LOG_SEV(slg, normal) << "Stopping to time nested functions"; }
Теперь каждая запись журнала, сделанная из функции logging_function
или любой другой функции, которую она вызывает, будет содержать атрибут «Timeline» с высокой точностью продолжительности времени, прошедшей с момента регистрации атрибута. На основе этих показаний можно определить, какие части кода требуют больше или меньше времени для выполнения. Атрибут «Timeline» будет незарегистрирован при выходе из объема функции timed_logging
.
См. раздел Атрибуты для подробного описания атрибутов, предоставляемых библиотекой. Полный код для этого раздела доступен здесь .
Как мы увидим в следующих разделах, полезно определить ключевое слово, описывающее конкретный атрибут, который использует приложение. Это ключевое слово может участвовать в фильтрации и форматировании выражений, таких как заполнитель severity
, который мы использовали в предыдущих разделах. Например, чтобы определить заполнители для некоторых атрибутов, которые мы использовали в предыдущих примерах, мы можем написать следующее:
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) BOOST_LOG_ATTRIBUTE_KEYWORD(scope, "Scope", attrs::named_scope::value_type) BOOST_LOG_ATTRIBUTE_KEYWORD(timeline, "Timeline", attrs::timer::value_type)
Каждый макрос определяет ключевое слово. Первый аргумент - это имя заполнителя, второй - имя атрибута, а последний параметр - тип значения атрибута. После определения заполнитель может использоваться в шаблонных выражениях и некоторых других контекстах библиотеки. Более подробная информация об определении ключевых слов атрибутов доступна здесь.
Статья Adding more information to log: Attributes раздела Chapter 1. Boost.Log v2 Tutorial может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
реклама |