Changeset View
Changeset View
Standalone View
Standalone View
src/logging.h
Show First 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | |||||
std::vector<CLogCategoryActive> ListActiveLogCategories(); | std::vector<CLogCategoryActive> ListActiveLogCategories(); | ||||
/** Return true if str parses as a log category and set the flag */ | /** Return true if str parses as a log category and set the flag */ | ||||
bool GetLogCategory(BCLog::LogFlags &flag, const std::string &str); | bool GetLogCategory(BCLog::LogFlags &flag, const std::string &str); | ||||
// Be conservative when using LogPrintf/error or other things which | // Be conservative when using LogPrintf/error or other things which | ||||
// unconditionally log to debug.log! It should not be the case that an inbound | // unconditionally log to debug.log! It should not be the case that an inbound | ||||
// peer can fill up a user's disk with debug.log entries. | // peer can fill up a user's disk with debug.log entries. | ||||
static inline void MarkUsed() {} | |||||
template <typename T, typename... Args> | |||||
static inline void MarkUsed(const T &t, const Args &... args) { | |||||
(void)t; | |||||
MarkUsed(args...); | |||||
} | |||||
template <typename... Args> | template <typename... Args> | ||||
std::string FormatStringFromLogArgs(const char *fmt, const Args &... args) { | static inline void LogPrintf(const char *fmt, const Args &... args) { | ||||
return fmt; | if (LogInstance().Enabled()) { | ||||
std::string log_msg; | |||||
try { | |||||
log_msg = tfm::format(fmt, args...); | |||||
} catch (tinyformat::format_error &fmterr) { | |||||
/** | |||||
* Original format string will have newline so don't add one here | |||||
*/ | |||||
log_msg = "Error \"" + std::string(fmterr.what()) + | |||||
"\" while formatting log message: " + fmt; | |||||
} | |||||
LogInstance().LogPrintStr(log_msg); | |||||
} | |||||
} | } | ||||
#ifdef USE_COVERAGE | // Use a macro instead of a function for conditional logging to prevent | ||||
#define LogPrintf(...) \ | // evaluating arguments when logging for the category is not enabled. | ||||
do { \ | |||||
MarkUsed(__VA_ARGS__); \ | |||||
} while (0) | |||||
#define LogPrint(category, ...) \ | |||||
do { \ | |||||
MarkUsed(__VA_ARGS__); \ | |||||
} while (0) | |||||
#else | |||||
#define LogPrintf(...) \ | |||||
do { \ | |||||
if (LogInstance().Enabled()) { \ | |||||
/* Unlikely name to avoid shadowing variables */ \ | |||||
std::string _log_msg_; \ | |||||
try { \ | |||||
_log_msg_ = tfm::format(__VA_ARGS__); \ | |||||
} catch (tinyformat::format_error & fmterr) { \ | |||||
/** \ | |||||
* Original format string will have newline so don't add one \ | |||||
* here \ | |||||
*/ \ | |||||
_log_msg_ = "Error \"" + std::string(fmterr.what()) + \ | |||||
"\" while formatting log message: " + \ | |||||
FormatStringFromLogArgs(__VA_ARGS__); \ | |||||
} \ | |||||
LogInstance().LogPrintStr(_log_msg_); \ | |||||
} \ | |||||
} while (0) | |||||
#define LogPrint(category, ...) \ | #define LogPrint(category, ...) \ | ||||
do { \ | do { \ | ||||
if (LogAcceptCategory((category))) { \ | if (LogAcceptCategory((category))) { \ | ||||
LogPrintf(__VA_ARGS__); \ | LogPrintf(__VA_ARGS__); \ | ||||
} \ | } \ | ||||
} while (0) | } while (0) | ||||
#endif | |||||
/** | /** | ||||
* These are aliases used to explicitly state that the message should not end | * These are aliases used to explicitly state that the message should not end | ||||
* with a newline character. It allows for detecting the missing newlines that | * with a newline character. It allows for detecting the missing newlines that | ||||
* could make the logs hard to read. | * could make the logs hard to read. | ||||
*/ | */ | ||||
#define LogPrintfToBeContinued LogPrintf | #define LogPrintfToBeContinued LogPrintf | ||||
#define LogPrintToBeContinued LogPrint | #define LogPrintToBeContinued LogPrint | ||||
#endif // BITCOIN_LOGGING_H | #endif // BITCOIN_LOGGING_H |