Skip to content

Commit 2bd785a

Browse files
laanwjDmitriy Korniychuk
authored andcommitted
Merge bitcoin#11781: Add -debuglogfile option
5a7c09a test: Add tests for `-debuglogfile` with subdirs (Anthony Towns) 4158734 doc: Update release notes for `-debuglogfile` (Wladimir J. van der Laan) 2323242 test: Add test for `-debuglogfile` (Wladimir J. van der Laan) cf5f432 Add `-debuglogfile` option (Wladimir J. van der Laan) Pull request description: This patch adds an option to configure the name and/or directory of the debug log file. The user can specify either a relative path, in which case the path is relative to the (network specific) data directory. They can also specify an absolute path to put the log anywhere else in the file system. Alternative to bitcoin#11741 that gets rid of the concept of a "log directory" by specifying the path for the specific kind of log, the debug log. Which happens to be the only kind of log we have at this point*, but a hypothetical new kind of log (say, an audit log) would get a new option. This has more flexibility than specifying a directory which has to contain all of them. \* excluding `db.log` which is internally generated by the wallet database library, but that one moves along with `-walletdir`. Tree-SHA512: 4434d0e598dc23504e5c9e67fdbaef56db4f0fd490f9f54fd503e69d4dda9b5b69c539e1794ed841e72161b7b1dc3374d2f1193dd431b057566750e56fd8f24b
1 parent 9d088fd commit 2bd785a

File tree

5 files changed

+95
-14
lines changed

5 files changed

+95
-14
lines changed

src/init.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ std::string HelpMessage(HelpMessageMode mode)
445445
}
446446
strUsage += HelpMessageOpt("-dbcache=<n>", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache));
447447
strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file on startup"));
448+
strUsage += HelpMessageOpt("-debuglogfile=<file>", strprintf(_("Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)"), DEFAULT_DEBUGLOGFILE));
448449
strUsage += HelpMessageOpt("-maxorphantxsize=<n>", strprintf(_("Maximum total size of all orphan transactions in megabytes (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS_SIZE));
449450
strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE));
450451
strUsage += HelpMessageOpt("-mempoolexpiry=<n>", strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY));
@@ -1540,8 +1541,11 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
15401541
ShrinkDebugFile();
15411542
}
15421543

1543-
if (fPrintToDebugLog)
1544-
OpenDebugLog();
1544+
if (fPrintToDebugLog) {
1545+
if (!OpenDebugLog()) {
1546+
return InitError(strprintf("Could not open debug log file %s", GetDebugLogPath().string()));
1547+
}
1548+
}
15451549

15461550
if (!fLogTimestamps)
15471551
LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()));

src/util.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ int nWalletBackups = 10;
110110

111111
const char * const BITCOIN_CONF_FILENAME = "cosanta.conf";
112112
const char * const BITCOIN_PID_FILENAME = "cosantad.pid";
113+
const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
113114

114115
ArgsManager gArgs;
115116
bool fPrintToConsole = false;
@@ -211,26 +212,40 @@ static void DebugPrintInit()
211212
vMsgsBeforeOpenLog = new std::list<std::string>;
212213
}
213214

