Repository: bitcoin/bitcoin
File: src/logging.cpp (C++)

Code before:

    if (m_log_threadnames && m_started_new_line) {
        const auto& threadname = util::ThreadGetInternalName();
        str_prefixed.insert(0, "[" + (threadname.empty() ? "unknown" : threadname) + "] ");
    }

    str_prefixed = LogTimestampStr(str_prefixed);

    m_started_new_line = !str.empty() && str[str.size()-1] == '\n';

    if (m_buffering) {
        // buffer if we haven't started logging yet
        m_msgs_before_open.push_back(str_prefixed);
        return;
    }

    if (m_print_to_console) {
        // print to console
        fwrite(str_prefixed.data(), 1, str_prefixed.size(), stdout);
        fflush(stdout);
    }
    for (const auto& cb : m_print_callbacks) {
        cb(str_prefixed);
    }
    if (m_print_to_file) {
        assert(m_fileout != nullptr);

        // reopen the log file, if requested
        if (m_reopen_file) {
            m_reopen_file = false;
            FILE* new_fileout = fsbridge::fopen(m_file_path, "a");
            if (new_fileout) {
                setbuf(new_fileout, nullptr); // unbuffered
                fclose(m_fileout);
                m_fileout = new_fileout;
            }
        }
        FileWriteStr(str_prefixed, m_fileout);
    }
}

void BCLog::Logger::ShrinkDebugFile()
{
    // Amount of debug.log to save at end when shrinking (must fit in memory)
    constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;

    assert(!m_file_path.empty());

    // Scroll debug.log if it's getting too big
    FILE* file = fsbridge::fopen(m_file_path, "r");


Review comment (performance):
In commit "logging: use std::string_view" (f3632d53a5be7efe61be8181ff481d30f7313bd4)

I wonder if using insert_many is actually more efficient than strprinf:

```c++
str.insert(0, strprintf("[%s:%d] [%s] ", RemovePrefix(source_file, "./"), source_line, logging_function);
```

Using strprintf seems more readable, and I suspect if we really wanted to optimize this code we probably would build up a new string rather than repeatedly inserting at the beginning of an existing string.

Code after:

    s += "] ";
    return s;
}

static size_t MemUsage(const BCLog::Logger::BufferedLog& buflog)
{
    return buflog.str.size() + buflog.logging_function.size() + buflog.source_file.size() + buflog.threadname.size() + memusage::MallocUsage(sizeof(memusage::list_node<BCLog::Logger::BufferedLog>));
}

void BCLog::Logger::FormatLogStrInPlace(std::string& str, BCLog::LogFlags category, BCLog::Level level, std::string_view source_file, int source_line, std::string_view logging_function, std::string_view threadname, SystemClock::time_point now, std::chrono::seconds mocktime) const
{
    str.insert(0, GetLogPrefix(category, level));

    if (m_log_sourcelocations) {
        str.insert(0, strprintf("[%s:%d] [%s] ", RemovePrefixView(source_file, "./"), source_line, logging_function));
    }

    if (m_log_threadnames) {
        str.insert(0, strprintf("[%s] ", (threadname.empty() ? "unknown" : threadname)));
    }

    str.insert(0, LogTimestampStr(now, mocktime));
}

void BCLog::Logger::LogPrintStr(std::string_view str, std::string_view logging_function, std::string_view source_file, int source_line, BCLog::LogFlags category, BCLog::Level level)
{
    StdLockGuard scoped_lock(m_cs);
    return LogPrintStr_(str, logging_function, source_file, source_line, category, level);
}

void BCLog::Logger::LogPrintStr_(std::string_view str, std::string_view logging_function, std::string_view source_file, int source_line, BCLog::LogFlags category, BCLog::Level level)
{
    std::string str_prefixed = LogEscapeMessage(str);

    const bool starts_new_line = m_started_new_line;
    m_started_new_line = !str.empty() && str[str.size()-1] == '\n';

    if (m_buffering) {
        if (!starts_new_line) {
            if (!m_msgs_before_open.empty()) {
                m_msgs_before_open.back().str += str_prefixed;
                m_cur_buffer_memusage += str_prefixed.size();
                return;
            } else {
                // unlikely edge case; add a marker that something was trimmed
                str_prefixed.insert(0, "[...] ");
            }
        }

        {