Boost Log 2.0 : mengosongkan tingkat Keparahan di log

Saya menggunakan Boost-Log 2.0, yang memiliki beberapa perbedaan dari versi 1, dan saya kesulitan mengeluarkan atribut "Keparahan".

Saya menggunakan pemformat "Boost.Format-style".

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

TimeStamp, LineID, dan Message adalah common_attributes. Uptime adalah atribut yang saya tambahkan menggunakan attrs::timer(). Saya pikir Severity ditambahkan secara otomatis saat menggunakan severity_logger, namun ternyata tidak dan itulah masalah saya. Saya mendapatkan tingkat keparahan yang kosong, misalnya:

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

Perhatikan <> yang kosong. Saya sudah mencoba menambahkan tingkat keparahan menggunakan register_simple_formatter_factory tetapi kemudian saya mendapatkan kesalahan kompiler:

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

dan aku tidak mengerti alasannya.

Ini kode saya:

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

Perhatikan baris yang dikomentari:

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

yang menghasilkan kesalahan yang disebutkan.

Saya mengkompilasinya dengan:

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 sumber
comment
Mungkin, pertanyaan ini terkait: stackoverflow.com/questions/18014335/   -  person SebastianK    schedule 16.07.2014


Jawaban (5)


Mengalami masalah yang sama (kosongkan %Keparahan% di file log DAN kesalahan kompiler yang sama saat mencoba menambahkan fungsi register). Saya menemukan bahwa panggilan ke register_simple_formatter_factory seharusnya:

boost::log::register_simple_formatter_factory< boost::log::trivial::severity_level, char >("Severity");
person W. Meert    schedule 13.10.2013
comment
Anda mungkin harus menambahkan jawaban Anda bahwa Anda harus melakukan itu sebelum panggilan add_file_log (atau serupa), jika tidak, maka itu tidak akan berfungsi secara diam-diam. - person Vitalii; 17.06.2019

Berikut prototipe templat fungsi register_simple_formatter_factory:

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

Artinya Anda lupa typename CharT, jadi ini yang benar:

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

Atau beberapa tipe karakter lainnya, seperti wchar_t.

person Matt Yang    schedule 14.06.2014

Anda dapat membuat backend Anda sendiri dan memanggil set_formatter di dalamnya. Berikut kode saya yang menunjukkan cara melakukannya ditambah beberapa tambahan seperti pembersihan file log dan auto flush:

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

        }

    }

Anda juga dapat mengatur tingkat logging sebagai:

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

catatan: Kode ini berasal dari repositori saya sendiri. dreamdridge adalah nama produk, oleh karena itu namespacenya.

person Mert    schedule 22.04.2013

Alasannya mungkin karena Anda tidak boleh menulis data ke std::ostream. boost.log menggunakan boost.log.formatting_ostream untuk mengeluarkan log, bukan std::ostream. silakan lihat kode ini yang diambil dari halaman 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

Memperbaiki panggilan untuk mendaftarkan pemformat (yaitu operator<<) seperti yang ditunjukkan oleh jawaban dari W. Merrt dan Matt Yang adalah semua yang Anda perlukan untuk membuat kode Anda saat ini dikompilasi dan dijalankan dengan benar.

Namun, untuk memanfaatkan sepenuhnya kemampuan pemfilteran Boost Log, Anda juga perlu menentukan operator>> untuk tingkat keparahan khusus Anda dan kemudian mendaftarkan metode tersebut ke pabrik filter.

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