@@ -76,15 +76,16 @@ bool BCLog::Logger::StartLogging()
7676 LogPrintStr_ (strprintf (" Early logging buffer overflowed, %d log lines discarded.\n " , m_buffer_lines_discarded), __func__, __FILE__, __LINE__, BCLog::ALL, Level::Info);
7777 }
7878 while (!m_msgs_before_open.empty ()) {
79- const std::string& s = m_msgs_before_open.front ();
79+ const auto & buflog = m_msgs_before_open.front ();
80+ std::string s{buflog.str };
81+ FormatLogStrInPlace (s, buflog.category , buflog.level , buflog.source_file , buflog.source_line , buflog.logging_function , buflog.threadname , buflog.now , buflog.mocktime );
82+ m_msgs_before_open.pop_front ();
8083
8184 if (m_print_to_file) FileWriteStr (s, m_fileout);
8285 if (m_print_to_console) fwrite (s.data (), 1 , s.size (), stdout);
8386 for (const auto & cb : m_print_callbacks) {
8487 cb (s);
8588 }
86-
87- m_msgs_before_open.pop_front ();
8889 }
8990 m_cur_buffer_memusage = 0 ;
9091 if (m_print_to_console) fflush (stdout);
@@ -298,28 +299,23 @@ std::string BCLog::Logger::LogLevelsString() const
298299 return Join (std::vector<BCLog::Level>{levels.begin (), levels.end ()}, " , " , [](BCLog::Level level) { return LogLevelToStr (level); });
299300}
300301
301- std::string BCLog::Logger::LogTimestampStr (const std::string& str)
302+ std::string BCLog::Logger::LogTimestampStr (SystemClock::time_point now, std::chrono::seconds mocktime) const
302303{
303304 std::string strStamped;
304305
305306 if (!m_log_timestamps)
306- return str;
307-
308- if (m_started_new_line) {
309- const auto now{SystemClock::now ()};
310- const auto now_seconds{std::chrono::time_point_cast<std::chrono::seconds>(now)};
311- strStamped = FormatISO8601DateTime (TicksSinceEpoch<std::chrono::seconds>(now_seconds));
312- if (m_log_time_micros && !strStamped.empty ()) {
313- strStamped.pop_back ();
314- strStamped += strprintf (" .%06dZ" , Ticks<std::chrono::microseconds>(now - now_seconds));
315- }
316- std::chrono::seconds mocktime = GetMockTime ();
317- if (mocktime > 0s) {
318- strStamped += " (mocktime: " + FormatISO8601DateTime (count_seconds (mocktime)) + " )" ;
319- }
320- strStamped += ' ' + str;
321- } else
322- strStamped = str;
307+ return strStamped;
308+
309+ const auto now_seconds{std::chrono::time_point_cast<std::chrono::seconds>(now)};
310+ strStamped = FormatISO8601DateTime (TicksSinceEpoch<std::chrono::seconds>(now_seconds));
311+ if (m_log_time_micros && !strStamped.empty ()) {
312+ strStamped.pop_back ();
313+ strStamped += strprintf (" .%06dZ" , Ticks<std::chrono::microseconds>(now - now_seconds));
314+ }
315+ if (mocktime > 0s) {
316+ strStamped += " (mocktime: " + FormatISO8601DateTime (count_seconds (mocktime)) + " )" ;
317+ }
318+ strStamped += ' ' ;
323319
324320 return strStamped;
325321}
@@ -372,9 +368,24 @@ std::string BCLog::Logger::GetLogPrefix(BCLog::LogFlags category, BCLog::Level l
372368 return s;
373369}
374370
375- static size_t MemUsage (const std::string& str )
371+ static size_t MemUsage (const BCLog::Logger::BufferedLog& buflog )
376372{
377- return str.size () + memusage::MallocUsage (sizeof (memusage::list_node<std::string>));
373+ return buflog.str .size () + buflog.logging_function .size () + buflog.source_file .size () + buflog.threadname .size () + memusage::MallocUsage (sizeof (memusage::list_node<BCLog::Logger::BufferedLog>));
374+ }
375+
376+ void BCLog::Logger::FormatLogStrInPlace (std::string& str, BCLog::LogFlags category, BCLog::Level level, const std::string& source_file, int source_line, const std::string& logging_function, const std::string& threadname, SystemClock::time_point now, std::chrono::seconds mocktime) const
377+ {
378+ str.insert (0 , GetLogPrefix (category, level));
379+
380+ if (m_log_sourcelocations) {
381+ str.insert (0 , " [" + RemovePrefix (source_file, " ./" ) + " :" + ToString (source_line) + " ] [" + logging_function + " ] " );
382+ }
383+
384+ if (m_log_threadnames) {
385+ str.insert (0 , " [" + (threadname.empty () ? " unknown" : threadname) + " ] " );
386+ }
387+
388+ str.insert (0 , LogTimestampStr (now, mocktime));
378389}
379390
380391void BCLog::Logger::LogPrintStr (const std::string& str, const std::string& logging_function, const std::string& source_file, int source_line, BCLog::LogFlags category, BCLog::Level level)
@@ -387,28 +398,37 @@ void BCLog::Logger::LogPrintStr_(const std::string& str, const std::string& logg
387398{
388399 std::string str_prefixed = LogEscapeMessage (str);
389400
390- if (m_started_new_line) {
391- str_prefixed.insert (0 , GetLogPrefix (category, level));
392- }
393-
394- if (m_log_sourcelocations && m_started_new_line) {
395- str_prefixed.insert (0 , " [" + RemovePrefix (source_file, " ./" ) + " :" + ToString (source_line) + " ] [" + logging_function + " ] " );
396- }
397-
398- if (m_log_threadnames && m_started_new_line) {
399- const auto & threadname = util::ThreadGetInternalName ();
400- str_prefixed.insert (0 , " [" + (threadname.empty () ? " unknown" : threadname) + " ] " );
401- }
402-
403- str_prefixed = LogTimestampStr (str_prefixed);
404-
401+ const bool starts_new_line = m_started_new_line;
405402 m_started_new_line = !str.empty () && str[str.size ()-1 ] == ' \n ' ;
406403
407404 if (m_buffering) {
408- // buffer if we haven't started logging yet
409- m_msgs_before_open.push_back (str_prefixed);
405+ if (!starts_new_line) {
406+ if (!m_msgs_before_open.empty ()) {
407+ m_msgs_before_open.back ().str += str_prefixed;
408+ m_cur_buffer_memusage += str_prefixed.size ();
409+ return ;
410+ } else {
411+ // unlikely edge case; add a marker that something was trimmed
412+ str_prefixed.insert (0 , " [...] " );
413+ }
414+ }
415+
416+ {
417+ BufferedLog buf{
418+ .now =SystemClock::now (),
419+ .mocktime =GetMockTime (),
420+ .str =str_prefixed,
421+ .logging_function =logging_function,
422+ .source_file =source_file,
423+ .threadname =util::ThreadGetInternalName (),
424+ .source_line =source_line,
425+ .category =category,
426+ .level =level,
427+ };
428+ m_cur_buffer_memusage += MemUsage (buf);
429+ m_msgs_before_open.push_back (std::move (buf));
430+ }
410431
411- m_cur_buffer_memusage += MemUsage (str_prefixed);
412432 while (m_cur_buffer_memusage > m_max_buffer_memusage) {
413433 if (m_msgs_before_open.empty ()) {
414434 m_cur_buffer_memusage = 0 ;
@@ -418,9 +438,14 @@ void BCLog::Logger::LogPrintStr_(const std::string& str, const std::string& logg
418438 m_msgs_before_open.pop_front ();
419439 ++m_buffer_lines_discarded;
420440 }
441+
421442 return ;
422443 }
423444
445+ if (starts_new_line) {
446+ FormatLogStrInPlace (str_prefixed, category, level, source_file, source_line, logging_function, util::ThreadGetInternalName (), SystemClock::now (), GetMockTime ());
447+ }
448+
424449 if (m_print_to_console) {
425450 // print to console
426451 fwrite (str_prefixed.data (), 1 , str_prefixed.size (), stdout);
0 commit comments