我实现了一个接收器,它将记录记录到std :: vector并在调用flush函数时将所有日志刷新到控制台。我根据以下内容添加了四个属性:
BOOST_LOG_ATTRIBUTE_KEYWORD(a_timestamp, "TimeStamp", boost::log::attributes::local_clock::value_type)
BOOST_LOG_ATTRIBUTE_KEYWORD(a_severity, "Severity", boost::log::trivial::severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(a_file, "File", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(a_line, "Line", std::string)
但是,当我使用set_formatter函数时,出现编译器错误(MSVC17),提示:
错误C2679二进制'<<':未找到使用右手的运算符 'const T'类型的操作数(或者没有可接受的值) 转换)ControllerSoftware c:\ local \ boost_1_68_0 \ boost \ log \ utility \ formatting_ostream.hpp 870
为了清楚起见,我将提供完整的代码:
// cswlogger.h
#pragma once
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/attributes/mutable_constant.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/sources/global_logger_storage.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>
#include <boost/log/core.hpp>
#include <boost/log/sinks/basic_sink_backend.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <vector>
#include <string>
namespace sinks = boost::log::sinks;
BOOST_LOG_GLOBAL_LOGGER(sysLogger,
boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level>);
class CswLogger
{
public:
/// Init with default info level logging
static void init(bool useRamLog = false, boost::log::trivial::severity_level level = boost::log::trivial::info);
/// Disable logging
static void disable();
// Flush log
static void flushLogs();
// Convert file path to only the filename
static std::string path_to_filename(std::string path)
{
return path.substr(path.find_last_of("/\\") + 1);
}
private:
static void registerRamLog();
};
class RamLogSink :
public sinks::basic_formatted_sink_backend<
char,
sinks::combine_requirements<
sinks::synchronized_feeding,
sinks::flushing
>::type
>
{
public:
// The function consumes the log records that come from the frontend
void consume(boost::log::record_view const& rec, string_type const& strType);
// The function flushes the logs in vector
void flush();
private:
std::vector<std::string> logEntries_;
};
// Complete sink type
typedef sinks::synchronous_sink< RamLogSink > sink_t;
#define LOG_LOG_LOCATION(LOGGER, LEVEL, ARG) \
BOOST_LOG_SEV(LOGGER, boost::log::trivial::LEVEL) \
<< boost::log::add_value("Line", std::to_string(__LINE__)) \
<< boost::log::add_value("File", CswLogger::path_to_filename(__FILE__)) << ARG
// System Log macros.
// TRACE < DEBUG < INFO < WARN < ERROR < FATAL
#define LOG_TRACE(ARG) LOG_LOG_LOCATION(sysLogger::get(), trace, ARG);
#define LOG_DEBUG(ARG) LOG_LOG_LOCATION(sysLogger::get(), debug, ARG);
#define LOG_INFO(ARG) LOG_LOG_LOCATION(sysLogger::get(), info, ARG);
#define LOG_WARN(ARG) LOG_LOG_LOCATION(sysLogger::get(), warning, ARG);
#define LOG_ERROR(ARG) LOG_LOG_LOCATION(sysLogger::get(), error, ARG);
#define LOG_FATAL(ARG) LOG_LOG_LOCATION(sysLogger::get(), fatal, ARG);
源文件:
// cswlogger.cpp
#include "cswlogger.h"
#include <boost/log/core.hpp>
#include <boost/log/common.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/settings.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <string>
#include <iostream>
BOOST_LOG_GLOBAL_LOGGER_DEFAULT(sysLogger,
boost::log::sources::severity_channel_logger_mt<boost::log::trivial::severity_level>);
BOOST_LOG_ATTRIBUTE_KEYWORD(a_timestamp, "TimeStamp", boost::log::attributes::local_clock::value_type)
BOOST_LOG_ATTRIBUTE_KEYWORD(a_severity, "Severity", boost::log::trivial::severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(a_file, "File", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(a_line, "Line", std::string)
void CswLogger::init(bool useRamLog, boost::log::trivial::severity_level level)
{
boost::log::register_simple_formatter_factory<boost::log::trivial::severity_level, char>("Severity");
if (useRamLog)
{
registerRamLog();
}
else
{
boost::log::add_console_log
(
std::clog,
boost::log::keywords::format = "[%TimeStamp%] [%Severity%] %File%(%Line%): %Message%"
);
}
boost::log::add_common_attributes();
boost::log::core::get()->set_filter
(
boost::log::trivial::severity >= level
);
// Indicate start of logging
LOG_INFO("Log Start");
}
void CswLogger::disable()
{
boost::log::core::get()->set_logging_enabled(false);
}
void CswLogger::flushLogs()
{
boost::log::core::get()->flush();
}
void CswLogger::registerRamLog()
{
boost::shared_ptr< RamLogSink > backend(new RamLogSink());
boost::shared_ptr< sink_t > sink(new sink_t(backend));
sink->set_formatter(boost::log::expressions::stream
<< "[" << a_timestamp << "] " // <--- Compile error here
<< "[" << a_severity << "] "
<< "[" << a_file << "(" << a_line << ")] "
<< boost::log::expressions::message);
boost::log::core::get()->add_sink(sink);
}
// RamlogSink Class declarations
void RamLogSink::consume(boost::log::record_view const& rec, string_type const& strType)
{
logEntries_.emplace_back(strType);
}
void RamLogSink::flush()
{
for (auto const& entry : logEntries_)
{
std::cout << entry << std::endl;
}
logEntries_.clear();
}
main.cpp:
#include "cswlogger.h"
CswLogger::init(true);
LOG_TRACE("This should not be printed");
LOG_ERROR("Very bad error that needs to be printed");
int theInt = 234;
LOG_FATAL("TheInt integer is: " << theInt);
CswLogger::flushLogs();
在添加“ Line”属性时,我也遇到了问题:
BOOST_LOG_ATTRIBUTE_KEYWORD(a_line, "Line", int)
我不得不更改为std :: string并将整数转换为
#define LOG_LOG_LOCATION(LOGGER, LEVEL, ARG) \
BOOST_LOG_SEV(LOGGER, boost::log::trivial::LEVEL) \
<< boost::log::add_value("Line", std::to_string(__LINE__)) \
<< boost::log::add_value("File", CswLogger::path_to_filename(__FILE__)) << ARG
否则,行号以空字符串形式出现。