diff options
| author | bitflash-maintainer <noreply@bitflash.invalid> | 2026-09-02 05:26:51 +0000 |
|---|---|---|
| committer | bitflash-maintainer <noreply@bitflash.invalid> | 2026-09-02 05:26:51 +0000 |
| commit | ae1c6a7b49d9b4f8cf7218c0baec84f348eb5ef6 (patch) | |
| tree | c8444d683f25d54135d5026eca4c677f24b7ab41 /src/util.h | |
| parent | e4f898c4a6b9900553c64b9804889b5fdae3e55f (diff) | |
log: cap debug.log in-process, and ship a logrotate policy
debug.log grew without bound (production: 1.95 GiB, 51-129 MB/day).
Nothing shrank it once the process was up -- there is no
ShrinkDebugFile in this tree, and upstream's only ran at startup.
OutputDebugStringF now rolls the file to debug.log.old when it
passes -maxdebugfilesize (MB, default 1024, 0 disables). The write
path already opens and closes the file per line under one lock, so
the rename-and-reopen is a few lines inside that lock and no fd can
be stranded mid-roll.
contrib/logrotate/bitflash-debug.logrotate is the longer-term policy
(size 1G, rotate 4, compress, missingok, notifempty, copytruncate);
copytruncate keeps the writer's append handle valid across rotation.
Closes #34
Diffstat (limited to 'src/util.h')
| -rw-r--r-- | src/util.h | 29 |
1 files changed, 29 insertions, 0 deletions
| @@ -87,6 +87,11 @@ inline T& REF(const T& val) | |||
| 87 | 87 | ||
| 88 | extern bool fDebug; | 88 | extern bool fDebug; |
| 89 | 89 | ||
| 90 | // debug.log is rolled to debug.log.old once it grows past this many bytes | ||
| 91 | // (set from -maxdebugfilesize, in MB; 0 disables the check). See the roll | ||
| 92 | // site in OutputDebugStringF() below. | ||
| 93 | extern int64 nMaxDebugFileSize; | ||
| 94 | |||
| 90 | // --------------------------------------------------------------------------- | 95 | // --------------------------------------------------------------------------- |
| 91 | // Categorized, burst-collapsing logging | 96 | // Categorized, burst-collapsing logging |
| 92 | // | 97 | // |
| @@ -391,6 +396,30 @@ inline int OutputDebugStringF(const char* pszFormat, ...) | |||
| 391 | strDebugFile = "debug.log"; | 396 | strDebugFile = "debug.log"; |
| 392 | } | 397 | } |
| 393 | FILE* fileout = fopen(strDebugFile.c_str(), "a"); | 398 | FILE* fileout = fopen(strDebugFile.c_str(), "a"); |
| 399 | if (fileout && nMaxDebugFileSize > 0) | ||
| 400 | { | ||
| 401 | // Roll an overgrown debug.log before adding to it. Nothing in the | ||
| 402 | // tree shrinks this file once the process is running (there is no | ||
| 403 | // ShrinkDebugFile, and even Bitcoin's only ran at startup), so a | ||
| 404 | // node that stays up for months grows the log without bound -- | ||
| 405 | // production hit ~2 GiB. The file is opened and closed per line, | ||
| 406 | // so a rename is safe here: the next line simply reopens the | ||
| 407 | // path. One generation is kept as debug.log.old; logrotate | ||
| 408 | // (contrib/logrotate/) handles anything longer-term. | ||
| 409 | int nSize = GetFilesize(fileout); | ||
| 410 | if (nSize >= 0 && (int64)nSize > nMaxDebugFileSize) | ||
| 411 | { | ||
| 412 | fclose(fileout); | ||
| 413 | string strOldFile = strDebugFile + ".old"; | ||
| 414 | remove(strOldFile.c_str()); // rename() won't clobber on Windows | ||
| 415 | rename(strDebugFile.c_str(), strOldFile.c_str()); | ||
| 416 | fileout = fopen(strDebugFile.c_str(), "a"); | ||
| 417 | if (fileout) | ||
| 418 | fprintf(fileout, | ||
| 419 | "debug.log grew past %lld MB; previous contents moved to debug.log.old (-maxdebugfilesize)\n", | ||
| 420 | (long long)(nMaxDebugFileSize / 1024 / 1024)); | ||
| 421 | } | ||
| 422 | } | ||
| 394 | if (fileout) | 423 | if (fileout) |
| 395 | { | 424 | { |
| 396 | va_list arg_ptr; | 425 | va_list arg_ptr; |