Boost Log 2.0 : ล้างระดับความรุนแรงในบันทึก

ฉันใช้ Boost-Log 2.0 ซึ่งมีความแตกต่างบางอย่างจากเวอร์ชัน 1 และฉันมีช่วงเวลาที่ยากลำบากในการแสดงแอตทริบิวต์ "Severity"

ฉันใช้ฟอร์แมต "Boost.Format-style"

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

TimeStamp, LineID และ Message คือ common_attributes Uptime เป็นแอตทริบิวต์ที่ฉันเพิ่มโดยใช้ attrs::timer() ฉันคิดว่า Severity ถูกเพิ่มโดยอัตโนมัติเมื่อใช้ severity_logger แต่ดูเหมือนจะไม่เป็นเช่นนั้น และนั่นคือปัญหาของฉัน ฉันได้รับค่าความเข้มงวดที่ว่างเปล่า เช่น:

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

สังเกตช่องว่าง <> ฉันพยายามเพิ่มความรุนแรงโดยใช้ register_simple_formatter_factory แต่แล้วฉันได้รับข้อผิดพลาดของคอมไพเลอร์:

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

และฉันไม่เข้าใจว่าทำไม

นี่คือรหัสของฉัน:

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

สังเกตบรรทัดที่ใส่ความคิดเห็นไว้:

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

ซึ่งทำให้เกิดข้อผิดพลาดดังกล่าว

ฉันรวบรวมมันด้วย:

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

person Arthur    schedule 06.04.2013    source แหล่งที่มา
comment
บางทีคำถามนี้อาจเกี่ยวข้อง: stackoverflow.com/questions/18014335/   -  person SebastianK    schedule 16.07.2014


คำตอบ (5)


พบปัญหาเดียวกัน (% ความรุนแรง% ว่างในไฟล์บันทึกและข้อผิดพลาดคอมไพเลอร์เดียวกันเมื่อพยายามเพิ่มฟังก์ชันการลงทะเบียน) ฉันพบว่าการเรียก register_simple_formatter_factory ควรเป็น:

boost::log::register_simple_formatter_factory< boost::log::trivial::severity_level, char >("Severity");
person W. Meert    schedule 13.10.2013
comment
คุณอาจต้องเพิ่มคำตอบว่าต้องทำก่อนการโทร add_file_log (หรือคล้ายกัน) ไม่เช่นนั้นระบบจะไม่ทำงานอย่างเงียบๆ - person Vitalii; 17.06.2019

นี่คือต้นแบบของเทมเพลตฟังก์ชัน register_simple_formatter_factory:

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

นั่นหมายความว่าคุณลืม typename CharT ดังนั้น นี่คือสิ่งที่ถูกต้อง:

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

หรืออักขระประเภทอื่นๆ เช่น wchar_t

person Matt Yang    schedule 14.06.2014

คุณสามารถสร้างแบ็กเอนด์ของคุณเองและเรียก set_formatter ได้ นี่คือโค้ดของฉันที่แสดงวิธีการ พร้อมด้วยส่วนเพิ่มเติมบางอย่าง เช่น การล้างไฟล์บันทึกและการล้างข้อมูลอัตโนมัติ:

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

        }

    }

นอกจากนี้คุณยังสามารถตั้งค่าระดับการบันทึกเป็น:

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

หมายเหตุ: รหัสนี้มาจากที่เก็บของฉันเอง dreamdridge คือชื่อผลิตภัณฑ์ ดังนั้นเนมสเปซ

person Mert    schedule 22.04.2013

สาเหตุอาจเป็นเพราะคุณไม่ควรเขียนข้อมูลไปที่ std::ostream boost.log ใช้ boost.log.formatting_ostream เพื่อส่งออกบันทึก ไม่ใช่ std::ostream โปรดดูโค้ดนี้ที่ดึงมาจากหน้า 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;
}
person imafish    schedule 19.07.2013

แก้ไขการเรียกเพื่อลงทะเบียนฟอร์แมตเตอร์ (เช่น operator<<) ตามคำตอบจาก W คุณเพียงแค่ Merrt และ Matt Yang เพื่อทำให้โค้ดปัจจุบันคอมไพล์และทำงานได้อย่างถูกต้อง

อย่างไรก็ตาม เพื่อที่จะใช้ประโยชน์จากความสามารถในการกรองของ Boost Log ได้อย่างเต็มที่ คุณจะต้องกำหนด operator>> สำหรับระดับความรุนแรงที่คุณกำหนดเอง จากนั้นจึงลงทะเบียนวิธีการนั้นกับโรงงานตัวกรอง

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());
}
person McManip    schedule 11.01.2016