2013-04-06 11 views
21

Używam Boost-Log 2.0, który ma pewne różnice w stosunku do wersji 1, i mam problem z wydrukowaniem atrybutu "Severity".Boost Log 2.0: empty Poziom istotności w logach

używam "Boost.Format-style" formatek: "%TimeStamp% [%Uptime%] (%LineID%) <%Severity%>: %Message%"

TimeStamp, LineID i Messagecommon_attributes. Uptime jest atrybutem dodanym przy użyciu attrs::timer(). Myślałem, że Severity został automatycznie dodany podczas korzystania z severity_logger, ale najwyraźniej tak nie jest i to jest mój problem. Mam pustych nasileniu, np:

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

Wskazówka pusty <>. Próbowałem dodać ciężkość korzystając register_simple_formatter_factory ale wtedy pojawia się błąd kompilatora:

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

a ja nie rozumiem dlaczego.

Oto mój kod:

#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; 
} 

Wskazówka linia zakomentowanych:

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

która produkuje wspomniany błąd.

skompilować go z: g++ main.cpp -Wall -DBOOST_ALL_DYN_LINK -lboost_system -lboost_log_setup -lboost_log -lboost_filesystem -lboost_date_time -lboost_thread -o main

Każda pomoc mile widziana!

+0

Być może to pytanie jest powiązane: http://stackoverflow.com/questions/18014335/boost-log-severity-logger-init-from-stream – SebastianK

Odpowiedz

3

Możesz stworzyć swój własny backend i wywołać set_formatter na nim. Oto mój kod pokazujący jak to zrobić plus kilka dodatków takich jak czyszczenie pliku dziennika i automatycznego spłukiwania:

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(); 

     } 

    } 

również można ustawić poziom rejestrowania jako:

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 
     ); 
    } 

Uwaga: Ten kod jest od moje własne repozytorium. dreamdridge to nazwa produktu, stąd przestrzeń nazw.

1

Przyczyną może być to, że nie powinieneś zapisywać danych na std :: ostream. Funkcja boost.log używa metody boost.log.formatting_ostream do wyprowadzania dzienników, a nie std :: ostream. proszę zobaczyć ten kod wyodrębnione ze strony 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; 
} 
23

wpadł na ten sam problem (puste% Istotność% w pliku log i ten sam błąd kompilatora, gdy próbuje dodać funkcję rejestru). Uważam, że wezwanie do register_simple_formatter_factory powinno być:

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

Oto prototyp szablonu register_simple_formatter_factory funkcji:

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

Oznacza to, że zapomniał typename CharT, tak, tutaj jest prawidłowa:

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

Lub kilka innych typów znaków, takich jak wchar_t.

0

Poprawienie połączenia z rejestratorem formatyzatora (tj.), jak wskazano w odpowiedziach z W. Merrt i Matt Yang, to wszystko, czego potrzeba, aby bieżący kod był kompilowany i działał poprawnie.

Jednakże, aby w pełni wykorzystać możliwości filtrowania Boost Log, należy również zdefiniować operator>> dla niestandardowych poziomów ważności, a następnie zarejestrować tę metodę w fabryce filtrów.

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()); 
} 
Powiązane problemy