214-
void OpenDebugLog()
215+
fs::path GetDebugLogPath()
216+
{
217+
fs::path logfile(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE));
218+
if (logfile.is_absolute()) {
219+
return logfile;
220+
} else {
221+
return GetDataDir() / logfile;
222+
}
223+
}
224+
225+
bool OpenDebugLog()
215226
{
216227
boost::call_once(&DebugPrintInit, debugPrintInitFlag);
217228
boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
218229

219230
assert(fileout == nullptr);
220231
assert(vMsgsBeforeOpenLog);
221-
fs::path pathDebug = GetDataDir() / "debug.log";
232+
fs::path pathDebug = GetDebugLogPath();
233+
222234
fileout = fsbridge::fopen(pathDebug, "a");
223-
if (fileout) {
224-
setbuf(fileout, nullptr); // unbuffered
225-
// dump buffered messages from before we opened the log
226-
while (!vMsgsBeforeOpenLog->empty()) {
227-
FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
228-
vMsgsBeforeOpenLog->pop_front();
229-
}
235+
if (!fileout) {
236+
return false;
237+
}
238+
239+
setbuf(fileout, nullptr); // unbuffered
240+
// dump buffered messages from before we opened the log
241+
while (!vMsgsBeforeOpenLog->empty()) {
242+
FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
243+
vMsgsBeforeOpenLog->pop_front();
230244
}
231245

232246
delete vMsgsBeforeOpenLog;
233247
vMsgsBeforeOpenLog = nullptr;
248+
return true;
234249
}
235250

236251
struct CLogCategoryDesc
@@ -452,7 +467,7 @@ int LogPrintStr(const std::string &str)
452467
// reopen the log file, if requested
453468
if (fReopenDebugLog) {
454469
fReopenDebugLog = false;
455-
fs::path pathDebug = GetDataDir() / "debug.log";
470+
fs::path pathDebug = GetDebugLogPath();
456471
if (fsbridge::freopen(pathDebug,"a",fileout) != nullptr)
457472
setbuf(fileout, nullptr); // unbuffered
458473
}
@@ -883,7 +898,7 @@ void ShrinkDebugFile()
883898
// Amount of debug.log to save at end when shrinking (must fit in memory)
884899
constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
885900
// Scroll debug.log if it's getting too big
886-
fs::path pathLog = GetDataDir() / "debug.log";
901+
fs::path pathLog = GetDebugLogPath();
887902
FILE* file = fsbridge::fopen(pathLog, "r");
888903
// If debug.log file is more than 10% bigger the RECENT_DEBUG_HISTORY_SIZE
889904
// trim it down by saving only the last RECENT_DEBUG_HISTORY_SIZE bytes

src/util.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ static const bool DEFAULT_LOGTIMEMICROS = false;
5757
static const bool DEFAULT_LOGIPS = false;
5858
static const bool DEFAULT_LOGTIMESTAMPS = true;
5959
static const bool DEFAULT_LOGTHREADNAMES = false;
60+
extern const char * const DEFAULT_DEBUGLOGFILE;
6061

6162
/** Signals for translation. */
6263
class CTranslationInterface
@@ -241,7 +242,8 @@ void CreatePidFile(const fs::path &path, pid_t pid);
241242
#ifdef WIN32
242243
fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
243244
#endif
244-
void OpenDebugLog();
245+
fs::path GetDebugLogPath();
246+
bool OpenDebugLog();
245247
void ShrinkDebugFile();
246248
void runCommand(const std::string& strCommand);
247249

test/functional/feature_logging.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2017 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+
"""Test debug logging."""
6+
7+
import os
8+
9+
from test_framework.test_framework import BitcoinTestFramework
10+
11+
class LoggingTest(BitcoinTestFramework):
12+
def set_test_params(self):
13+
self.num_nodes = 1
14+
self.setup_clean_chain = True
15+
16+
def run_test(self):
17+
# test default log file name
18+
assert os.path.isfile(os.path.join(self.nodes[0].datadir, "regtest", "debug.log"))
19+
20+
# test alternative log file name in datadir
21+
self.restart_node(0, ["-debuglogfile=foo.log"])
22+
assert os.path.isfile(os.path.join(self.nodes[0].datadir, "regtest", "foo.log"))
23+
24+
# test alternative log file name outside datadir
25+
tempname = os.path.join(self.options.tmpdir, "foo.log")
26+
self.restart_node(0, ["-debuglogfile=%s" % tempname])
27+
assert os.path.isfile(tempname)
28+
29+
# check that invalid log (relative) will cause error
30+
invdir = os.path.join(self.nodes[0].datadir, "regtest", "foo")
31+
invalidname = os.path.join("foo", "foo.log")
32+
self.stop_node(0)
33+
self.assert_start_raises_init_error(0, ["-debuglogfile=%s" % (invalidname)],
34+
"Error: Could not open debug log file")
35+
assert not os.path.isfile(os.path.join(invdir, "foo.log"))
36+
37+
# check that invalid log (relative) works after path exists
38+
self.stop_node(0)
39+
os.mkdir(invdir)
40+
self.start_node(0, ["-debuglogfile=%s" % (invalidname)])
41+
assert os.path.isfile(os.path.join(invdir, "foo.log"))
42+
43+
# check that invalid log (absolute) will cause error
44+
self.stop_node(0)
45+
invdir = os.path.join(self.options.tmpdir, "foo")
46+
invalidname = os.path.join(invdir, "foo.log")
47+
self.assert_start_raises_init_error(0, ["-debuglogfile=%s" % invalidname],
48+
"Error: Could not open debug log file")
49+
assert not os.path.isfile(os.path.join(invdir, "foo.log"))
50+
51+
# check that invalid log (absolute) works after path exists
52+
self.stop_node(0)
53+
os.mkdir(invdir)
54+
self.start_node(0, ["-debuglogfile=%s" % (invalidname)])
55+
assert os.path.isfile(os.path.join(invdir, "foo.log"))
56+
57+
58+
if __name__ == '__main__':
59+
LoggingTest().main()

test/functional/test_runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@
143143
'feature_shutdown.py',
144144
'privatesend.py',
145145
'uacomment.py',
146+
'feature_logging.py',
146147
]
147148

148149
EXTENDED_SCRIPTS = [

0 commit comments

Comments
 (0)