Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2009-2010 Satoshi Nakamoto2// Copyright (c) 2009-present The Bitcoin Core developers3// Distributed under the MIT software license, see the accompanying4// file COPYING or http://www.opensource.org/licenses/mit-license.php.6#include <logging.h>7#include <memusage.h>8#include <util/check.h>9#include <util/fs.h>10#include <util/string.h>11#include <util/threadnames.h>12#include <util/time.h>14#include <array>15#include <cstring>16#include <map>17#include <optional>18#include <utility>20using util::Join;21using util::RemovePrefixView;23const char * const DEFAULT_DEBUGLOGFILE = "debug.log";24constexpr auto MAX_USER_SETABLE_SEVERITY_LEVEL{BCLog::Level::Info};26BCLog::Logger& LogInstance()27{28/**29* NOTE: the logger instances is leaked on exit. This is ugly, but will be30* cleaned up by the OS/libc. Defining a logger as a global object doesn't work31* since the order of destruction of static/global objects is undefined.32* Consider if the logger gets destroyed, and then some later destructor calls33* LogInfo, maybe indirectly, and you get a core dump at shutdown trying to34* access the logger. When the shutdown sequence is fully audited and tested,35* explicit destruction of these objects can be implemented by changing this36* from a raw pointer to a std::unique_ptr.37* Since the ~Logger() destructor is never called, the Logger class and all38* its subclasses must have implicitly-defined destructors.39*40* This method of initialization was originally introduced in41* ee3374234c60aba2cc4c5cd5cac1c0aefc2d817c.42*/43static BCLog::Logger* g_logger{new BCLog::Logger()};44return *g_logger;45}47bool fLogIPs = DEFAULT_LOGIPS;49static int FileWriteStr(std::string_view str, FILE *fp)50{51return fwrite(str.data(), 1, str.size(), fp);52}54bool BCLog::Logger::StartLogging()55{56STDLOCK(m_cs);58assert(m_buffering);59assert(m_fileout == nullptr);61if (m_print_to_file) {62assert(!m_file_path.empty());63m_fileout = fsbridge::fopen(m_file_path, "a");64if (!m_fileout) {65return false;66}68setbuf(m_fileout, nullptr); // unbuffered70// Add newlines to the logfile to distinguish this execution from the71// last one.72FileWriteStr("\n\n\n\n\n", m_fileout);73}75// dump buffered messages from before we opened the log76m_buffering = false;77if (m_buffer_lines_discarded > 0) {78LogPrint_({79.category = BCLog::ALL,80.level = Level::Info,81.should_ratelimit = false,82.source_loc = SourceLocation{__func__},83.message = strprintf("Early logging buffer overflowed, %d log lines discarded.", m_buffer_lines_discarded),84});85}86while (!m_msgs_before_open.empty()) {87const auto& buflog = m_msgs_before_open.front();88std::string s{Format(buflog)};89m_msgs_before_open.pop_front();91if (m_print_to_file) FileWriteStr(s, m_fileout);92if (m_print_to_console) fwrite(s.data(), 1, s.size(), stdout);93for (const auto& cb : m_print_callbacks) {94cb(s);95}96}97m_cur_buffer_memusage = 0;98if (m_print_to_console) fflush(stdout);100return true;101}103void BCLog::Logger::DisconnectTestLogger()104{105STDLOCK(m_cs);106m_buffering = true;107if (m_fileout != nullptr) fclose(m_fileout);108m_fileout = nullptr;109m_print_callbacks.clear();110m_max_buffer_memusage = DEFAULT_MAX_LOG_BUFFER;111m_cur_buffer_memusage = 0;112m_buffer_lines_discarded = 0;113m_msgs_before_open.clear();114}116void BCLog::Logger::DisableLogging()117{118{119STDLOCK(m_cs);120assert(m_buffering);121assert(m_print_callbacks.empty());122}123m_print_to_file = false;124m_print_to_console = false;125StartLogging();126}128void BCLog::Logger::EnableCategory(BCLog::LogFlags flag)129{130m_categories |= flag;131}133bool BCLog::Logger::EnableCategory(std::string_view str)134{135if (const auto flag{GetLogCategory(str)}) {136EnableCategory(*flag);137return true;138}139return false;140}142void BCLog::Logger::DisableCategory(BCLog::LogFlags flag)143{144m_categories &= ~flag;145}147bool BCLog::Logger::DisableCategory(std::string_view str)148{149if (const auto flag{GetLogCategory(str)}) {150DisableCategory(*flag);151return true;152}153return false;154}156bool BCLog::Logger::WillLogCategory(BCLog::LogFlags category) const157{158return (m_categories.load(std::memory_order_relaxed) & category) != 0;159}161bool BCLog::Logger::WillLogCategoryLevel(BCLog::LogFlags category, BCLog::Level level) const162{163// Log messages at Info, Warning and Error level unconditionally, so that164// important troubleshooting information doesn't get lost.165if (level >= BCLog::Level::Info) return true;167if (!WillLogCategory(category)) return false;169STDLOCK(m_cs);170const auto it{m_category_log_levels.find(category)};171return level >= (it == m_category_log_levels.end() ? LogLevel() : it->second);172}174bool BCLog::Logger::DefaultShrinkDebugFile() const175{176return m_categories == BCLog::NONE;177}179static const std::map<std::string, BCLog::LogFlags, std::less<>> LOG_CATEGORIES_BY_STR{180{"net", BCLog::NET},181{"tor", BCLog::TOR},182{"mempool", BCLog::MEMPOOL},183{"http", BCLog::HTTP},184{"bench", BCLog::BENCH},185{"zmq", BCLog::ZMQ},186{"walletdb", BCLog::WALLETDB},187{"rpc", BCLog::RPC},188{"estimatefee", BCLog::ESTIMATEFEE},189{"addrman", BCLog::ADDRMAN},190{"selectcoins", BCLog::SELECTCOINS},191{"reindex", BCLog::REINDEX},192{"cmpctblock", BCLog::CMPCTBLOCK},193{"rand", BCLog::RAND},194{"prune", BCLog::PRUNE},195{"proxy", BCLog::PROXY},196{"mempoolrej", BCLog::MEMPOOLREJ},197{"coindb", BCLog::COINDB},198{"qt", BCLog::QT},199{"leveldb", BCLog::LEVELDB},200{"validation", BCLog::VALIDATION},201{"i2p", BCLog::I2P},202{"ipc", BCLog::IPC},203#ifdef DEBUG_LOCKCONTENTION204{"lock", BCLog::LOCK},205#endif206{"blockstorage", BCLog::BLOCKSTORAGE},207{"txreconciliation", BCLog::TXRECONCILIATION},208{"scan", BCLog::SCAN},209{"txpackages", BCLog::TXPACKAGES},210{"kernel", BCLog::KERNEL},211{"privatebroadcast", BCLog::PRIVBROADCAST},212{"mining", BCLog::MINING},213};215static const std::unordered_map<BCLog::LogFlags, std::string> LOG_CATEGORIES_BY_FLAG{216// Swap keys and values from LOG_CATEGORIES_BY_STR.217[](const auto& in) {218std::unordered_map<BCLog::LogFlags, std::string> out;219for (const auto& [k, v] : in) {220const bool inserted{out.emplace(v, k).second};221assert(inserted);222}223return out;224}(LOG_CATEGORIES_BY_STR)225};227std::optional<BCLog::LogFlags> BCLog::Logger::GetLogCategory(std::string_view str)228{229if (str.empty() || str == "1" || str == "all") {230return BCLog::ALL;231}232auto it = LOG_CATEGORIES_BY_STR.find(str);233if (it != LOG_CATEGORIES_BY_STR.end()) {234return it->second;235}236if (str == "libevent") {237LogWarning("The logging category `%s` is deprecated, does nothing, and will be removed in a future version", str);238return BCLog::NONE;239}240return std::nullopt;241}243std::string BCLog::Logger::LogLevelToStr(BCLog::Level level)244{245switch (level) {246case BCLog::Level::Trace:247return "trace";248case BCLog::Level::Debug:249return "debug";250case BCLog::Level::Info:
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.