versiones guia español actualizar c++ boost boost-log

c++ - guia - Boost Log 2.0: vacío nivel de gravedad en los registros



qgis español (5)

Aquí está el prototipo de la plantilla de función register_simple_formatter_factory :

template<typename AttributeValueT, typename CharT> void register_simple_formatter_factory(attribute_name const &);

Eso significa que olvidó el nombre de typename CharT , así que aquí está el correcto:

logging::register_simple_formatter_factory<severity_level, char>("Severity");

O algunos otros tipos de caracteres, como wchar_t .

Estoy usando Boost-Log 2.0, que tiene algunas diferencias con la versión 1, y me cuesta mucho dar salida al atributo "Gravedad".

Estoy usando los formateadores "Boost.Format-style"

"%TimeStamp% [%Uptime%] (%LineID%) <%Severity%>: %Message%"

TimeStamp , LineID y Message son common_attributes . Uptime es un atributo que agregué usando attrs::timer() . Pensé que la Severity se agregó automáticamente al usar severity_logger , pero aparentemente no lo es y ese es mi problema. Obtengo severidades vacías, por ejemplo:

2013-Apr-06 19:21:52.408974 [00:00:00.001337] (3) <>: A warning severity message

Observe el vacío <> . He intentado agregar severidad usando register_simple_formatter_factory pero luego me aparece el error del compilador:

error: no matching function for call to ‘register_simple_formatter_factory(const char [9])’

Y no entiendo por qué.

Aquí está mi código:

#include <iostream> #include <boost/log/common.hpp> #include <boost/log/core.hpp> #include <boost/log/trivial.hpp> #include <boost/log/expressions.hpp> #include <boost/log/sinks/text_file_backend.hpp> #include <boost/log/sinks/sync_frontend.hpp> #include <boost/log/sinks/text_ostream_backend.hpp> #include <boost/log/utility/setup/file.hpp> #include <boost/log/utility/setup/common_attributes.hpp> #include <boost/log/utility/setup/formatter_parser.hpp> #include <boost/log/sources/severity_logger.hpp> #include <boost/log/sources/severity_feature.hpp> #include <boost/log/sources/record_ostream.hpp> #include <boost/log/attributes.hpp> using namespace std; namespace logging = boost::log; namespace expr = boost::log::expressions; namespace attrs = boost::log::attributes; namespace src = boost::log::sources; namespace keywords = boost::log::keywords; enum severity_level { DEBUG, INFO, WARNING, ERROR, CRITICAL }; BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, src::severity_logger_mt< severity_level> ) // The formatting logic for the severity level template< typename CharT, typename TraitsT > inline std::basic_ostream< CharT, TraitsT >& operator<< ( std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl) { static const char* const str[] = { "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL" }; if (static_cast< std::size_t >(lvl) < (sizeof(str) / sizeof(*str))) strm << str[lvl]; else strm << static_cast< int >(lvl); return strm; } void init() { // logging::register_simple_formatter_factory< severity_level >("Severity"); logging::add_file_log( keywords::file_name = "blop.log", keywords::auto_flush = true, keywords::open_mode = (std::ios::out | std::ios::app), keywords::format = "%TimeStamp% [%Uptime%] (%LineID%) <%Severity%>: %Message%" ); logging::add_common_attributes(); logging::core::get()->add_global_attribute("Uptime", attrs::timer()); } int main(int argc, const char *argv[]) { init(); src::severity_logger_mt< severity_level > lg = my_logger::get(); BOOST_LOG_SEV(lg, DEBUG) << "A debug severity message"; BOOST_LOG_SEV(lg, INFO) << "An informational severity message"; BOOST_LOG_SEV(lg, WARNING) << "A warning severity message"; BOOST_LOG_SEV(lg, ERROR) << "An error severity message"; BOOST_LOG_SEV(lg, CRITICAL) << "A critical severity message"; return 0; }

Observe la línea comentada:

// logging::register_simple_formatter_factory< severity_level >("Severity");

que produce el error mencionado.

Lo compilo con:

g++ main.cpp -Wall -DBOOST_ALL_DYN_LINK -lboost_system -lboost_log_setup -lboost_log -lboost_filesystem -lboost_date_time -lboost_thread -o main


Corregir la llamada para registrar el formateador (es decir, el operator<< ) como indican las respuestas de W. Merrt y Matt Yang es todo lo que necesita para hacer que su código actual se compile y ejecute correctamente.

Sin embargo, para aprovechar al máximo las capacidades de filtrado de Boost Log, también debe definir el operator>> para sus niveles de gravedad personalizados y luego registrar ese método en la fábrica de filtros.

