вытащить значение severity level для rec? Само сообщение как-то примерно так через задницу достается:
*rec[boost::log::expressions::smessage]
Но не severity level. Вообще, просто зла не хватает на автора этого Boost.Log. Марсианин какой-то. Сплошная, блин, гибкость кругом, только воспользоваться ничем нельзя и документация кривая. В документации одни неймспейсы, в коде - другие, и ничего толком не описано. Самая основная вещь и хрен чего про неё найдешь.
ну, гуголь вывел на вот это: http://stackoverflow.com/questions/17491561/boost-log-callback
там в первом же ответе приведён, кхм, примерчик... не, это действительно изврат. если ты не из ЛГБИ, то лучше в это не лезть. что за плюсы должны быть у этого монстра, чтобы окупить моральные издержки на такой извращённый синтаксис?
Ну так boost::log::aux::default_attribute_names::severity() это и есть тот самый атрибут Severity который [uninitialized]. Не работает оно. Потому я и спрашиваю. В лог пишу с помощью BOOST_LOG_TRIVIAL, который severety_logger. Всё должно работать, а оно не работает.
// c++ -Wall -std=c++11 -O2 -DBOOST_LOG_DYN_LINK -I /opt/local/include -L /opt/local/lib -o a.out crap14.cc -lboost_log-mt -lboost_system-mt -lpthread
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/basic_sink_backend.hpp>
#include <boost/log/sinks/frontend_requirements.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/trivial.hpp>
#include <iostream>
class ForwardingLogSinkBackend : public boost::log::sinks::basic_sink_backend<boost::log::sinks::combine_requirements<boost::log::sinks::synchronized_feeding>::type> {
public:
explicit ForwardingLogSinkBackend()
{
}
// The function consumes the log records that come from the the logging frontend
void consume(const boost::log::record_view& rec)
{
auto map = rec.attribute_values();
for(auto mi = map.begin(); mi != map.end(); ++mi) {
std::clog << mi->first << " : " << mi->second.get_type().pretty_name() << std::endl;
}
auto severity = rec.attribute_values()[boost::log::aux::default_attribute_names::severity()].extract<boost::log::trivial::severity_level>();
std::clog << "severity" << " = " << severity << ", message = " << *rec[boost::log::expressions::smessage] << std::endl;
}
};
typedef boost::log::sinks::synchronous_sink<ForwardingLogSinkBackend> ForwardingLogSink;
int main()
{
auto sink = boost::make_shared<ForwardingLogSink>(boost::make_shared<ForwardingLogSinkBackend>());
boost::log::core::get()->add_sink(sink);
BOOST_LOG_TRIVIAL(info) << "Hello, World!";
}
Там, хоть и через задницу, но работает. У меня тот же код, но вызываемый внутри динамической библиотеки, уже выдает что-то вроде severity = , message = Hello, World!
Проще - это использовать оператор [] напрямую у rec, а не просить attribute_values(), а так нет принципиальной разницы. Проблема в том, что если этот sink положить в DLL и logc->add_sink (sink); делать оттуда же, то при вызове severity.get() будет вот как-то так:
Assertion failed: (m_ptr != __null), function get, file /opt/local/include/boost/log/utility/value_ref.hpp, line 150.
Abort trap: 6
ЗЫ кстати твой Sink - никакой не sink на самом деле, а именно sink backend. И у меня он от basic_sink_backend наследуется, что тоже имеет значение.
ну, во-первых, я не телепат, чужие мысли на расстоянии улавливаю плохо. во-вторых, я этот boost::log после прочтения этой темы в первый раз вижу. boost'ом вообще пользуюсь много лет, версии так с 29-й. но не всё отслеживаю, да и не всё мне нужно в работе. думаю, если поковыряться больше 15 минут, то можно понять, какая там идеология. хотя синтаксис библиотеки удрочает весьма, это факт.
Вообще, просто зла не хватает на автора этого Boost.*. Марсианин какой-то. Сплошная, блин, гибкость кругом, только воспользоваться ничем нельзя и документация кривая. В документации одни неймспейсы, в коде - другие, и ничего толком не описано. Самая основная вещь и хрен чего про неё найдешь.
А если в библиотеке BOOST_LOG_TRIVIAL() вызвать - тоже работает? Ну понятно, что такие штуки уже сильно зависят от компилятора, параметров линковки и т.п.
Ну я бы не сказал так про весь boost. Из того, чем я там успел попользоваться (не считая того, что уже переехало стандартную библиотеку) - unit_test_framework, program_options, filesystem, system, thread, serialization, endian, chrono, log - у log самый идиотский интерфейс (и вообще архитектура). Далее за ним идет program_options, но там уже лучше. Кстати, характерно, что авторы этих двух библиотек - выходцы из СССР. Закономерность?
А вот лог и правда получился «странный». Посматривал на либу ещё до принятия в буст - всё-таки иметь стандартное логирование удобно. Надеялся, что раз сразу не приняли, то автор более прямо сделает, но похоже не судьба.
асболютно без проблем. я тут не вижу никаких зависимостей от того, где эту фигню инициализировать. библиотека подгружается и дальше работает в том же пространстве памяти. никаких хитростей тут нет. компилятор у меня совершенно стандартный GCC 4.9.2. параметры компиляции тоже стандартные для подобных вещей:
-std=c++11 -Wall -fexceptions -pthread -fPIC -DBOOST_LOG_DYN_LINK
ничего такого особенного.
да, кстати, program_options у меня использовался в некоторых проектах и мне он показался довольно удобным. у меня была железяка, в которую прогружалось более 200 параметров и чтобы весь этот зоопарк как-то консистентно представить для юзера, был заюзан boost::program_options. на него у меня нареканий нет. он довольно просто и свои задачи вполне решает.
я тоже «выходец из СССР». и это во многом мне помогло. у меня хотя бы образование хорошее.
Да тоже накручено всего, но при этом на сами опции приходится ссылаться по их строковым названиям. В результате можно ссылаться на несуществующие опции и не знать об этом до тех пор, пока в рантайме этот баг не вылезет. У boost::program_options::notify() странная семантика с выбросом исключения. Документация тоже не ахти. Потом, в С++11 есть статическая инициализация, там её до сих пор не появилось. Ну а так то лучше, чем log, конечно.
да куда эта статическая инициализация упёрлась? без неё жили сто лет, никто не жужжал. буст - это обкатка будущих стандартов С++. но у них нет цели ежедневно обновлять весь свой код, которого там немало. они в первую очередь поддерживают консистентность на всех платформах и компиляторах, которые буст поддерживает.
я считаю, что программист должен думать головой. а не надеяться, что компилятор его спасёт от него самого. ошибки типа «ссылался на несуществующую опцию» из разряда ССЗБ. обычно системы и библиотеки предоставляют интерфейсы для проверки того, существует ли объект, можно ли писать в какой-то адрес и многое другое. вопрос лишь в том, насколько программист дисциплинирован, чтобы использовать эти проверки.
Не нравится, что в документации http://www.boost.org/doc/libs/1_58_0/doc/html/boost/program_options/notify.html всего одна строка - Runs all 'notify' function for options in 'm'. А на самом деле эта штуковина первым и главным делом проверит m и выбросит исключение, если там будет что-то не так (какой-нибудь обязательной опции например нет). То есть проверка неявная, да ещё и недокументированная.
В итоге, несмотря на обилие библиотек из boost в проекте, переехал с boost.log на spdlog: https://github.com/gabime/spdlog
Библиотечка на порядок проще и на 2 порядка быстрее, что тоже важно.
С Boost.Log не стал разбираться дальше поскольку:
If your application consists of more than one module (e.g. an exe and one or several dll's) that use Boost.Log, the library must be built as a shared object. If you have a single executable or a single module that works with Boost.Log, you may build the library as a static library.
и хотя в конкретном описанном случае линковка с boost.log была динамической (и всё равно не работало!), на винде проект линкуется статически. Spdlog с этой ситуацией справляется нормально. Единственная проблема - при использовании синглетонов на статических переменных, при попытке использовать spdlog из деструктора такого синглетона, spdlog начинает кидать исключения (ибо сам реализован на таких синглетонах), что, в общем, предсказуемо.
не, ну требование динамики при использовании из разных модулей - оно понятно и это вполне ожидаемо. но под офтопиком нет проблем собрать динамику. буст даже в уже собранном виде поставляется под маздай. просто синтаксис библиотеки не особо удобен. а если она ещё и тормозит, то и вовсе нет смысла её юзать.