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#ifndef BITCOIN_LOGGING_H7#define BITCOIN_LOGGING_H9#include <crypto/siphash.h>10#include <logging/categories.h> // IWYU pragma: export11#include <span.h>12#include <util/byte_units.h>13#include <util/fs.h>14#include <util/log.h> // IWYU pragma: export15#include <util/stdmutex.h>16#include <util/string.h>17#include <util/time.h>19#include <atomic>20#include <cstdint>21#include <cstring>22#include <functional>23#include <list>24#include <memory>25#include <optional>26#include <string>27#include <unordered_map>28#include <vector>30inline constexpr bool DEFAULT_LOGTIMEMICROS = false;31inline constexpr bool DEFAULT_LOGIPS = false;32inline constexpr bool DEFAULT_LOGTIMESTAMPS = true;33inline constexpr bool DEFAULT_LOGTHREADNAMES = false;34inline constexpr bool DEFAULT_LOGSOURCELOCATIONS = false;35inline constexpr bool DEFAULT_LOGLEVELALWAYS = false;36extern const char * const DEFAULT_DEBUGLOGFILE;38extern bool fLogIPs;40struct SourceLocationEqual {41bool operator()(const SourceLocation& lhs, const SourceLocation& rhs) const noexcept42{43return lhs.line() == rhs.line() && std::string_view(lhs.file_name()) == std::string_view(rhs.file_name());44}45};47struct SourceLocationHasher {48size_t operator()(const SourceLocation& s) const noexcept49{50// Use CSipHasher(0, 0) as a simple way to get uniform distribution.51return size_t(CSipHasher(0, 0)52.Write(s.line())53.Write(MakeUCharSpan(std::string_view{s.file_name()}))54.Finalize());55}56};58struct LogCategory {59std::string category;60bool active;61};63namespace BCLog {64constexpr auto DEFAULT_LOG_LEVEL{Level::Debug};65constexpr size_t DEFAULT_MAX_LOG_BUFFER{1'000'000}; // buffer up to 1MB of log data prior to StartLogging66constexpr uint64_t RATELIMIT_MAX_BYTES{1_MiB}; // maximum number of bytes per source location that can be logged within the RATELIMIT_WINDOW67constexpr auto RATELIMIT_WINDOW{1h}; // time window after which log ratelimit stats are reset68constexpr bool DEFAULT_LOGRATELIMIT{true};70//! Fixed window rate limiter for logging.71class LogRateLimiter72{73public:74//! Keeps track of an individual source location and how many available bytes are left for logging from it.75struct Stats {76//! Remaining bytes77uint64_t m_available_bytes;78//! Number of bytes that were consumed but didn't fit in the available bytes.79uint64_t m_dropped_bytes{0};81Stats(uint64_t max_bytes) : m_available_bytes{max_bytes} {}82//! Updates internal accounting and returns true if enough available_bytes were remaining83bool Consume(uint64_t bytes);84};86private:87mutable StdMutex m_mutex;89//! Stats for each source location that has attempted to log something.90std::unordered_map<SourceLocation, Stats, SourceLocationHasher, SourceLocationEqual> m_source_locations GUARDED_BY(m_mutex);91//! Whether any log locations are suppressed. Cached view on m_source_locations for performance reasons.92std::atomic<bool> m_suppression_active{false};93LogRateLimiter(uint64_t max_bytes, std::chrono::seconds reset_window);95public:96using SchedulerFunction = std::function<void(std::function<void()>, std::chrono::milliseconds)>;97/**98* @param scheduler_func Callable object used to schedule resetting the window. The first99* parameter is the function to be executed, and the second is the100* reset_window interval.101* @param max_bytes Maximum number of bytes that can be logged for each source102* location.103* @param reset_window Time window after which the stats are reset.104*/105static std::shared_ptr<LogRateLimiter> Create(106SchedulerFunction&& scheduler_func,107uint64_t max_bytes,108std::chrono::seconds reset_window);109//! Maximum number of bytes logged per location per window.110const uint64_t m_max_bytes;111//! Interval after which the window is reset.112const std::chrono::seconds m_reset_window;113//! Suppression status of a source log location.114enum class Status {115UNSUPPRESSED, // string fits within the limit116NEWLY_SUPPRESSED, // suppression has started since this string117STILL_SUPPRESSED, // suppression is still ongoing118};119//! Consumes `source_loc`'s available bytes corresponding to the size of the (formatted)120//! `str` and returns its status.121[[nodiscard]] Status Consume(122const SourceLocation& source_loc,123const std::string& str) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);124//! Resets all usage to zero. Called periodically by the scheduler.125void Reset() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);126//! Returns true if any log locations are currently being suppressed.127bool SuppressionsActive() const { return m_suppression_active; }128};130class Logger131{132private:133mutable StdMutex m_cs; // Can not use Mutex from sync.h because in debug mode it would cause a deadlock when a potential deadlock was detected135FILE* m_fileout GUARDED_BY(m_cs) = nullptr;136std::list<util::log::Entry> m_msgs_before_open GUARDED_BY(m_cs);137bool m_buffering GUARDED_BY(m_cs) = true; //!< Buffer messages before logging can be started.138size_t m_max_buffer_memusage GUARDED_BY(m_cs){DEFAULT_MAX_LOG_BUFFER};139size_t m_cur_buffer_memusage GUARDED_BY(m_cs){0};140size_t m_buffer_lines_discarded GUARDED_BY(m_cs){0};142//! Manages the rate limiting of each log location.143std::shared_ptr<LogRateLimiter> m_limiter GUARDED_BY(m_cs);145//! Category-specific log level. Overrides `m_log_level`.146std::unordered_map<LogFlags, Level> m_category_log_levels GUARDED_BY(m_cs);148//! If there is no category-specific log level, all logs with a severity149//! level lower than `m_log_level` will be ignored.150std::atomic<Level> m_log_level{DEFAULT_LOG_LEVEL};152/** Log categories bitfield. */153std::atomic<CategoryMask> m_categories{BCLog::NONE};155std::string Format(const util::log::Entry& entry) const;157std::string LogTimestampStr(SystemClock::time_point now, std::chrono::seconds mocktime) const;159/** Slots that connect to the print signal */160std::list<std::function<void(const std::string&)>> m_print_callbacks GUARDED_BY(m_cs){};162/** Send an entry to the log output (internal) */163void LogPrint_(util::log::Entry log_entry) EXCLUSIVE_LOCKS_REQUIRED(m_cs);165std::string GetLogPrefix(LogFlags category, Level level) const;167public:168bool m_print_to_console = false;169bool m_print_to_file = false;171bool m_log_timestamps = DEFAULT_LOGTIMESTAMPS;172bool m_log_time_micros = DEFAULT_LOGTIMEMICROS;173bool m_log_threadnames = DEFAULT_LOGTHREADNAMES;174bool m_log_sourcelocations = DEFAULT_LOGSOURCELOCATIONS;175bool m_always_print_category_level = DEFAULT_LOGLEVELALWAYS;177fs::path m_file_path;178std::atomic<bool> m_reopen_file{false};180/** Send an entry to the log output */181void LogPrint(util::log::Entry log_entry) EXCLUSIVE_LOCKS_REQUIRED(!m_cs);183/** Returns whether logs will be written to any output */184bool Enabled() const EXCLUSIVE_LOCKS_REQUIRED(!m_cs)185{186STDLOCK(m_cs);187return m_buffering || m_print_to_console || m_print_to_file || !m_print_callbacks.empty();188}190/** Connect a slot to the print signal and return the connection */191std::list<std::function<void(const std::string&)>>::iterator PushBackCallback(std::function<void(const std::string&)> fun) EXCLUSIVE_LOCKS_REQUIRED(!m_cs)192{193STDLOCK(m_cs);194m_print_callbacks.push_back(std::move(fun));195return --m_print_callbacks.end();196}198/** Delete a connection */199void DeleteCallback(std::list<std::function<void(const std::string&)>>::iterator it) EXCLUSIVE_LOCKS_REQUIRED(!m_cs)200{201STDLOCK(m_cs);202m_print_callbacks.erase(it);203}205size_t NumConnections() EXCLUSIVE_LOCKS_REQUIRED(!m_cs)206{207STDLOCK(m_cs);208return m_print_callbacks.size();209}211/** Start logging (and flush all buffered messages) */212bool StartLogging() EXCLUSIVE_LOCKS_REQUIRED(!m_cs);213/** Only for testing */214void DisconnectTestLogger() EXCLUSIVE_LOCKS_REQUIRED(!m_cs);216void SetRateLimiting(std::shared_ptr<LogRateLimiter> limiter) EXCLUSIVE_LOCKS_REQUIRED(!m_cs)217{218STDLOCK(m_cs);219m_limiter = std::move(limiter);220}222/** Disable logging223* This offers a slight speedup and slightly smaller memory usage224* compared to leaving the logging system in its default state.225* Mostly intended for libbitcoin-kernel apps that don't want any logging.226* Should be used instead of StartLogging().227*/228void DisableLogging() EXCLUSIVE_LOCKS_REQUIRED(!m_cs);230void ShrinkDebugFile() EXCLUSIVE_LOCKS_REQUIRED(!m_cs);232std::unordered_map<LogFlags, Level> CategoryLevels() const EXCLUSIVE_LOCKS_REQUIRED(!m_cs)233{234STDLOCK(m_cs);235return m_category_log_levels;236}237void SetCategoryLogLevel(const std::unordered_map<LogFlags, Level>& levels) EXCLUSIVE_LOCKS_REQUIRED(!m_cs)238{239STDLOCK(m_cs);240m_category_log_levels = levels;241}242void AddCategoryLogLevel(LogFlags category, Level level) EXCLUSIVE_LOCKS_REQUIRED(!m_cs)243{244STDLOCK(m_cs);245m_category_log_levels[category] = level;246}247bool SetCategoryLogLevel(std::string_view category_str, std::string_view level_str) EXCLUSIVE_LOCKS_REQUIRED(!m_cs);249Level LogLevel() const { return m_log_level.load(); }250void SetLogLevel(Level level) { m_log_level = level; }
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.