0

i want to prepare log message and store it in something.
then pass this something to function ,which apply << to this something putting it into BOOst_LOG macro.
i need this because i put this log to several backends using several loggers .
i read about formatting_ostream but all examples show overloading of << ,during this it takes lvalue reference to formatting_ostream. i wonder where is formatting_ostream created??.
can i do this:

boost::log::formatting_ostream os << "Request #" << this->GetId() << " for " << mUrl << " has been cancelled by the user at start of execute coroutine." << std::endl;
        boost_log_function(mHTTPRequest_LoggingInstance_shared_pointer);

then :

BOOST_LOG(*loggerChannel_cancelExecute.get()) << os;
ahmed allam
  • 377
  • 2
  • 15

1 Answers1

1

First, you don't need to output a log record in multiple loggers in order to have it processed in multiple sink backends. As long as the record is not rejected by filters, every log record is processed in all sinks, regardless of which logger was used to produce it. If you purposely arrange filters and attributes in loggers so that records from one logger are only processed in one sink (e.g. by using channels), you could also arrange them in a way that allows records from other loggers not associated with particular sinks to be processed in all sinks. This is much more efficient than generating multiple records in different loggers because it avoids overhead of creating extra log records and applying filters to them.

Now, to directly answer your question, the formatting_ostream object that is passed to various functions is created by Boost.Log. Exactly where it is created depends on the function in question. For example, the stream that is passed to formatters is created as part of the sink frontend implementation.

You can create formatting_ostream, but you need to remember the following:

  • You have to supply a string in which the formatted output will be stored in the formatting_ostream constructor. That string must stay alive for the whole lifetime of the stream object.
  • After you're done with formatting, you need to explicitly flush the stream to ensure any buffered content in the stream is pushed out into the string.
std::string str;
boost::log::formatting_ostream strm(str);
strm << "Request #" << this->GetId() << " for " << mUrl
    << " has been cancelled by the user at start of execute coroutine.";
strm.flush();

BOOST_LOG(*loggerChannel_cancelExecute.get()) << str;

However, you are not required to use formatting_ostream in the first place. You can compose the string in any way you want, including std::ostringstream, Boost.Format or even std::snprintf.

You should know though that pre-composing the message string like this may be bad for performance. If a log record is discarded by filters, the streaming expression is not evaluated at all. But your code that pre-composes the message is always evaluated, even if the log record is discarded afterwards.

Andrey Semashev
  • 10,046
  • 1
  • 17
  • 27
  • should i use method clear on formatting_ostream to prepare it for next process???is there any issues with multithreading??should i pass stream to function by pointer or reference or value?? – ahmed allam Mar 30 '20 at 13:43
  • i try to pass the stream but it gives me error of allocator inaccessible.in my code the stream is public member of class Request and it is sent to free function boost_log_function.so i try to pass `this->m-formatting_stream` but it still gives error. i think this is related to rules of passing class members?right? – ahmed allam Mar 30 '20 at 13:50
  • 1
    Sorry, I have no idea what you're doing and what is wrong. If you have further questions, you can post them as separate questions on StackOverflow. But please provide a minimal compilable code sample along with your questions. – Andrey Semashev Mar 30 '20 at 14:18