template< typename CharT, typename TraitsT> inline std::basic_istream< CharT, TraitsT >& operator>> ( std::basic_istream< CharT, TraitsT >& strm, severity_level &lvl) { std::string tmp; strm >> tmp; // can make it case insensitive to allow ''warning'' instead of only ''WARNING'' // std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::toupper); // if you have a lot of levels you may want use a map instead if (tmp.compare("DEBUG") == 0) lvl = DEBUG; else if (tmp.compare("INFO") == 0) lvl = INFO; else if (tmp.compare("WARNING") == 0) lvl = WARNING; else if (tmp.compare("ERROR") == 0) lvl = ERROR; else if (tmp.compare("CRITICAL") == 0) lvl = CRITICAL; // provide a default value for invalid strings else lvl = DEBUG; // or you could throw an exception // else tmp.append(" is not a valid severity level."), throw std::invalid_argument(tmp); return strm; } void init() { // register operator<< for severity_level logging::register_simple_formatter_factory< severity_level, char >("Severity"); // register operator>> for severity_level logging::register_simple_filter_factory< severity_level >("Severity"); logging::add_file_log( keywords::file_name = "blop.log", keywords::auto_flush = true, keywords::open_mode = (std::ios::out | std::ios::app), keywords::format = "%TimeStamp% [%Uptime%] (%LineID%) <%Severity%>: %Message%", // now you can filter using the name of the severity level keywords::filter = "%Severity% >= INFO" ); logging::add_common_attributes(); logging::core::get()->add_global_attribute("Uptime", attrs::timer()); }


El motivo podría ser que no debería escribir datos en std :: ostream. boost.log utiliza boost.log.formatting_ostream para generar registros, no std :: ostream. consulte el código extraído de la página http://www.boost.org/doc/libs/1_54_0/libs/log/doc/html/log/detailed/expressions.html

// The operator is used when putting the severity level to log logging::formatting_ostream& operator<< ( logging::formatting_ostream& strm, logging::to_log_manip< severity_level, severity_tag > const& manip ) { static const char* strings[] = { "NORM", "NTFY", "WARN", "ERRR", "CRIT" }; severity_level level = manip.get(); if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings)) strm << strings[level]; else strm << static_cast< int >(level); return strm; }


Puedes crear tu propio backend y llamar a set_formatter en él. Aquí está mi código que muestra cómo hacerlo, más algunas adiciones, como la limpieza del archivo de registro y la descarga automática:

BOOST_LOG_DECLARE_GLOBAL_LOGGER(db_logger, src::severity_logger_mt< dreambridge::log::LogLevel >); #define LOGGER(level) BOOST_LOG_STREAM_SEV(db_logger::get(), level) void InitializeFileLog(const std::string & logDir) { boost::shared_ptr< logging::core > loggingCore = logging::core::get(); db_logger::get().add_attribute( "TimeStamp", boost::make_shared< attrs::local_clock >()); string logPath = logDir + "/DreamBridgeSapi2MrcpTts_%N.log"; boost::shared_ptr< sinks::text_file_backend > backend = boost::make_shared< sinks::text_file_backend >( // file name pattern keywords::file_name = logPath, // rotate the file upon reaching 5 MiB size... keywords::rotation_size = 5 * 1024 * 1024, // ...or at midnight, whichever comes first keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0) ); backend->auto_flush(true); // Wrap it into the frontend and register in the core. // The backend requires synchronization in the frontend. typedef sinks::synchronous_sink< sinks::text_file_backend > sink_t; boost::shared_ptr< sink_t > sink(new sink_t(backend)); loggingCore->add_sink(sink); backend->set_formatter(fmt::stream << fmt::date_time< boost::posix_time::ptime >("TimeStamp") << " : [" << fmt::attr< dreambridge::log::LogLevel >("Severity") << "] " << fmt::message() ); backend->set_file_collector(sinks::file::make_collector( // rotated logs will be moved here keywords::target = logDir + "/old_logs", // oldest log files will be removed if the total size reaches 100 MiB... keywords::max_size = 100 * 1024 * 1024, // ...or the free space in the target directory comes down to 50 MiB keywords::min_free_space = 50 * 1024 * 1024 )); try { backend->scan_for_files(sinks::file::scan_all); } catch(std::exception & e) { LOGGER(emergency) << "exception during scanning : " << e.what(); } }

También puede establecer el nivel de registro como:

void SetLogLevel(dreambridge::log::LogLevel logLevel) { boost::shared_ptr< logging::core > loggingCore = logging::core::get(); loggingCore->set_filter ( flt::attr< dreambridge::log::LogLevel >("Severity") <= logLevel ); }

Nota: Este código es de mi propio repositorio. Dreamdridge es el nombre del producto, de ahí los espacios de nombres.


Se encontró con el mismo problema (en blanco% Gravedad% en el archivo de registro Y el mismo error del compilador al intentar agregar la función de registro). Encontré que la llamada a register_simple_formatter_factory debería ser:

boost::log::register_simple_formatter_factory< boost::log::trivial::severity_level, char >("Severity");