52 return fwrite(str.data(), 1, str.size(),
fp);
82 .should_ratelimit =
false,
124 m_print_to_file =
false;
125 m_print_to_console =
false;
131 m_categories |= flag;
136 if (
const auto flag{GetLogCategory(str)}) {
137 EnableCategory(*flag);
145 m_categories &=
~flag;
150 if (
const auto flag{GetLogCategory(str)}) {
151 DisableCategory(*flag);
159 return (m_categories.load(std::memory_order_relaxed) & category) != 0;
166 if (level >= BCLog::Level::Info)
return true;
168 if (!WillLogCategory(category))
return false;
204#ifdef DEBUG_LOCKCONTENTION
205 {
"lock", BCLog::LOCK},
219 std::unordered_map<BCLog::LogFlags, std::string> out;
220 for (
const auto& [
k, v] : in) {
221 const bool inserted{out.emplace(v,
k).second};
230 if (str.empty() || str ==
"1" || str ==
"all") {
237 if (str ==
"libevent") {
238 LogWarning(
"The logging category `%s` is deprecated, does nothing, and will be removed in a future version", str);
247 case BCLog::Level::Trace:
249 case BCLog::Level::Debug:
251 case BCLog::Level::Info:
253 case BCLog::Level::Warning:
255 case BCLog::Level::Error:
274 return BCLog::Level::Trace;
276 return BCLog::Level::Debug;
278 return BCLog::Level::Info;
280 return BCLog::Level::Warning;
282 return BCLog::Level::Error;
290 std::vector<LogCategory>
ret;
301 return {BCLog::Level::Info, BCLog::Level::Debug, BCLog::Level::Trace};
307 return Join(std::vector<BCLog::Level>{
levels.begin(),
levels.end()},
", ", [](
BCLog::Level level) {
return LogLevelToStr(level); });
314 if (!m_log_timestamps)
317 const auto now_seconds{std::chrono::time_point_cast<std::chrono::seconds>(now)};
319 if (m_log_time_micros && !
strStamped.empty()) {
342 for (
char ch_in : str) {
344 if (
ch >= 32 &&
ch !=
'\x7f') {
368 if (m_always_print_category_level || !
has_category || level != Level::Debug) {
404 const std::string& str)
408 Status status{stats.m_dropped_bytes > 0 ? Status::STILL_SUPPRESSED : Status::UNSUPPRESSED};
410 if (!stats.Consume(str.size()) && status == Status::UNSUPPRESSED) {
411 status = Status::NEWLY_SUPPRESSED;
412 m_suppression_active =
true;
422 if (m_log_threadnames) {
426 if (m_log_sourcelocations) {
440 return LogPrint_(std::move(entry));
473 .level = Level::Warning,
474 .should_ratelimit =
false,
477 "Excessive logging detected from %s:%d (%s): >%d bytes logged during "
478 "the last time window of %is. Suppressing logging to disk from this "
479 "source location until time window resets. Console logging "
480 "unaffected. Last log entry.",
496 if (m_print_to_console) {
509 m_reopen_file =
false;
528 assert(!m_file_path.empty());
536 log_size = fs::file_size(m_file_path);
537 }
catch (
const fs::filesystem_error&) {}
549 .level = Level::Warning,
550 .should_ratelimit =
true,
552 .message =
"Failed to shrink debug log file: fseek(...) failed",
557 int nBytes =
fread(vch.data(), 1, vch.size(), file);
567 else if (file !=
nullptr)
577 m_suppression_active =
false;
580 if (stats.m_dropped_bytes == 0)
continue;
582 "Restarting logging from %s:%d (%s): %d bytes were dropped during the last %ss.",
583 source_loc.file_name(), source_loc.line(), source_loc.function_name_short(),
590 if (bytes > m_available_bytes) {
591 m_dropped_bytes += bytes;
592 m_available_bytes = 0;
596 m_available_bytes -= bytes;
604 m_log_level = level.value();
611 if (!flag)
return false;
Fixed window rate limiter for logging.
static std::shared_ptr< LogRateLimiter > Create(SchedulerFunction &&scheduler_func, uint64_t max_bytes, std::chrono::seconds reset_window)
std::function< void(std::function< void()>, std::chrono::milliseconds)> SchedulerFunction
LogRateLimiter(uint64_t max_bytes, std::chrono::seconds reset_window)
Status Consume(const SourceLocation &source_loc, const std::string &str) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Consumes source_loc's available bytes corresponding to the size of the (formatted) str and returns it...
Status
Suppression status of a source log location.
void Reset() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Resets all usage to zero. Called periodically by the scheduler.
static std::string LogLevelToStr(BCLog::Level level)
Returns the string representation of a log level.
bool WillLogCategory(LogFlags category) const
std::string LogTimestampStr(SystemClock::time_point now, std::chrono::seconds mocktime) const
bool DefaultShrinkDebugFile() const
void LogPrint_(util::log::Entry log_entry) EXCLUSIVE_LOCKS_REQUIRED(m_cs)
Send an entry to the log output (internal)
void SetCategoryLogLevel(const std::unordered_map< LogFlags, Level > &levels) EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
void SetLogLevel(Level level)
void ShrinkDebugFile() EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
bool WillLogCategoryLevel(LogFlags category, Level level) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
void DisableLogging() EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
Disable logging This offers a slight speedup and slightly smaller memory usage compared to leaving th...
std::vector< LogCategory > LogCategoriesList() const
Returns a vector of the log categories in alphabetical order.
static std::optional< BCLog::LogFlags > GetLogCategory(std::string_view str)
Return log flag if str parses as a log category.
bool StartLogging() EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
Start logging (and flush all buffered messages)
void EnableCategory(LogFlags flag)
std::string GetLogPrefix(LogFlags category, Level level) const
void DisconnectTestLogger() EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
Only for testing.
std::string LogLevelsString() const
Returns a string with all user-selectable log levels.
void LogPrint(util::log::Entry log_entry) EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
Send an entry to the log output.
std::string Format(const util::log::Entry &entry) const
void DisableCategory(LogFlags flag)
Like std::source_location, but allowing to override the function name.
std::string_view function_name_short() const
std::string_view file_name() const
std::uint_least32_t line() const
static constexpr std::array< BCLog::Level, 3 > LogLevelsList()
Log severity levels that can be selected by the user.
static int FileWriteStr(std::string_view str, FILE *fp)
static std::string LogCategoryToStr(BCLog::LogFlags category)
static const std::map< std::string, BCLog::LogFlags, std::less<> > LOG_CATEGORIES_BY_STR
BCLog::Logger & LogInstance()
static const std::unordered_map< BCLog::LogFlags, std::string > LOG_CATEGORIES_BY_FLAG
const char *const DEFAULT_DEBUGLOGFILE
static std::optional< BCLog::Level > GetLogLevel(std::string_view level_str)
static size_t MemUsage(const util::log::Entry &log)
constexpr auto MAX_USER_SETABLE_SEVERITY_LEVEL
constexpr bool DEFAULT_LOGIPS
std::string LogEscapeMessage(std::string_view str)
Belts and suspenders: make sure outgoing log messages don't contain potentially suspicious characters...
constexpr size_t DEFAULT_MAX_LOG_BUFFER
FILE * fopen(const fs::path &p, const char *mode)
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
static size_t MallocUsage(size_t alloc)
Compute the total memory used by allocating alloc bytes.
void Log(Entry entry)
Send message to be logged.
bool ShouldDebugLog(Category)
Return whether messages with specified category should be debug logged.
bool ShouldTraceLog(Category)
Return whether messages with specified category should be trace logged.
constexpr NoRateLimitTag NO_RATE_LIMIT
std::string_view RemoveSuffixView(std::string_view str LIFETIMEBOUND, std::string_view suffix)
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
std::string_view RemovePrefixView(std::string_view str LIFETIMEBOUND, std::string_view prefix)
bool Consume(uint64_t bytes)
Updates internal accounting and returns true if enough available_bytes were remaining.
SourceLocation source_loc
SystemClock::time_point timestamp
bool should_ratelimit
Hint for consumers if this entry should be ratelimited.
std::chrono::seconds mocktime
std::string FormatISO8601DateTime(int64_t nTime)
ISO 8601 formatting is preferred.
constexpr int64_t count_seconds(std::chrono::seconds t)
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.