【问题标题】:Boost Log 2.0 : empty Severity level in logsBoost Log 2.0:日志中的空严重级别
【发布时间】:2023-04-07 11:38:01
【问题描述】:

我使用的是 Boost-Log 2.0,它与版本 1 有一些不同,我很难输出“严重性”属性。

我正在使用“Boost.Format-style”格式化程序

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

TimeStampLineIDMessagecommon_attributesUptime 是我使用 attrs::timer() 添加的属性。我以为Severity 是在使用severity_logger 时自动添加的,但显然不是,这是我的问题。我得到空的严重性,例如:

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

注意空的&lt;&gt;。我尝试使用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

【问题讨论】:

标签: c++ boost boost-log


【解决方案1】:

遇到了同样的问题(日志文件中的 %Severity% 为空白,尝试添加注册函数时出现相同的编译器错误)。 我发现对 register_simple_formatter_factory 的调用应该是:

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

【讨论】:

  • 您可能必须在add_file_log(或类似的)电话之前添加您必须这样做的答案,否则它不会静默工作。
【解决方案2】:

这是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

【讨论】:

    【解决方案3】:

    您可以制作自己的后端并在其上调用 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 是产品名称,因此是命名空间。

    【讨论】:

      【解决方案4】:

      W. MerrtMatt Yang 的答案所指出的,更正注册格式化程序的调用(即operator&lt;&lt;)是使当前代码正确编译和运行所需的全部内容。

      但是,为了充分利用 Boost Log 的过滤功能,您还需要为自定义严重级别定义 operator&gt;&gt;,然后将该方法注册到过滤器工厂。

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

      【讨论】:

        【解决方案5】:

        原因可能是您不应该将数据写入 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;
        }
        

        【讨论】:

          猜你喜欢
          • 2021-12-26
          • 2023-03-15
          • 1970-01-01
          • 2018-05-26
          • 1970-01-01
          • 2021-11-28
          • 1970-01-01
          • 1970-01-01
          • 2015-10-07
          相关资源
          最近更新 更多