logging: pass log::Entry through to logging functions
What changed, and why it matters
This commit is a straightforward internal code cleanup in Bitcoin Core's logging system. It bundles log details (timestamp, thread name, message, category, etc.) into a single struct called log::Entry and passes that struct around instead of many separate arguments. There is no security fix or behavior change visible in the diff.
No security action required. Treat as normal code-quality refactor during review.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors BCLog::Logger so that LogPrintStr()/LogPrintStr_() are replaced by LogPrint()/LogPrint_() taking a util::log::Entry object. The key functional difference is that the timestamp and thread_name are now captured at the call site (inside util::log::Log) and preserved through buffering and formatting, rather than being re-captured inside the logger. This is a correctness/consistency improvement for buffered early logs and for any future callers, but it does not alter access control, trust boundaries, or parsing of untrusted data. No security vulnerability is addressed.
Changed components
src/logging.cppsrc/logging.hsrc/test/logging_tests.cppInspect captured patch +43 / −33
diff --git a/src/logging.cpp b/src/logging.cpp
index bfd48c96..78b34f38 100644
--- a/src/logging.cpp
+++ b/src/logging.cpp
@@ -75,7 +75,13 @@ bool BCLog::Logger::StartLogging()
// dump buffered messages from before we opened the log
m_buffering = false;
if (m_buffer_lines_discarded > 0) {
- LogPrintStr_(strprintf("Early logging buffer overflowed, %d log lines discarded.\n", m_buffer_lines_discarded), SourceLocation{__func__}, BCLog::ALL, Level::Info, /*should_ratelimit=*/false);
+ LogPrint_({
+ .category = BCLog::ALL,
+ .level = Level::Info,
+ .should_ratelimit = false,
+ .source_loc = SourceLocation{__func__},
+ .message = strprintf("Early logging buffer overflowed, %d log lines discarded.", m_buffer_lines_discarded),
+ });
}
while (!m_msgs_before_open.empty()) {
const auto& buflog = m_msgs_before_open.front();
@@ -421,28 +427,29 @@ void BCLog::Logger::FormatLogStrInPlace(std::string& str, BCLog::LogFlags catego
str.insert(0, LogTimestampStr(now, mocktime));
}
-void BCLog::Logger::LogPrintStr(std::string_view str, SourceLocation&& source_loc, BCLog::LogFlags category, BCLog::Level level, bool should_ratelimit)
+void BCLog::Logger::LogPrint(util::log::Entry entry)
{
STDLOCK(m_cs);
- return LogPrintStr_(str, std::move(source_loc), category, level, should_ratelimit);
+ return LogPrint_(std::move(entry));
}
// NOLINTNEXTLINE(misc-no-recursion)
-void BCLog::Logger::LogPrintStr_(std::string_view str, SourceLocation&& source_loc, BCLog::LogFlags category, BCLog::Level level, bool should_ratelimit)
+void BCLog::Logger::LogPrint_(util::log::Entry entry)
{
- std::string str_prefixed = LogEscapeMessage(str);
+ std::string str_prefixed = LogEscapeMessage(entry.message);
if (m_buffering) {
{
BufferedLog buf{
- .now = SystemClock::now(),
+ .now = entry.timestamp,
.mocktime = GetMockTime(),
- .str = str_prefixed,
- .threadname = util::ThreadGetInternalName(),
- .source_loc = std::move(source_loc),
- .category = category,
- .level = level,
+ .str = std::move(str_prefixed),
+ .threadname = std::move(entry.thread_name),
+ .source_loc = entry.source_loc,
+ .category = static_cast<LogFlags>(entry.category),
+ .level = entry.level,
};
+ (void)std::move(entry);
m_cur_buffer_memusage += MemUsage(buf);
m_msgs_before_open.push_back(std::move(buf));
}
@@ -460,21 +467,26 @@ void BCLog::Logger::LogPrintStr_(std::string_view str, SourceLocation&& source_l
return;
}
- FormatLogStrInPlace(str_prefixed, category, level, source_loc, util::ThreadGetInternalName(), SystemClock::now(), GetMockTime());
+ FormatLogStrInPlace(str_prefixed, static_cast<LogFlags>(entry.category), entry.level, entry.source_loc, entry.thread_name, entry.timestamp, GetMockTime());
bool ratelimit{false};
- if (should_ratelimit && m_limiter) {
- auto status{m_limiter->Consume(source_loc, str_prefixed)};
+ if (entry.should_ratelimit && m_limiter) {
+ auto status{m_limiter->Consume(entry.source_loc, str_prefixed)};
if (status == LogRateLimiter::Status::NEWLY_SUPPRESSED) {
// NOLINTNEXTLINE(misc-no-recursion)
- LogPrintStr_(strprintf(
- "Excessive logging detected from %s:%d (%s): >%d bytes logged during "
- "the last time window of %is. Suppressing logging to disk from this "
- "source location until time window resets. Console logging "
- "unaffected. Last log entry.",
- source_loc.file_name(), source_loc.line(), source_loc.function_name_short(),
- m_limiter->m_max_bytes,
- Ticks<std::chrono::seconds>(m_limiter->m_reset_window)),
- SourceLocation{__func__}, LogFlags::ALL, Level::Warning, /*should_ratelimit=*/false); // with should_ratelimit=false, this cannot lead to infinite recursion
+ LogPrint_({
+ .category = LogFlags::ALL,
+ .level = Level::Warning,
+ .should_ratelimit = false, // with should_ratelimit=false, this cannot lead to infinite recursion
+ .source_loc = SourceLocation{__func__},
+ .message = strprintf(
+ "Excessive logging detected from %s:%d (%s): >%d bytes logged during "
+ "the last time window of %is. Suppressing logging to disk from this "
+ "source location until time window resets. Console logging "
+ "unaffected. Last log entry.",
+ entry.source_loc.file_name(), entry.source_loc.line(), entry.source_loc.function_name_short(),
+ m_limiter->m_max_bytes,
+ Ticks<std::chrono::seconds>(m_limiter->m_reset_window)),
+ });
} else if (status == LogRateLimiter::Status::STILL_SUPPRESSED) {
ratelimit = true;
}
@@ -612,6 +624,6 @@ void util::log::Log(util::log::Entry entry)
{
BCLog::Logger& logger{LogInstance()};
if (logger.Enabled()) {
- logger.LogPrintStr(std::move(entry.message), std::move(entry.source_loc), static_cast<BCLog::LogFlags>(entry.category), entry.level, entry.should_ratelimit);
+ logger.LogPrint(std::move(entry));
}
}
diff --git a/src/logging.h b/src/logging.h
index 005c67fd..c871a9d8 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -164,11 +164,10 @@ namespace BCLog {
std::string LogTimestampStr(SystemClock::time_point now, std::chrono::seconds mocktime) const;
/** Slots that connect to the print signal */
- std::list<std::function<void(const std::string&)>> m_print_callbacks GUARDED_BY(m_cs) {};
+ std::list<std::function<void(const std::string&)>> m_print_callbacks GUARDED_BY(m_cs){};
- /** Send a string to the log output (internal) */
- void LogPrintStr_(std::string_view str, SourceLocation&& source_loc, BCLog::LogFlags category, BCLog::Level level, bool should_ratelimit)
- EXCLUSIVE_LOCKS_REQUIRED(m_cs);
+ /** Send an entry to the log output (internal) */
+ void LogPrint_(util::log::Entry log_entry) EXCLUSIVE_LOCKS_REQUIRED(m_cs);
std::string GetLogPrefix(LogFlags category, Level level) const;
@@ -185,9 +184,8 @@ namespace BCLog {
fs::path m_file_path;
std::atomic<bool> m_reopen_file{false};
- /** Send a string to the log output */
- void LogPrintStr(std::string_view str, SourceLocation&& source_loc, BCLog::LogFlags category, BCLog::Level level, bool should_ratelimit)
- EXCLUSIVE_LOCKS_REQUIRED(!m_cs);
+ /** Send an entry to the log output */
+ void LogPrint(util::log::Entry log_entry) EXCLUSIVE_LOCKS_REQUIRED(!m_cs);
/** Returns whether logs will be written to any output */
bool Enabled() const EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
diff --git a/src/test/logging_tests.cpp b/src/test/logging_tests.cpp
index f232bb41..223615df 100644
--- a/src/test/logging_tests.cpp
+++ b/src/test/logging_tests.cpp
@@ -110,7 +110,7 @@ BOOST_AUTO_TEST_CASE(logging_timer)
BOOST_CHECK_EQUAL(micro_timer.LogMsg("msg").substr(0, result_prefix.size()), result_prefix);
}
-BOOST_FIXTURE_TEST_CASE(logging_LogPrintStr, LogSetup)
+BOOST_FIXTURE_TEST_CASE(logging_LogPrint, LogSetup)
{
LogInstance().m_log_sourcelocations = true;
@@ -134,7 +134,7 @@ BOOST_FIXTURE_TEST_CASE(logging_LogPrintStr, LogSetup)
std::vector<std::string> expected;
for (auto& [msg, category, level, prefix, loc] : cases) {
expected.push_back(tfm::format("[%s:%s] [%s] %s%s", util::RemovePrefix(loc.file_name(), "./"), loc.line(), loc.function_name_short(), prefix, msg));
- LogInstance().LogPrintStr(msg, std::move(loc), category, level, /*should_ratelimit=*/false);
+ LogInstance().LogPrint({.category = category, .level = level, .should_ratelimit = false, .source_loc = std::move(loc), .message = msg});
}
std::vector<std::string> log_lines{ReadDebugLogLines()};
BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.