Search code examples
c++boost-log

How to use timestamp and use string of severity?


  1. I used official code for sink formatting that succeded
    sink.set_formatter    (
        expr::stream
        << "[ "
        << expr::format_date_time<boost::posix_time::ptime>("TimeStamp","%H:%M:%S.%f")
        << " - " << severity << " ] "
        << expr::smessage
    )

But the ouput is [%time% - 1 ] %message%. And the severity is just output as int

But I wanted result of [%time% - debug ] %message%.

I used severity_logger_mt<SeverityLevel> with Severity just an enum


  1. I tried to convert Severity myself by supplying sink::set_formatter a function, the complied errors and output is shown in code:
void coloring_formatter(const boost::log::record_view& record,
                            boost::log::formatting_ostream& stream)
{

  stream << "["
    /* !!! ERROR !!! with no acceptable convertor for <<   */
    << record[timestamp]    

   /*!!! compile ERROR !!! no matching function call for format_date_time */
   << expr::format_date_time<
                    boost::posix_time::ptime>(timestamp, "%Y-%m-%d %H:%M:%S")

   /*!!! complied done but with no time stamp output !!!  */
<< boost::log::expressions::format_date_time<
                    boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d %H:%M:%S")
             << " - " << type << "] "
             << record[boost::log::expressions::smessage];
    }

Could anyone help me with

  1. right "timestamp" output in function of sink::set_formatter

  2. output string of Severity instead of int


Solution

    1. The code you presented is incomplete. In the formatter expression, severity has to be an attribute keyword for it to extract severity levels from log records. It is not clear what it is in your case, I suspect it may be a constant, which is output into a stream regardless of the actual severity level attached to log records.

    2. The coloring_formatter function is incorrect as it tries to use formatter lambda expressions like expr::format_date_time with an actual stream.

    You have to understand the difference between a lambda expression a.k.a. lazy expression (which constructs a function to be called at a later time; when that function is called with a stream, it will perform formatting) and an actual streaming expression, which produces output in the stream as it is being executed. expr::format_date_time and other components from boost::log::expressions namespace are used to compose lambda expressions for filters and formatters. They cannot be used in actual stream output expressions.

    When you call sink.set_formatter, you have to provide a function, which will perform log record formatting when called. There are multiple ways to describe that function. One way is to use a lambda expression, like in your case #1, starting with expr::stream or expr::format. Another way is to write the function from scratch, like in your case #2, but in that function you can no longer use lambda expressions.

    You can see Boost.Log examples (for instance, here, here or here) for how to format date/time and severity levels. The important parts to note about those examples:

    • There is an operator<< for the severity level type, which performs conversion from the enum to a string. This operator must be in the same namespace as the enum, otherwise the compiler won't find it and will output the enum as an integer.
    • The severity level enum must be used in the logger type as its template parameter. This way you will ensure that log records will have severity levels with the type of the enum.
    • The severity level enum must be used in the formatter, where you specify the severity level. When you use expr::attr, it must be in the template parameter, when you use a keyword, it must be part of the keyword definition with BOOST_LOG_ATTRIBUTE_KEYWORD. This will ensure the formatter is able to extract your enum from the log record when the formatter is called.
    • When formatting a date/time, expr::format_date_time can only be used in a lambda expression. When you write your formatting function from scratch, you have to use Boost.DateTime or functions like strftime to format the timestamp.