aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Posen <jimpo@coinbase.com>2018-04-11 10:03:21 -0700
committerJim Posen <jimpo@coinbase.com>2018-04-27 16:09:59 -0700
commitf55f4fcf05a53fdf618b4c69ddcf4c43b14e84c2 (patch)
treed5e549d544757a7d0aa1bd2fbcef5be376af8823
parent17266a13067c061783e0428c6200985ed8872b16 (diff)
util: Establish global logger object.
The object encapsulates logging configuration, and in a later commit, set up routines will also be moved into the class.
-rw-r--r--src/bench/bench_bitcoin.cpp2
-rw-r--r--src/init.cpp15
-rw-r--r--src/logging.cpp37
-rw-r--r--src/logging.h47
-rw-r--r--src/test/test_bitcoin.cpp2
-rw-r--r--src/util.h2
6 files changed, 66 insertions, 39 deletions
diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp
index 1d87883522..f08c099c16 100644
--- a/src/bench/bench_bitcoin.cpp
+++ b/src/bench/bench_bitcoin.cpp
@@ -46,7 +46,7 @@ main(int argc, char** argv)
RandomInit();
ECC_Start();
SetupEnvironment();
- fPrintToDebugLog = false; // don't want to write to debug.log file
+ g_logger->fPrintToDebugLog = false; // don't want to write to debug.log file
int64_t evaluations = gArgs.GetArg("-evals", DEFAULT_BENCH_EVALUATIONS);
std::string regex_filter = gArgs.GetArg("-filter", DEFAULT_BENCH_FILTER);
diff --git a/src/init.cpp b/src/init.cpp
index 99dab605ac..814fd39448 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -305,7 +305,7 @@ static void HandleSIGTERM(int)
static void HandleSIGHUP(int)
{
- fReopenDebugLog = true;
+ g_logger->fReopenDebugLog = true;
}
#ifndef WIN32
@@ -831,10 +831,11 @@ void InitLogging()
// debug.log.
LogPrintf("\n\n\n\n\n");
- fPrintToConsole = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false));
- fPrintToDebugLog = !gArgs.IsArgNegated("-debuglogfile");
- fLogTimestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
- fLogTimeMicros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
+ g_logger->fPrintToConsole = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false));
+ g_logger->fPrintToDebugLog = !gArgs.IsArgNegated("-debuglogfile");
+ g_logger->fLogTimestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
+ g_logger->fLogTimeMicros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
+
fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS);
std::string version_string = FormatFullVersion();
@@ -1230,7 +1231,7 @@ bool AppInitMain()
#ifndef WIN32
CreatePidFile(GetPidFile(), getpid());
#endif
- if (fPrintToDebugLog) {
+ if (g_logger->fPrintToDebugLog) {
if (gArgs.GetBoolArg("-shrinkdebugfile", logCategories == BCLog::NONE)) {
// Do this first since it both loads a bunch of debug.log into memory,
// and because this needs to happen before any other debug.log printing
@@ -1241,7 +1242,7 @@ bool AppInitMain()
}
}
- if (!fLogTimestamps)
+ if (!g_logger->fLogTimestamps)
LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime()));
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
LogPrintf("Using data directory %s\n", GetDataDir().string());
diff --git a/src/logging.cpp b/src/logging.cpp
index e481582321..de222d9465 100644
--- a/src/logging.cpp
+++ b/src/logging.cpp
@@ -12,13 +12,22 @@
const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
-bool fPrintToConsole = false;
-bool fPrintToDebugLog = true;
+/**
+ * NOTE: the logger instances is leaked on exit. This is ugly, but will be
+ * cleaned up by the OS/libc. Defining a logger as a global object doesn't work
+ * since the order of destruction of static/global objects is undefined.
+ * Consider if the logger gets destroyed, and then some later destructor calls
+ * LogPrintf, maybe indirectly, and you get a core dump at shutdown trying to
+ * access the logger. When the shutdown sequence is fully audited and tested,
+ * explicit destruction of these objects can be implemented by changing this
+ * from a raw pointer to a std::unique_ptr.
+ *
+ * This method of initialization was originally introduced in
+ * ee3374234c60aba2cc4c5cd5cac1c0aefc2d817c.
+ */
+BCLog::Logger* const g_logger = new BCLog::Logger();
-bool fLogTimestamps = DEFAULT_LOGTIMESTAMPS;
-bool fLogTimeMicros = DEFAULT_LOGTIMEMICROS;
bool fLogIPs = DEFAULT_LOGIPS;
-std::atomic<bool> fReopenDebugLog(false);
/** Log categories bitfield. */
std::atomic<uint32_t> logCategories(0);
@@ -174,19 +183,14 @@ std::vector<CLogCategoryActive> ListActiveLogCategories()
return ret;
}
-/**
- * fStartedNewLine is a state variable held by the calling context that will
- * suppress printing of the timestamp when multiple calls are made that don't
- * end in a newline. Initialize it to true, and hold it, in the calling context.
- */
-static std::string LogTimestampStr(const std::string &str, std::atomic_bool *fStartedNewLine)
+std::string BCLog::Logger::LogTimestampStr(const std::string &str)
{
std::string strStamped;
if (!fLogTimestamps)
return str;
- if (*fStartedNewLine) {
+ if (fStartedNewLine) {
int64_t nTimeMicros = GetTimeMicros();
strStamped = FormatISO8601DateTime(nTimeMicros/1000000);
if (fLogTimeMicros) {
@@ -202,19 +206,18 @@ static std::string LogTimestampStr(const std::string &str, std::atomic_bool *fSt
strStamped = str;
if (!str.empty() && str[str.size()-1] == '\n')
- *fStartedNewLine = true;
+ fStartedNewLine = true;
else
- *fStartedNewLine = false;
+ fStartedNewLine = false;
return strStamped;
}
-int LogPrintStr(const std::string &str)
+int BCLog::Logger::LogPrintStr(const std::string &str)
{
int ret = 0; // Returns total number of characters written
- static std::atomic_bool fStartedNewLine(true);
- std::string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
+ std::string strTimestamped = LogTimestampStr(str);
if (fPrintToConsole) {
// print to console
diff --git a/src/logging.h b/src/logging.h
index 4053f75acf..1ccf9136fd 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -19,13 +19,7 @@ static const bool DEFAULT_LOGIPS = false;
static const bool DEFAULT_LOGTIMESTAMPS = true;
extern const char * const DEFAULT_DEBUGLOGFILE;
-extern bool fPrintToConsole;
-extern bool fPrintToDebugLog;
-
-extern bool fLogTimestamps;
-extern bool fLogTimeMicros;
extern bool fLogIPs;
-extern std::atomic<bool> fReopenDebugLog;
extern std::atomic<uint32_t> logCategories;
@@ -61,7 +55,39 @@ namespace BCLog {
LEVELDB = (1 << 20),
ALL = ~(uint32_t)0,
};
-}
+
+ class Logger
+ {
+ private:
+ /**
+ * fStartedNewLine is a state variable that will suppress printing of
+ * the timestamp when multiple calls are made that don't end in a
+ * newline.
+ */
+ std::atomic_bool fStartedNewLine{true};
+
+ std::string LogTimestampStr(const std::string& str);
+
+ public:
+ bool fPrintToConsole = false;
+ bool fPrintToDebugLog = true;
+
+ bool fLogTimestamps = DEFAULT_LOGTIMESTAMPS;
+ bool fLogTimeMicros = DEFAULT_LOGTIMEMICROS;
+
+ std::atomic<bool> fReopenDebugLog{false};
+
+ /** Send a string to the log output */
+ int LogPrintStr(const std::string &str);
+
+ /** Returns whether logs will be written to any output */
+ bool Enabled() const { return fPrintToConsole || fPrintToDebugLog; }
+ };
+
+} // namespace BCLog
+
+extern BCLog::Logger* const g_logger;
+
/** Return true if log accepts specified category */
static inline bool LogAcceptCategory(uint32_t category)
{
@@ -77,9 +103,6 @@ std::vector<CLogCategoryActive> ListActiveLogCategories();
/** Return true if str parses as a log category and set the flags in f */
bool GetLogCategory(uint32_t *f, const std::string *str);
-/** Send a string to the log output */
-int LogPrintStr(const std::string &str);
-
/** Get format string from VA_ARGS for error reporting */
template<typename... Args> std::string FormatStringFromLogArgs(const char *fmt, const Args&... args) { return fmt; }
@@ -99,7 +122,7 @@ template<typename T, typename... Args> static inline void MarkUsed(const T& t, c
#define LogPrint(category, ...) do { MarkUsed(__VA_ARGS__); } while(0)
#else
#define LogPrintf(...) do { \
- if (fPrintToConsole || fPrintToDebugLog) { \
+ if (g_logger->Enabled()) { \
std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \
try { \
_log_msg_ = tfm::format(__VA_ARGS__); \
@@ -107,7 +130,7 @@ template<typename T, typename... Args> static inline void MarkUsed(const T& t, c
/* 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__); \
} \
- LogPrintStr(_log_msg_); \
+ g_logger->LogPrintStr(_log_msg_); \
} \
} while(0)
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index e9873f4526..fa59a9ce34 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -47,7 +47,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
SetupNetworking();
InitSignatureCache();
InitScriptExecutionCache();
- fPrintToDebugLog = false; // don't want to write to debug.log file
+ g_logger->fPrintToDebugLog = false; // don't want to write to debug.log file
fCheckBlockIndex = true;
SelectParams(chainName);
noui_connect();
diff --git a/src/util.h b/src/util.h
index ce94f396af..2da8023285 100644
--- a/src/util.h
+++ b/src/util.h
@@ -66,7 +66,7 @@ bool SetupNetworking();
template<typename... Args>
bool error(const char* fmt, const Args&... args)
{
- LogPrintStr("ERROR: " + tfm::format(fmt, args...) + "\n");
+ LogPrintf("ERROR: %s\n", tfm::format(fmt, args...));
return false;
}