41 return fwrite(str.data(), 1, str.size(), fp);
48 assert(m_fileout ==
nullptr);
58 setbuf(m_fileout,
nullptr);
67 while (!m_msgs_before_open.empty()) {
68 const std::string &s = m_msgs_before_open.front();
74 fwrite(s.data(), 1, s.size(), stdout);
76 for (
const auto &cb : m_print_callbacks) {
80 m_msgs_before_open.pop_front();
92 if (m_fileout !=
nullptr) {
96 m_print_callbacks.clear();
132#ifdef DEBUG_LOCKCONTENTION
148 if (category_desc.category == str) {
149 flag = category_desc.flag;
161 std::sort(categories.begin(), categories.end(),
162 [](
auto a,
auto b) { return a.category < b.category; });
164 std::vector<LogCategory> ret;
171 catActive.
category = category_desc.category;
172 catActive.
active = WillLogCategory(category_desc.flag);
173 ret.push_back(catActive);
185 std::string strStamped;
187 if (!m_log_timestamps) {
191 if (m_started_new_line) {
194 if (m_log_time_micros) {
195 strStamped.pop_back();
196 strStamped +=
strprintf(
".%06dZ", nTimeMicros % 1000000);
200 strStamped +=
" (mocktime: " +
203 strStamped +=
' ' + str;
221 for (
char ch_in : str) {
222 uint8_t ch = (uint8_t)ch_in;
223 if ((ch >= 32 || ch ==
'\n') && ch !=
'\x7f') {
234 const std::string &logging_function,
235 const std::string &source_file,
236 const int source_line) {
240 if (m_log_sourcelocations && m_started_new_line) {
241 str_prefixed.insert(0,
"[" +
RemovePrefix(source_file,
"./") +
":" +
243 logging_function +
"] ");
246 if (m_log_threadnames && m_started_new_line) {
250 str_prefixed = LogTimestampStr(str_prefixed);
252 m_started_new_line = !str.empty() && str[str.size() - 1] ==
'\n';
256 m_msgs_before_open.push_back(str_prefixed);
260 if (m_print_to_console) {
262 fwrite(str_prefixed.data(), 1, str_prefixed.size(), stdout);
265 for (
const auto &cb : m_print_callbacks) {
268 if (m_print_to_file) {
269 assert(m_fileout !=
nullptr);
273 m_reopen_file =
false;
277 setbuf(m_fileout,
nullptr);
279 m_fileout = new_fileout;
288 constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
290 assert(!m_file_path.empty());
298 log_size = fs::file_size(m_file_path);
299 }
catch (
const fs::filesystem_error &) {
304 if (file && log_size > 11 * (RECENT_DEBUG_HISTORY_SIZE / 10)) {
306 std::vector<char> vch(RECENT_DEBUG_HISTORY_SIZE, 0);
307 if (fseek(file, -((
long)vch.size()), SEEK_END)) {
308 LogPrintf(
"Failed to shrink debug log file: fseek(...) failed\n");
312 int nBytes = fread(vch.data(), 1, vch.size(), file);
317 fwrite(vch.data(), 1, nBytes, file);
320 }
else if (file !=
nullptr) {
326 m_categories |= category;
334 EnableCategory(flag);
339 m_categories &= ~category;
347 DisableCategory(flag);
355 LogPrintf(
"Error trying to log using a category mask instead of an "
356 "explicit category.\n");
360 return (m_categories.load(std::memory_order_relaxed) & category) != 0;
bool WillLogCategory(LogFlags category) const
Return true if log accepts specified category.
std::string LogTimestampStr(const std::string &str)
void DisconnectTestLogger()
Only for testing.
bool DefaultShrinkDebugFile() const
Default for whether ShrinkDebugFile should be run.
std::vector< LogCategory > LogCategoriesList() const
Returns a vector of the log categories in alphabetical order.
void DisableCategory(LogFlags category)
void EnableCategory(LogFlags category)
bool StartLogging()
Start logging (and flush all buffered messages)
void LogPrintStr(const std::string &str, const std::string &logging_function, const std::string &source_file, const int source_line)
Send a string to the log output.
const CLogCategoryDesc LogCategories[]
static int FileWriteStr(const std::string &str, FILE *fp)
BCLog::Logger & LogInstance()
bool GetLogCategory(BCLog::LogFlags &flag, const std::string &str)
Return true if str parses as a log category and set the flag.
const char *const DEFAULT_DEBUGLOGFILE
static const bool DEFAULT_LOGIPS
std::string LogEscapeMessage(const std::string &str)
Belts and suspenders: make sure outgoing log messages don't contain potentially suspicious characters...
FILE * fopen(const fs::path &p, const char *mode)
const std::string & ThreadGetInternalName()
Get the thread's internal (in-memory) name; used e.g.
std::string RemovePrefix(std::string_view str, std::string_view prefix)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
int64_t GetTimeMicros()
Returns the system time (not mockable)
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)