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&lt;boost::posix_time::ptime,wchar_t&gt;("TimeStamp",L"__%Y_%m_%d__")

在 Unix 中

boost::log::expressions::format_date_time&lt;boost::posix_time::ptime&gt;("TimeStamp","__%Y_%m_%d__")

参见 text_multifile_backend.hpp

必不可少的是typedef filesystem::path result_type;

【讨论】:

以上是关于text_multifile_backend 如何为文件名设置动态日期的主要内容,如果未能解决你的问题,请参考以下文章

Markdown公式用法大全

shell编程-如何定义函数如何调用函数如何调试shell

[精选] Mysql分表与分库如何拆分,如何设计,如何使用

四连问:前后端分离接口应该如何设计?如何保证安全?如何签名?如何防重?

集合元素如何添加?如何删除?如何遍历?

2021-10-16 如何如何如何。