51 return fwrite(str.data(), 1, str.size(),
fp);
118 m_print_to_file =
false;
119 m_print_to_console =
false;
125 m_categories |= flag;
132 EnableCategory(flag);
138 m_categories &=
~flag;
145 DisableCategory(flag);
151 return (m_categories.load(std::memory_order_relaxed) & category) != 0;
158 if (level >= BCLog::Level::Info)
return true;
160 if (!WillLogCategory(category))
return false;
197#ifdef DEBUG_LOCKCONTENTION
198 {
"lock", BCLog::LOCK},
211 std::unordered_map<BCLog::LogFlags, std::string> out;
212 for (
const auto& [
k, v] : in) {
213 const bool inserted{out.emplace(v,
k).second};
222 if (str.empty() || str ==
"1" || str ==
"all") {
237 case BCLog::Level::Trace:
239 case BCLog::Level::Debug:
241 case BCLog::Level::Info:
243 case BCLog::Level::Warning:
245 case BCLog::Level::Error:
264 return BCLog::Level::Trace;
266 return BCLog::Level::Debug;
268 return BCLog::Level::Info;
270 return BCLog::Level::Warning;
272 return BCLog::Level::Error;
280 std::vector<LogCategory>
ret;
291 return {BCLog::Level::Info, BCLog::Level::Debug, BCLog::Level::Trace};
297 return Join(std::vector<BCLog::Level>{
levels.begin(),
levels.end()},
", ", [](
BCLog::Level level) {
return LogLevelToStr(level); });
304 if (!m_log_timestamps)
307 const auto now_seconds{std::chrono::time_point_cast<std::chrono::seconds>(now)};
309 if (m_log_time_micros && !
strStamped.empty()) {
331 for (
char ch_in : str) {
333 if ((
ch >= 32 ||
ch ==
'\n') &&
ch !=
'\x7f') {
357 if (m_always_print_category_level || !
has_category || level != Level::Debug) {
393 const std::string& str)
397 Status status{stats.m_dropped_bytes > 0 ? Status::STILL_SUPPRESSED : Status::UNSUPPRESSED};
399 if (!stats.Consume(str.size()) && status == Status::UNSUPPRESSED) {
400 status = Status::NEWLY_SUPPRESSED;
401 m_suppression_active =
true;
409 if (!str.ends_with(
'\n')) str.push_back(
'\n');
411 str.insert(0, GetLogPrefix(category, level));
413 if (m_log_sourcelocations) {
417 if (m_log_threadnames) {
418 str.insert(0,
strprintf(
"[%s] ", (threadname.empty() ?
"unknown" : threadname)));
421 str.insert(0, LogTimestampStr(now, mocktime));
427 return LogPrintStr_(str, std::move(source_loc), category, level, should_ratelimit);
438 .
now = SystemClock::now(),
442 .source_loc = std::move(source_loc),
443 .category = category,
470 "Excessive logging detected from %s:%d (%s): >%d bytes logged during "
471 "the last time window of %is. Suppressing logging to disk from this "
472 "source location until time window resets. Console logging "
473 "unaffected. Last log entry.",
474 source_loc.file_name(), source_loc.line(), source_loc.function_name_short(),
489 if (m_print_to_console) {
502 m_reopen_file =
false;
519 assert(!m_file_path.empty());
527 log_size = fs::file_size(m_file_path);
528 }
catch (
const fs::filesystem_error&) {}
537 LogWarning(
"Failed to shrink debug log file: fseek(...) failed");
541 int nBytes =
fread(vch.data(), 1, vch.size(), file);
551 else if (file !=
nullptr)
561 m_suppression_active =
false;
564 if (stats.m_dropped_bytes == 0)
continue;
567 "Restarting logging from %s:%d (%s): %d bytes were dropped during the last %ss.",
568 source_loc.file_name(), source_loc.line(), source_loc.function_name_short(),
575 if (bytes > m_available_bytes) {
576 m_dropped_bytes += bytes;
577 m_available_bytes = 0;
581 m_available_bytes -= bytes;
589 m_log_level = level.value();
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
void FormatLogStrInPlace(std::string &str, LogFlags category, Level level, const SourceLocation &source_loc, std::string_view threadname, SystemClock::time_point now, std::chrono::seconds mocktime) const
void LogPrintStr_(std::string_view str, SourceLocation &&source_loc, BCLog::LogFlags category, BCLog::Level level, bool should_ratelimit) EXCLUSIVE_LOCKS_REQUIRED(m_cs)
Send a string to the log output (internal)
std::string LogTimestampStr(SystemClock::time_point now, std::chrono::seconds mocktime) const
bool DefaultShrinkDebugFile() const
void SetCategoryLogLevel(const std::unordered_map< LogFlags, Level > &levels) EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
void SetLogLevel(Level level)
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.
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 LogPrintStr(std::string_view str, SourceLocation &&source_loc, BCLog::LogFlags category, BCLog::Level level, bool should_ratelimit) EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
Send a string to the log output.
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
#define LogPrintLevel_(category, level, should_ratelimit,...)
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)
bool GetLogCategory(BCLog::LogFlags &flag, std::string_view str)
Return true if str parses as a log category and set the flag.
static size_t MemUsage(const BCLog::Logger::BufferedLog &buflog)
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)
constexpr auto MAX_USER_SETABLE_SEVERITY_LEVEL
static const 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.
uint64_t Category
Opaque to util::log; interpreted by consumers (e.g., BCLog::LogFlags).
bool ShouldLog(Category category, Level level)
Return whether messages with specified category and level should be logged.
std::string ThreadGetInternalName()
Get the thread's internal (in-memory) name; used e.g.
std::string_view RemovePrefixView(std::string_view str, std::string_view prefix)
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
bool Consume(uint64_t bytes)
Updates internal accounting and returns true if enough available_bytes were remaining.
SystemClock::time_point now
SourceLocation source_loc
bool should_ratelimit
Hint for consumers if this entry should be ratelimited.
std::chrono::seconds GetMockTime()
For testing.
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.