Search code examples
c++boost-log

How to use Boost.Log formatting expressions in custom formatting function


I am trying to use a custom formatter with Boost.Log. The way I know how to do this is to call the set_formatter method of a sink giving it the address of a local function where the signature of the local function needs to be:

void my_formatter(boost::log::record_view const& rec, boost::log::formatting_ostream& strm)

In my_formatter I can use the Boost.Log extraction api to get the attribute values that I need. Once I get the values, I can output them to the strm. I want to do this so I can easily format some custom attributes stored in the record. But for other, more conventional Boost.Log attributes, I would like to continue to use the simple formatting expressions that are documented as keyword arguments to the set_formatter method. Is there a way to also use the keyword expressions in my_formatter custom function?

For example:

void my_formatter(boost::log::record_view const& rec, boost::log::formatting_ostream& strm)
{
    // here I can get the timestamp attribute and format its ticks value to the stream
    boost::log::value_ref<boost::posix_time::ptime> tstamp_ref =
        boost::log::extract<boost::posix_time::ptime>("TimeStamp", rec);
    const boost::posix_time::ptime& timestamp = tstamp_ref.get();

    strm << timestamp.time_of_day().ticks();
}

Then given a sink, I can call

sink->set_formatter(&my_formatter)

But Boost.Log gives me an elegant (almost magical) expression that I can use to set the formatter:

boost::log::formatter formatter =
    expr::stream
    << expr::format_date_time<boost::posix_time::ptime>(
        "TimeStamp", "%Y/%m/%d, %H:%M:%S.%f, ");

sink->set_formatter(formatter)

My question is: is there a way to use the formatter expression in my custom my_formatter function?

Thanks!


Solution

  • What you might want to do is to inject your custom parts of the formatter into the formatting expression created with Boost.Log instead of the other way around. This answer describes a way to achieve that by using phoenix::bind.