text_multifile_backend 如何为文件名设置动态日期
Posted
技术标签:
【中文标题】text_multifile_backend 如何为文件名设置动态日期【英文标题】:text_multifile_backend how to set dynamic date for file name 【发布时间】:2018-12-17 23:36:51 【问题描述】:我尝试为我的 boost 多文件记录器设置动态日期,以将每天的日志文件分隔在不同的文件中,如下所示:'log___2018-07-10__172.17.18.199.log'。
我不想将代码中每个函数的日期设置为 BOOST_LOG_SCOPED_THREAD_TAG!
我希望 boost 核心记录器能够做到这一点,我只想在全局属性中设置本地时钟,但我不知道该怎么做。 这是我的代码:
#include <boost/shared_ptr.hpp>
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/common.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_multifile_backend.hpp>
#include <boost/log/support/date_time.hpp>
enum SeverityLevel
TRACE,
DEBUG,
WARNING,
INFO,
ERROR,
FATAL
;
enum
THREAD_COUNT = 5,
LOG_RECORDS_TO_WRITE = 10
;
boost::log::sources::severity_logger_mt< SeverityLevel > myLogger;
#define LOG_ERROR BOOST_LOG_SEV(myLogger, ERROR)
#define LOG_FATAL BOOST_LOG_SEV(myLogger, FATAL)
#define LOG_INFO BOOST_LOG_SEV(myLogger, INFO)
#define LOG_WARNING BOOST_LOG_SEV(myLogger, WARNING)
#define LOG_DEBUG BOOST_LOG_SEV(myLogger, DEBUG)
#define LOG_TRACE BOOST_LOG_SEV(myLogger, TRACE)
// This function is executed in a separate thread
void thread_fooMain()
BOOST_LOG_NAMED_SCOPE("thread_fooMain");
for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
LOG_ERROR << "Log record " << i;
void thread_foo2()
BOOST_LOG_SCOPED_THREAD_TAG("TerminalIP", "172.17.18.102");
BOOST_LOG_NAMED_SCOPE("thread_fooMain");
for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
LOG_TRACE << "Log record " << i;
void thread_foo3()
BOOST_LOG_SCOPED_THREAD_TAG("TerminalIP", "172.17.18.103");
BOOST_LOG_NAMED_SCOPE("thread_fooMain");
for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
LOG_INFO << "Log record " << i;
void thread_foo4()
BOOST_LOG_SCOPED_THREAD_TAG("TerminalIP", "172.17.18.104");
BOOST_LOG_NAMED_SCOPE("thread_fooMain");
for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
LOG_INFO << "Log record " << i;
void thread_foo5()
BOOST_LOG_SCOPED_THREAD_TAG("TerminalIP", "172.17.18.105");
BOOST_LOG_NAMED_SCOPE("thread_fooMain");
for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
LOG_INFO << "Log record " << i;
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", SeverityLevel)
BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "Timestamp", boost::posix_time::ptime)
BOOST_LOG_ATTRIBUTE_KEYWORD(dateStream, "DateStream", boost::posix_time::ptime)
BOOST_LOG_ATTRIBUTE_KEYWORD(thread_id, "ThreadID", boost::log::attributes::current_thread_id::value_type)
// The operator puts a human-friendly representation of the severity level to the stream
std::ostream & operator<< (std::ostream & strm, SeverityLevel level)
static const char* strings[] =
"TRACE",
"DEBUG",
"WARNING",
"INFO",
"ERROR",
"FATAL"
;
if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
strm << strings[level];
else
strm << static_cast< int >(level);
return strm;
int main(int argc, char* argv[])
try
// Create a text file sink
typedef boost::log::sinks::synchronous_sink< boost::log::sinks::text_multifile_backend > file_sink;
boost::shared_ptr< file_sink > sink(new file_sink);
// Set up how the file names will be generated
sink->locked_backend()->set_file_name_composer(
boost::log::sinks::file::as_file_name_composer(
boost::log::expressions::stream <<
"log/log_" <<
boost::log::expressions::format_date_time(dateStream, "__%Y_%m_%d__") <<
boost::log::expressions::attr< std::string >("TerminalIP") <<
".log"
)
);
sink->set_formatter
(
boost::log::expressions::stream <<
boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "[%Y/%m/%d %H:%M:%S.%f]") <<
"<" << severity << ">" <<
"[" << thread_id << "]:" <<
"<" << boost::log::expressions::format_named_scope("Scope", boost::log::keywords::format = "%n") << "> " <<
boost::log::expressions::smessage
);
// Add it to the core
boost::log::core::get()->add_sink(sink);
boost::log::core::get()->set_filter
(
severity >= WARNING
);
// Add some attributes too
boost::log::core::get()->add_global_attribute("TimeStamp", boost::log::attributes::local_clock());
boost::log::core::get()->add_global_attribute("DateStream", boost::log::attributes::local_clock());
boost::log::core::get()->add_global_attribute("Scope", boost::log::attributes::named_scope());
boost::log::core::get()->add_global_attribute("ThreadID", boost::log::attributes::current_thread_id());
// Create threads and make some logs
boost::thread_group threads;
threads.create_thread(&thread_fooMain);
threads.create_thread(&thread_foo2);
threads.create_thread(&thread_foo3);
threads.create_thread(&thread_foo4);
threads.create_thread(&thread_foo5);
threads.join_all();
return 0;
catch (std::exception& e)
std::cout << "FAILURE: " << e.what() << std::endl;
return 1;
但出现此链接器错误:
ErrorC2664 'boost::log::v2s_mt_nt6::aux::light_function<void (boost::log::v2s_mt_nt6::basic_formatting_ostream<char,std::char_traits<char>,std::allocator<char>> &,const boost::posix_time::ptime &)>::result_type boost::log::v2s_mt_nt6::aux::light_function<void (boost::log::v2s_mt_nt6::basic_formatting_ostream<char,std::char_traits<char>,std::allocator<char>> &,const boost::posix_time::ptime &)>::operator ()(boost::log::v2s_mt_nt6::basic_formatting_ostream<char,std::char_traits<char>,std::allocator<char>> &,const boost::posix_time::ptime &) const':
cannot convert argument 1 from 'boost::log::v2s_mt_nt6::basic_formatting_ostream<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t>>' to 'boost::log::v2s_mt_nt6::basic_formatting_ostream<char,std::char_traits<char>,std::allocator<char>> &' sample.boost.asio e:\programming\c++\boost libraries\boost_1_66_0\boost\log\utility\functional\bind.hpp 93
谁能解释一下为什么会这样?
【问题讨论】:
使用 boost 1.69 版,我可以毫无错误地编译并按照您指定的日期创建日志文件.. 【参考方案1】:在 Windows 中
boost::log::expressions::format_date_time<boost::posix_time::ptime,wchar_t>("TimeStamp",L"__%Y_%m_%d__")
在 Unix 中
boost::log::expressions::format_date_time<boost::posix_time::ptime>("TimeStamp","__%Y_%m_%d__")
参见 text_multifile_backend.hpp
必不可少的是typedef filesystem::path result_type;
【讨论】:
以上是关于text_multifile_backend 如何为文件名设置动态日期的主要内容,如果未能解决你的问题,请参考以下文章