Skip to content

Commit 05fe2d7

Browse files
laanwjgades
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 1d54500 commit 05fe2d7

File tree

5 files changed

+96
-15
lines changed

5 files changed

+96
-15
lines changed

src/init.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ std::string HelpMessage(HelpMessageMode mode)
446446
}
447447
strUsage += HelpMessageOpt("-dbcache=<n>", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache));
448448
strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file on startup"));
449+
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));
449450
strUsage += HelpMessageOpt("-maxorphantxsize=<n>", strprintf(_("Maximum total size of all orphan transactions in megabytes (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS_SIZE));
450451
strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE));
451452
strUsage += HelpMessageOpt("-mempoolexpiry=<n>", strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY));
@@ -1526,8 +1527,11 @@ bool AppInitMain()
15261527
ShrinkDebugFile();
15271528
}
15281529

1529-
if (fPrintToDebugLog)
1530-
OpenDebugLog();
1530+
if (fPrintToDebugLog) {
1531+
if (!OpenDebugLog()) {
1532+
return InitError(strprintf("Could not open debug log file %s", GetDebugLogPath().string()));
1533+
}
1534+
}
15311535

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

src/util.cpp

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ bool fLiteMode = false;
108108
int nWalletBackups = 10;
109109

110110
const char * const BITCOIN_CONF_FILENAME = "cosanta.conf";
111-
const char * const BITCOIN_PID_FILENAME = "cosantad.pid";
111+
const char * const BITCOIN_PID_FILENAME = "cosanta.pid";
112+
const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
112113

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

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

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

231245
delete vMsgsBeforeOpenLog;
232246
vMsgsBeforeOpenLog = nullptr;
247+
return true;
233248
}
234249

235250
struct CLogCategoryDesc
@@ -447,7 +462,7 @@ int LogPrintStr(const std::string &str)
447462
// reopen the log file, if requested
448463
if (fReopenDebugLog) {
449464
fReopenDebugLog = false;
450-
fs::path pathDebug = GetDataDir() / "debug.log";
465+
fs::path pathDebug = GetDebugLogPath();
451466
if (fsbridge::freopen(pathDebug,"a",fileout) != nullptr)
452467
setbuf(fileout, nullptr); // unbuffered
453468
}
@@ -1005,7 +1020,7 @@ void ShrinkDebugFile()
10051020
// Amount of debug.log to save at end when shrinking (must fit in memory)
10061021
constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
10071022
// Scroll debug.log if it's getting too big
1008-
fs::path pathLog = GetDataDir() / "debug.log";
1023+
fs::path pathLog = GetDebugLogPath();
10091024
FILE* file = fsbridge::fopen(pathLog, "r");
10101025
// If debug.log file is more than 10% bigger the RECENT_DEBUG_HISTORY_SIZE
10111026
// 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
@@ -59,6 +59,7 @@ static const bool DEFAULT_LOGTIMEMICROS = false;
5959
static const bool DEFAULT_LOGIPS = false;
6060
static const bool DEFAULT_LOGTIMESTAMPS = true;
6161
static const bool DEFAULT_LOGTHREADNAMES = false;
62+
extern const char * const DEFAULT_DEBUGLOGFILE;
6263

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

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)