2013-04-06 4 views
21

Ich benutze Boost-Log 2.0, das einige Unterschiede zu Version 1 hat, und ich habe es schwer, das Attribut "Schweregrad" auszugeben.Boost Log 2.0: leer Schweregrad in Protokollen

Ich benutze die "Boost.Format-style" Formatierer: "%TimeStamp% [%Uptime%] (%LineID%) <%Severity%>: %Message%"

TimeStamp, LineID und Messagecommon_attributes sind. Uptime ist ein Attribut, das ich unter Verwendung von attrs::timer() hinzugefügt habe. Ich dachte, dass Severity wurde automatisch bei der Verwendung severity_logger hinzugefügt, aber anscheinend ist es nicht, und das ist mein Problem. Ich bekomme leer severities, zB:

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

Beachten Sie die leere <>. Ich habe versucht, Schwere hinzuzufügen register_simple_formatter_factory verwenden, aber dann habe ich den Compiler-Fehler:

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

und ich nicht, warum.

Hier ist mein Code:

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

Beachten Sie die kommentierten-out line:

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

, die die genannten Fehler erzeugt.

ich kompilieren mit: g++ main.cpp -Wall -DBOOST_ALL_DYN_LINK -lboost_system -lboost_log_setup -lboost_log -lboost_filesystem -lboost_date_time -lboost_thread -o main

Jede Hilfe dankbar!

+0

Vielleicht ist diese Frage verwandt: http://stackoverflow.com/questions/18014335/boost-log-severity-logger-init-from-stream – SebastianK

Antwort

3

Sie können Ihr eigenes Backend erstellen und set_formatter aufrufen. Hier ist mein Code zeigt, wie es zu tun plus ein paar Ergänzungen, wie die Protokolldatei Bereinigung und Auto Flush:

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

Anmerkung:

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

     } 

    } 

auch Sie die Protokollierungsebene als festlegen Dieser Code ist aus mein eigenes Repository. dreamdridge ist der Produktname, daher die Namespaces.

1

Der Grund könnte sein, dass Sie keine Daten in std :: ostream schreiben sollten. boost.log verwendet boost.log.formatting_ostream, um Protokolle auszugeben, nicht std :: ostream. sehen Sie bitte den Code ab Seite extrahierte 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

lief in das gleiche Problem (Leer% Severity% in der Protokolldatei und den gleichen Compiler-Fehler, wenn die Registerfunktion hinzuzufügen versuchen). fand ich, dass der Anruf register_simple_formatter_factory sein:

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

Hier ist der Prototyp register_simple_formatter_factory Funktionsvorlage:

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

Das heißt, Sie typename CharT vergessen, so, hier ist die richtige:

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

Oder einige andere Zeichentypen, wie wchar_t.

0

den Anruf Korrektur der Formatierer (das heißt operator<<) zu registrieren, wie durch die Antworten von W. Merrt und Matt Yang wies darauf hin, ist alles, was Sie benötigen, um Ihre aktuellen Code der Kompilierung zu machen und ordnungsgemäß ausgeführt.

Um jedoch die Filterfunktionen von Boost Log voll auszunutzen, müssen Sie auch operator>> für Ihre benutzerdefinierten Schweregrade definieren und diese Methode dann bei der Filterfabrik registrieren.

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()); 
} 
Verwandte Themen