c++boostboost-log

Missed timestamp in Boost.Log


I'm new in Boost.Log. I'd like to print out data in the following format: [TimeStamp][Severity] Message.

I have such code

auto my_formatter = [](boost::log::record_view const& rec, boost::log::formatting_ostream& strm)
{
    strm << "[" << boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S") << "]";
    strm << "[" << rec[boost::log::trivial::severity] << "] ";
    strm << rec[boost::log::expressions::smessage];
};

void addFileSink()
{
    using sinkType = boost::log::sinks::synchronous_sink<boost::log::sinks::text_file_backend>;

    auto backend = boost::make_shared<boost::log::sinks::text_file_backend>(
        boost::log::keywords::file_name = "log_%N.log",
        boost::log::keywords::rotation_size = 10 * 1024 * 1024,
        boost::log::keywords::open_mode = std::ios_base::app
    );

    boost::shared_ptr<sinkType> sink(new sinkType(backend));
    sink->set_formatter(my_formatter);
    sink->set_filter(boost::log::trivial::severity >= boost::log::trivial::severity_level::info);
    boost::log::core::get()->add_sink(sink);
}

void addConsoleSink()
{
    using sinkType = boost::log::sinks::synchronous_sink<boost::log::sinks::text_ostream_backend>;

    auto backend = boost::make_shared<boost::log::sinks::text_ostream_backend>();
    backend->add_stream(boost::shared_ptr<std::ostream>(&std::cout, boost::null_deleter()));
    backend->auto_flush(true);

    boost::shared_ptr<sinkType> sink(new sinkType(backend));
    sink->set_formatter(my_formatter);
    sink->set_filter(boost::log::trivial::severity >= boost::log::trivial::severity_level::error);
    boost::log::core::get()->add_sink(sink);
}

int main()
{
    boost::log::add_common_attributes();

    addFileSink();
    addConsoleSink();

    boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg;

    BOOST_LOG_SEV(lg, boost::log::trivial::severity_level::error) << "Message error";
    BOOST_LOG_SEV(lg, boost::log::trivial::severity_level::info) << "Message info";

    return 0;
}

It works fine beside of TimeStamp attribute, I'm getting such output:

[[error] Message error

I've tried different ways from examples and so on, but I can't find solution for this problem.. boost::log::add_common_attributes(); doesn't help.


Solution

  • boost::log::expressions::format_date_time is not a function to format date and time. It is a formatter generator to be used in lambda formatting expressions. In other words, format_date_time creates a formatter (a function object with a specific signature), which, upon calling, will extract the attribute value from the log record and format it.

    You should either use lambda expressions to build the formatter instead of your my_formatter function, in which case you can use format_date_time, or use one of the traditional methods of formatting date and time, like strftime or Boost.DateTime IO.

    Example of using the lambda expressions:

    namespace expr = boost::log::expressions;
    
    sink->set_formatter
    (
        expr::stream
            << "[" << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S") << "]"
            << "[" << boost::log::trivial::severity << "] "
            << expr::smessage
    );
    

    Example of using strftime:

    auto my_formatter = [](boost::log::record_view const& rec, boost::log::formatting_ostream& strm)
    {
        if (auto timestamp = boost::log::extract< boost::posix_time::ptime >("TimeStamp", rec))
        {
            std::tm ts = boost::posix_time::to_tm(*timestamp);
    
            char buf[128];
            if (std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &ts) > 0)
                strm << "[" << buf << "]";
        }
    
        strm << "[" << rec[boost::log::trivial::severity] << "] ";
        strm << rec[boost::log::expressions::smessage];
    };