1

I try to set dynamic date for my boost multi-file logger to separate log files for everyday in different files like this :'log___2018-07-10__172.17.18.199.log'.

I don't want to set the date in each functions in my code a BOOST_LOG_SCOPED_THREAD_TAG!

I want the boost core logger to do that and I just want to set local clock in global attributes, but I do NOT know how to do that. Here is me code:

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

but got this linker error:

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  

Can anyone explain to me why this happened?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • With boost version 1.69 I could compile without any errors and create the log files as you specified with the date in them.. – jav Apr 17 '19 at 06:30

1 Answers1

0

In Windows

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

In Unix

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

See text_multifile_backend.hpp

The essential is typedef filesystem::path result_type;

Alexey Usharovski
  • 1,404
  • 13
  • 31