Bitcoin Core  31.0.0
P2P Digital Currency
logging.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-present The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
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>
13 
14 #include <array>
15 #include <cstring>
16 #include <map>
17 #include <optional>
18 #include <utility>
19 
20 using util::Join;
22 
23 const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
25 
27 {
43  static BCLog::Logger* g_logger{new BCLog::Logger()};
44  return *g_logger;
45 }
46 
48 
49 static int FileWriteStr(std::string_view str, FILE *fp)
50 {
51  return fwrite(str.data(), 1, str.size(), fp);
52 }
53 
55 {
56  StdLockGuard scoped_lock(m_cs);
57 
58  assert(m_buffering);
59  assert(m_fileout == nullptr);
60 
61  if (m_print_to_file) {
62  assert(!m_file_path.empty());
63  m_fileout = fsbridge::fopen(m_file_path, "a");
64  if (!m_fileout) {
65  return false;
66  }
67 
68  setbuf(m_fileout, nullptr); // unbuffered
69 
70  // Add newlines to the logfile to distinguish this execution from the
71  // last one.
72  FileWriteStr("\n\n\n\n\n", m_fileout);
73  }
74 
75  // dump buffered messages from before we opened the log
76  m_buffering = false;
77  if (m_buffer_lines_discarded > 0) {
78  LogPrintStr_(strprintf("Early logging buffer overflowed, %d log lines discarded.\n", m_buffer_lines_discarded), SourceLocation{__func__}, BCLog::ALL, Level::Info, /*should_ratelimit=*/false);
79  }
80  while (!m_msgs_before_open.empty()) {
81  const auto& buflog = m_msgs_before_open.front();
82  std::string s{buflog.str};
83  FormatLogStrInPlace(s, buflog.category, buflog.level, buflog.source_loc, buflog.threadname, buflog.now, buflog.mocktime);
84  m_msgs_before_open.pop_front();
85 
86  if (m_print_to_file) FileWriteStr(s, m_fileout);
87  if (m_print_to_console) fwrite(s.data(), 1, s.size(), stdout);
88  for (const auto& cb : m_print_callbacks) {
89  cb(s);
90  }
91  }
92  m_cur_buffer_memusage = 0;
93  if (m_print_to_console) fflush(stdout);
94 
95  return true;
96 }
97 
99 {
100  StdLockGuard scoped_lock(m_cs);
101  m_buffering = true;
102  if (m_fileout != nullptr) fclose(m_fileout);
103  m_fileout = nullptr;
104  m_print_callbacks.clear();
105  m_max_buffer_memusage = DEFAULT_MAX_LOG_BUFFER;
106  m_cur_buffer_memusage = 0;
107  m_buffer_lines_discarded = 0;
108  m_msgs_before_open.clear();
109 }
110 
112 {
113  {
114  StdLockGuard scoped_lock(m_cs);
115  assert(m_buffering);
116  assert(m_print_callbacks.empty());
117  }
118  m_print_to_file = false;
119  m_print_to_console = false;
120  StartLogging();
121 }
122 
124 {
125  m_categories |= flag;
126 }
127 
128 bool BCLog::Logger::EnableCategory(std::string_view str)
129 {
130  BCLog::LogFlags flag;
131  if (!GetLogCategory(flag, str)) return false;
132  EnableCategory(flag);
133  return true;
134 }
135 
137 {
138  m_categories &= ~flag;
139 }
140 
141 bool BCLog::Logger::DisableCategory(std::string_view str)
142 {
143  BCLog::LogFlags flag;
144  if (!GetLogCategory(flag, str)) return false;
145  DisableCategory(flag);
146  return true;
147 }
148 
150 {
151  return (m_categories.load(std::memory_order_relaxed) & category) != 0;
152 }
153 
155 {
156  // Log messages at Info, Warning and Error level unconditionally, so that
157  // important troubleshooting information doesn't get lost.
158  if (level >= BCLog::Level::Info) return true;
159 
160  if (!WillLogCategory(category)) return false;
161 
162  StdLockGuard scoped_lock(m_cs);
163  const auto it{m_category_log_levels.find(category)};
164  return level >= (it == m_category_log_levels.end() ? LogLevel() : it->second);
165 }
166 
168 {
169  return m_categories == BCLog::NONE;
170 }
171 
172 static const std::map<std::string, BCLog::LogFlags, std::less<>> LOG_CATEGORIES_BY_STR{
173  {"net", BCLog::NET},
174  {"tor", BCLog::TOR},
175  {"mempool", BCLog::MEMPOOL},
176  {"http", BCLog::HTTP},
177  {"bench", BCLog::BENCH},
178  {"zmq", BCLog::ZMQ},
179  {"walletdb", BCLog::WALLETDB},
180  {"rpc", BCLog::RPC},
181  {"estimatefee", BCLog::ESTIMATEFEE},
182  {"addrman", BCLog::ADDRMAN},
183  {"selectcoins", BCLog::SELECTCOINS},
184  {"reindex", BCLog::REINDEX},
185  {"cmpctblock", BCLog::CMPCTBLOCK},
186  {"rand", BCLog::RAND},
187  {"prune", BCLog::PRUNE},
188  {"proxy", BCLog::PROXY},
189  {"mempoolrej", BCLog::MEMPOOLREJ},
190  {"libevent", BCLog::LIBEVENT},
191  {"coindb", BCLog::COINDB},
192  {"qt", BCLog::QT},
193  {"leveldb", BCLog::LEVELDB},
194  {"validation", BCLog::VALIDATION},
195  {"i2p", BCLog::I2P},
196  {"ipc", BCLog::IPC},
197 #ifdef DEBUG_LOCKCONTENTION
198  {"lock", BCLog::LOCK},
199 #endif
200  {"blockstorage", BCLog::BLOCKSTORAGE},
201  {"txreconciliation", BCLog::TXRECONCILIATION},
202  {"scan", BCLog::SCAN},
203  {"txpackages", BCLog::TXPACKAGES},
204  {"kernel", BCLog::KERNEL},
205  {"privatebroadcast", BCLog::PRIVBROADCAST},
206 };
207 
208 static const std::unordered_map<BCLog::LogFlags, std::string> LOG_CATEGORIES_BY_FLAG{
209  // Swap keys and values from LOG_CATEGORIES_BY_STR.
210  [](const auto& in) {
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};
214  assert(inserted);
215  }
216  return out;
218 };
219 
220 bool GetLogCategory(BCLog::LogFlags& flag, std::string_view str)
221 {
222  if (str.empty() || str == "1" || str == "all") {
223  flag = BCLog::ALL;
224  return true;
225  }
226  auto it = LOG_CATEGORIES_BY_STR.find(str);
227  if (it != LOG_CATEGORIES_BY_STR.end()) {
228  flag = it->second;
229  return true;
230  }
231  return false;
232 }
233 
235 {
236  switch (level) {
237  case BCLog::Level::Trace:
238  return "trace";
239  case BCLog::Level::Debug:
240  return "debug";
241  case BCLog::Level::Info:
242  return "info";
244  return "warning";
245  case BCLog::Level::Error:
246  return "error";
247  }
248  assert(false);
249 }
250 
251 static std::string LogCategoryToStr(BCLog::LogFlags category)
252 {
253  if (category == BCLog::ALL) {
254  return "all";
255  }
256  auto it = LOG_CATEGORIES_BY_FLAG.find(category);
257  assert(it != LOG_CATEGORIES_BY_FLAG.end());
258  return it->second;
259 }
260 
261 static std::optional<BCLog::Level> GetLogLevel(std::string_view level_str)
262 {
263  if (level_str == "trace") {
264  return BCLog::Level::Trace;
265  } else if (level_str == "debug") {
266  return BCLog::Level::Debug;
267  } else if (level_str == "info") {
268  return BCLog::Level::Info;
269  } else if (level_str == "warning") {
270  return BCLog::Level::Warning;
271  } else if (level_str == "error") {
272  return BCLog::Level::Error;
273  } else {
274  return std::nullopt;
275  }
276 }
277 
278 std::vector<LogCategory> BCLog::Logger::LogCategoriesList() const
279 {
280  std::vector<LogCategory> ret;
281  ret.reserve(LOG_CATEGORIES_BY_STR.size());
282  for (const auto& [category, flag] : LOG_CATEGORIES_BY_STR) {
283  ret.push_back(LogCategory{.category = category, .active = WillLogCategory(flag)});
284  }
285  return ret;
286 }
287 
289 static constexpr std::array<BCLog::Level, 3> LogLevelsList()
290 {
291  return {BCLog::Level::Info, BCLog::Level::Debug, BCLog::Level::Trace};
292 }
293 
295 {
296  const auto& levels = LogLevelsList();
297  return Join(std::vector<BCLog::Level>{levels.begin(), levels.end()}, ", ", [](BCLog::Level level) { return LogLevelToStr(level); });
298 }
299 
300 std::string BCLog::Logger::LogTimestampStr(SystemClock::time_point now, std::chrono::seconds mocktime) const
301 {
302  std::string strStamped;
303 
304  if (!m_log_timestamps)
305  return strStamped;
306 
307  const auto now_seconds{std::chrono::time_point_cast<std::chrono::seconds>(now)};
308  strStamped = FormatISO8601DateTime(TicksSinceEpoch<std::chrono::seconds>(now_seconds));
309  if (m_log_time_micros && !strStamped.empty()) {
310  strStamped.pop_back();
311  strStamped += strprintf(".%06dZ", Ticks<std::chrono::microseconds>(now - now_seconds));
312  }
313  if (mocktime > 0s) {
314  strStamped += " (mocktime: " + FormatISO8601DateTime(count_seconds(mocktime)) + ")";
315  }
316  strStamped += ' ';
317 
318  return strStamped;
319 }
320 
321 namespace BCLog {
329  std::string LogEscapeMessage(std::string_view str) {
330  std::string ret;
331  for (char ch_in : str) {
332  uint8_t ch = (uint8_t)ch_in;
333  if ((ch >= 32 || ch == '\n') && ch != '\x7f') {
334  ret += ch_in;
335  } else {
336  ret += strprintf("\\x%02x", ch);
337  }
338  }
339  return ret;
340  }
341 } // namespace BCLog
342 
343 std::string BCLog::Logger::GetLogPrefix(BCLog::LogFlags category, BCLog::Level level) const
344 {
345  if (category == LogFlags::NONE) category = LogFlags::ALL;
346 
347  const bool has_category{m_always_print_category_level || category != LogFlags::ALL};
348 
349  // If there is no category, Info is implied
350  if (!has_category && level == Level::Info) return {};
351 
352  std::string s{"["};
353  if (has_category) {
354  s += LogCategoryToStr(category);
355  }
356 
357  if (m_always_print_category_level || !has_category || level != Level::Debug) {
358  // If there is a category, Debug is implied, so don't add the level
359 
360  // Only add separator if we have a category
361  if (has_category) s += ":";
362  s += Logger::LogLevelToStr(level);
363  }
364 
365  s += "] ";
366  return s;
367 }
368 
369 static size_t MemUsage(const BCLog::Logger::BufferedLog& buflog)
370 {
371  return memusage::DynamicUsage(buflog.str) +
374 }
375 
376 BCLog::LogRateLimiter::LogRateLimiter(uint64_t max_bytes, std::chrono::seconds reset_window)
377  : m_max_bytes{max_bytes}, m_reset_window{reset_window} {}
378 
379 std::shared_ptr<BCLog::LogRateLimiter> BCLog::LogRateLimiter::Create(
380  SchedulerFunction&& scheduler_func, uint64_t max_bytes, std::chrono::seconds reset_window)
381 {
382  auto limiter{std::shared_ptr<LogRateLimiter>(new LogRateLimiter(max_bytes, reset_window))};
383  std::weak_ptr<LogRateLimiter> weak_limiter{limiter};
384  auto reset = [weak_limiter] {
385  if (auto shared_limiter{weak_limiter.lock()}) shared_limiter->Reset();
386  };
387  scheduler_func(reset, limiter->m_reset_window);
388  return limiter;
389 }
390 
392  const SourceLocation& source_loc,
393  const std::string& str)
394 {
395  StdLockGuard scoped_lock(m_mutex);
396  auto& stats{m_source_locations.try_emplace(source_loc, m_max_bytes).first->second};
397  Status status{stats.m_dropped_bytes > 0 ? Status::STILL_SUPPRESSED : Status::UNSUPPRESSED};
398 
399  if (!stats.Consume(str.size()) && status == Status::UNSUPPRESSED) {
400  status = Status::NEWLY_SUPPRESSED;
401  m_suppression_active = true;
402  }
403 
404  return status;
405 }
406 
407 void BCLog::Logger::FormatLogStrInPlace(std::string& str, BCLog::LogFlags category, BCLog::Level level, const SourceLocation& source_loc, std::string_view threadname, SystemClock::time_point now, std::chrono::seconds mocktime) const
408 {
409  if (!str.ends_with('\n')) str.push_back('\n');
410 
411  str.insert(0, GetLogPrefix(category, level));
412 
413  if (m_log_sourcelocations) {
414  str.insert(0, strprintf("[%s:%d] [%s] ", RemovePrefixView(source_loc.file_name(), "./"), source_loc.line(), source_loc.function_name_short()));
415  }
416 
417  if (m_log_threadnames) {
418  str.insert(0, strprintf("[%s] ", (threadname.empty() ? "unknown" : threadname)));
419  }
420 
421  str.insert(0, LogTimestampStr(now, mocktime));
422 }
423 
424 void BCLog::Logger::LogPrintStr(std::string_view str, SourceLocation&& source_loc, BCLog::LogFlags category, BCLog::Level level, bool should_ratelimit)
425 {
426  StdLockGuard scoped_lock(m_cs);
427  return LogPrintStr_(str, std::move(source_loc), category, level, should_ratelimit);
428 }
429 
430 // NOLINTNEXTLINE(misc-no-recursion)
431 void BCLog::Logger::LogPrintStr_(std::string_view str, SourceLocation&& source_loc, BCLog::LogFlags category, BCLog::Level level, bool should_ratelimit)
432 {
433  std::string str_prefixed = LogEscapeMessage(str);
434 
435  if (m_buffering) {
436  {
437  BufferedLog buf{
438  .now = SystemClock::now(),
439  .mocktime = GetMockTime(),
440  .str = str_prefixed,
441  .threadname = util::ThreadGetInternalName(),
442  .source_loc = std::move(source_loc),
443  .category = category,
444  .level = level,
445  };
446  m_cur_buffer_memusage += MemUsage(buf);
447  m_msgs_before_open.push_back(std::move(buf));
448  }
449 
450  while (m_cur_buffer_memusage > m_max_buffer_memusage) {
451  if (m_msgs_before_open.empty()) {
452  m_cur_buffer_memusage = 0;
453  break;
454  }
455  m_cur_buffer_memusage -= MemUsage(m_msgs_before_open.front());
456  m_msgs_before_open.pop_front();
457  ++m_buffer_lines_discarded;
458  }
459 
460  return;
461  }
462 
463  FormatLogStrInPlace(str_prefixed, category, level, source_loc, util::ThreadGetInternalName(), SystemClock::now(), GetMockTime());
464  bool ratelimit{false};
465  if (should_ratelimit && m_limiter) {
466  auto status{m_limiter->Consume(source_loc, str_prefixed)};
468  // NOLINTNEXTLINE(misc-no-recursion)
469  LogPrintStr_(strprintf(
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(),
475  m_limiter->m_max_bytes,
476  Ticks<std::chrono::seconds>(m_limiter->m_reset_window)),
477  SourceLocation{__func__}, LogFlags::ALL, Level::Warning, /*should_ratelimit=*/false); // with should_ratelimit=false, this cannot lead to infinite recursion
478  } else if (status == LogRateLimiter::Status::STILL_SUPPRESSED) {
479  ratelimit = true;
480  }
481  }
482 
483  // To avoid confusion caused by dropped log messages when debugging an issue,
484  // we prefix log lines with "[*]" when there are any suppressed source locations.
485  if (m_limiter && m_limiter->SuppressionsActive()) {
486  str_prefixed.insert(0, "[*] ");
487  }
488 
489  if (m_print_to_console) {
490  // print to console
491  fwrite(str_prefixed.data(), 1, str_prefixed.size(), stdout);
492  fflush(stdout);
493  }
494  for (const auto& cb : m_print_callbacks) {
495  cb(str_prefixed);
496  }
497  if (m_print_to_file && !ratelimit) {
498  assert(m_fileout != nullptr);
499 
500  // reopen the log file, if requested
501  if (m_reopen_file) {
502  m_reopen_file = false;
503  FILE* new_fileout = fsbridge::fopen(m_file_path, "a");
504  if (new_fileout) {
505  setbuf(new_fileout, nullptr); // unbuffered
506  fclose(m_fileout);
507  m_fileout = new_fileout;
508  }
509  }
510  FileWriteStr(str_prefixed, m_fileout);
511  }
512 }
513 
515 {
516  // Amount of debug.log to save at end when shrinking (must fit in memory)
517  constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
518 
519  assert(!m_file_path.empty());
520 
521  // Scroll debug.log if it's getting too big
522  FILE* file = fsbridge::fopen(m_file_path, "r");
523 
524  // Special files (e.g. device nodes) may not have a size.
525  size_t log_size = 0;
526  try {
527  log_size = fs::file_size(m_file_path);
528  } catch (const fs::filesystem_error&) {}
529 
530  // If debug.log file is more than 10% bigger the RECENT_DEBUG_HISTORY_SIZE
531  // trim it down by saving only the last RECENT_DEBUG_HISTORY_SIZE bytes
532  if (file && log_size > 11 * (RECENT_DEBUG_HISTORY_SIZE / 10))
533  {
534  // Restart the file with some of the end
535  std::vector<char> vch(RECENT_DEBUG_HISTORY_SIZE, 0);
536  if (fseek(file, -((long)vch.size()), SEEK_END)) {
537  LogWarning("Failed to shrink debug log file: fseek(...) failed");
538  fclose(file);
539  return;
540  }
541  int nBytes = fread(vch.data(), 1, vch.size(), file);
542  fclose(file);
543 
544  file = fsbridge::fopen(m_file_path, "w");
545  if (file)
546  {
547  fwrite(vch.data(), 1, nBytes, file);
548  fclose(file);
549  }
550  }
551  else if (file != nullptr)
552  fclose(file);
553 }
554 
556 {
557  decltype(m_source_locations) source_locations;
558  {
559  StdLockGuard scoped_lock(m_mutex);
560  source_locations.swap(m_source_locations);
561  m_suppression_active = false;
562  }
563  for (const auto& [source_loc, stats] : source_locations) {
564  if (stats.m_dropped_bytes == 0) continue;
566  LogFlags::ALL, Level::Warning, /*should_ratelimit=*/false,
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(),
569  stats.m_dropped_bytes, Ticks<std::chrono::seconds>(m_reset_window));
570  }
571 }
572 
574 {
575  if (bytes > m_available_bytes) {
576  m_dropped_bytes += bytes;
577  m_available_bytes = 0;
578  return false;
579  }
580 
581  m_available_bytes -= bytes;
582  return true;
583 }
584 
585 bool BCLog::Logger::SetLogLevel(std::string_view level_str)
586 {
587  const auto level = GetLogLevel(level_str);
588  if (!level.has_value() || level.value() > MAX_USER_SETABLE_SEVERITY_LEVEL) return false;
589  m_log_level = level.value();
590  return true;
591 }
592 
593 bool BCLog::Logger::SetCategoryLogLevel(std::string_view category_str, std::string_view level_str)
594 {
595  BCLog::LogFlags flag;
596  if (!GetLogCategory(flag, category_str)) return false;
597 
598  const auto level = GetLogLevel(level_str);
599  if (!level.has_value() || level.value() > MAX_USER_SETABLE_SEVERITY_LEVEL) return false;
600 
601  StdLockGuard scoped_lock(m_cs);
602  m_category_log_levels[flag] = level.value();
603  return true;
604 }
605 
606 bool util::log::ShouldLog(Category category, Level level)
607 {
608  return LogInstance().WillLogCategoryLevel(static_cast<BCLog::LogFlags>(category), level);
609 }
610 
612 {
613  BCLog::Logger& logger{LogInstance()};
614  if (logger.Enabled()) {
615  logger.LogPrintStr(std::move(entry.message), std::move(entry.source_loc), static_cast<BCLog::LogFlags>(entry.category), entry.level, entry.should_ratelimit);
616  }
617 }
Definition: log.h:49
void EnableCategory(LogFlags flag)
Definition: logging.cpp:123
void DisableLogging() EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
Disable logging This offers a slight speedup and slightly smaller memory usage compared to leaving th...
Definition: logging.cpp:111
int ret
StdMutex m_cs
Definition: logging.h:140
constexpr auto MAX_USER_SETABLE_SEVERITY_LEVEL
Definition: logging.cpp:24
BCLog::Logger & LogInstance()
Definition: logging.cpp:26
constexpr int64_t count_seconds(std::chrono::seconds t)
Definition: time.h:88
assert(!tx.IsCoinBase())
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:25
#define LogWarning(...)
Definition: log.h:96
Level
Definition: log.h:41
fs::path m_file_path
Definition: logging.h:185
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
bool GetLogCategory(BCLog::LogFlags &flag, std::string_view str)
Return true if str parses as a log category and set the flag.
Definition: logging.cpp:220
Status
Suppression status of a source log location.
Definition: logging.h:111
std::string threadname
Definition: logging.h:133
Status Consume(const SourceLocation &source_loc, const std::string &str) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Consumes source_loc&#39;s available bytes corresponding to the size of the (formatted) str and returns it...
Definition: logging.cpp:391
static size_t DynamicUsage(const int8_t &v)
Dynamic memory usage for built-in types is zero.
Definition: memusage.h:31
Category category
Definition: log.h:50
static constexpr std::array< BCLog::Level, 3 > LogLevelsList()
Log severity levels that can be selected by the user.
Definition: logging.cpp:289
std::string message
Definition: log.h:54
bool m_print_to_console
Definition: logging.h:176
SystemClock::time_point now
Definition: logging.h:131
std::string FormatISO8601DateTime(int64_t nTime)
ISO 8601 formatting is preferred.
Definition: time.cpp:83
std::string_view function_name_short() const
Definition: log.h:30
static size_t MemUsage(const BCLog::Logger::BufferedLog &buflog)
Definition: logging.cpp:369
LogFlags
Definition: categories.h:14
static const std::unordered_map< BCLog::LogFlags, std::string > LOG_CATEGORIES_BY_FLAG
Definition: logging.cpp:208
bool should_ratelimit
Hint for consumers if this entry should be ratelimited.
Definition: log.h:52
std::string_view RemovePrefixView(std::string_view str, std::string_view prefix)
Definition: string.h:182
std::string LogEscapeMessage(std::string_view str)
Belts and suspenders: make sure outgoing log messages don&#39;t contain potentially suspicious characters...
Definition: logging.cpp:329
bool m_print_to_file
Definition: logging.h:177
static int FileWriteStr(std::string_view str, FILE *fp)
Definition: logging.cpp:49
Fixed window rate limiter for logging.
Definition: logging.h:68
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.
Definition: logging.cpp:424
std::string category
Definition: logging.h:56
std::function< void(std::function< void()>, std::chrono::milliseconds)> SchedulerFunction
Definition: logging.h:93
std::string_view file_name() const
Definition: log.h:28
std::string LogTimestampStr(SystemClock::time_point now, std::chrono::seconds mocktime) const
Definition: logging.cpp:300
static const std::map< std::string, BCLog::LogFlags, std::less<> > LOG_CATEGORIES_BY_STR
Definition: logging.cpp:172
#define LOCK(cs)
Definition: sync.h:258
static std::shared_ptr< LogRateLimiter > Create(SchedulerFunction &&scheduler_func, uint64_t max_bytes, std::chrono::seconds reset_window)
Definition: logging.cpp:379
Level level
Definition: log.h:51
constexpr size_t DEFAULT_MAX_LOG_BUFFER
Definition: logging.h:62
bool StartLogging(const ArgsManager &args)
Definition: common.cpp:107
void DisableCategory(LogFlags flag)
Definition: logging.cpp:136
void SetCategoryLogLevel(const std::unordered_map< LogFlags, Level > &levels) EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
Definition: logging.h:246
void SetLogLevel(Level level)
Definition: logging.h:259
std::uint_least32_t line() const
Definition: log.h:29
bool WillLogCategory(LogFlags category) const
Definition: logging.cpp:149
#define LogPrintLevel_(category, level, should_ratelimit,...)
Definition: log.h:89
std::string GetLogPrefix(LogFlags category, Level level) const
Definition: logging.cpp:343
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
Definition: logging.cpp:407
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)
Definition: logging.cpp:431
static size_t MallocUsage(size_t alloc)
Compute the total memory used by allocating alloc bytes.
Definition: memusage.h:52
void DisconnectTestLogger() EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
Only for testing.
Definition: logging.cpp:98
void Reset() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Resets all usage to zero. Called periodically by the scheduler.
Definition: logging.cpp:555
static std::string LogLevelToStr(BCLog::Level level)
Returns the string representation of a log level.
Definition: logging.cpp:234
bool fLogIPs
Definition: logging.cpp:47
bool Consume(uint64_t bytes)
Updates internal accounting and returns true if enough available_bytes were remaining.
Definition: logging.cpp:573
bool StartLogging() EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
Start logging (and flush all buffered messages)
Definition: logging.cpp:54
std::string LogLevelsString() const
Returns a string with all user-selectable log levels.
Definition: logging.cpp:294
std::vector< LogCategory > LogCategoriesList() const
Returns a vector of the log categories in alphabetical order.
Definition: logging.cpp:278
void Log(Entry entry)
Send message to be logged.
Definition: logging.cpp:611
std::string ThreadGetInternalName()
Get the thread&#39;s internal (in-memory) name; used e.g.
Definition: threadnames.cpp:45
uint64_t Category
Opaque to util::log; interpreted by consumers (e.g., BCLog::LogFlags).
Definition: log.h:39
static const bool DEFAULT_LOGIPS
Definition: logging.h:28
static std::optional< BCLog::Level > GetLogLevel(std::string_view level_str)
Definition: logging.cpp:261
Like std::source_location, but allowing to override the function name.
Definition: log.h:18
bool WillLogCategoryLevel(LogFlags category, Level level) const EXCLUSIVE_LOCKS_REQUIRED(!m_cs)
Definition: logging.cpp:154
bool ShouldLog(Category category, Level level)
Return whether messages with specified category and level should be logged.
Definition: logging.cpp:606
std::chrono::seconds GetMockTime()
For testing.
Definition: time.cpp:52
LogRateLimiter(uint64_t max_bytes, std::chrono::seconds reset_window)
Definition: logging.cpp:376
const char *const DEFAULT_DEBUGLOGFILE
Definition: logging.cpp:23
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
Definition: string.h:205
void ShrinkDebugFile()
Definition: logging.cpp:514
SourceLocation source_loc
Definition: log.h:53
static std::string LogCategoryToStr(BCLog::LogFlags category)
Definition: logging.cpp:251
bool DefaultShrinkDebugFile() const
Definition: logging.cpp:167