From b1fe0cfefb29fe9cc4469f0575dfb5a5f4dd2f03 Mon Sep 17 00:00:00 2001 From: Administrator Date: Tue, 28 Apr 2026 11:11:24 +0200 Subject: [PATCH] fix(log): auto-rotate the other 3 internal log files (debug, rot, doodstream) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3.3.2 fixed fileuploader.log unbounded growth, but three siblings kept growing without limit: - upload-debug.log (verbose, every IPC + progress event log line) - account-rotation.log (every rotation decision) - doodstream-debug.log (per-hoster trace from lib/doodstream-upload.js) A multi-month dev install or a heavy production user could fill the log dir with multi-GB files and slow every appendFile. Wire all three through the same lib/log-rotation.js helper: - upload-debug.log → 25 MB cap, 2 numbered backups (~75 MB worst) - account-rotation.log → 10 MB cap, 2 numbered backups (~30 MB worst) - doodstream-debug.log → 10 MB cap, 1 numbered backup (~20 MB worst) The rotation check runs once per flush call (each is debounced or already a once-per-event path), so the statSync overhead is microscopic. _flushDebugLog passes a noop logger to avoid recursing into itself; _flushRotLog and _debugLog (doodstream) use the normal debugLog so any rotation surprises end up in upload-debug.log. 126/126 tests still green. --- lib/doodstream-upload.js | 10 +++++++++- main.js | 17 ++++++++++++++++- tasks/todo.md | 1 + 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/lib/doodstream-upload.js b/lib/doodstream-upload.js index 76c28c2..962b7eb 100644 --- a/lib/doodstream-upload.js +++ b/lib/doodstream-upload.js @@ -7,10 +7,18 @@ const BASE_URL = 'https://doodstream.com'; const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'; const UPLOAD_TIMEOUT = 1800000; // 30 min +// Cap doodstream's per-hoster debug log alongside the main log files so +// dev-mode sessions don't accumulate gigabytes of upload trace. +const { maybeRotateLogFile } = require('./log-rotation'); +const _DOODSTREAM_LOG_PATH = path.join(__dirname, '..', 'doodstream-debug.log'); +const _DOODSTREAM_LOG_MAX_BYTES = 10 * 1024 * 1024; +const _DOODSTREAM_LOG_MAX_BACKUPS = 1; + function _debugLog(msg) { try { + maybeRotateLogFile(_DOODSTREAM_LOG_PATH, _DOODSTREAM_LOG_MAX_BYTES, _DOODSTREAM_LOG_MAX_BACKUPS); const ts = new Date().toISOString(); - fs.appendFileSync(path.join(__dirname, '..', 'doodstream-debug.log'), `[${ts}] ${msg}\n`); + fs.appendFileSync(_DOODSTREAM_LOG_PATH, `[${ts}] ${msg}\n`); } catch {} } diff --git a/main.js b/main.js index d0991d9..4838f03 100644 --- a/main.js +++ b/main.js @@ -76,12 +76,24 @@ const _debugLogBuffer = []; let _debugLogFlushTimer = null; let _debugLogWriting = false; +// 25 MB cap for upload-debug.log + 10 MB for account-rotation.log. Each +// keeps 2 numbered backups, so the on-disk worst case is bounded: +// upload-debug ~75 MB, account-rotation ~30 MB. Reuses the same +// lib/log-rotation.js helper that fileuploader.log already uses. +const DEBUG_LOG_MAX_BYTES = 25 * 1024 * 1024; +const ROT_LOG_MAX_BYTES = 10 * 1024 * 1024; +const INTERNAL_LOG_MAX_BACKUPS = 2; + function _flushDebugLog() { if (_debugLogWriting || _debugLogBuffer.length === 0) return; const chunk = _debugLogBuffer.join(''); _debugLogBuffer.length = 0; _debugLogWriting = true; - fs.appendFile(getDebugLogPath(), chunk, 'utf-8', () => { + const target = getDebugLogPath(); + // Pass a noop logger here — debugLog() is THIS file's writer, recursing + // into it would deadlock the buffer/timer state. + maybeRotateLogFile(target, DEBUG_LOG_MAX_BYTES, INTERNAL_LOG_MAX_BACKUPS, () => {}); + fs.appendFile(target, chunk, 'utf-8', () => { _debugLogWriting = false; // If more lines arrived during the write, flush them next tick. if (_debugLogBuffer.length) setImmediate(_flushDebugLog); @@ -128,6 +140,9 @@ function _flushRotLog() { try { fs.mkdirSync(path.dirname(tryTargets[i]), { recursive: true }); } catch {} + // Cap account-rotation.log so a long-running install can't keep + // growing it indefinitely (rotation events fire on every account-fail). + maybeRotateLogFile(tryTargets[i], ROT_LOG_MAX_BYTES, INTERNAL_LOG_MAX_BACKUPS, debugLog); fs.appendFile(tryTargets[i], chunk, 'utf-8', (err) => { if (err) return write(i + 1); _rotLogWriting = false; diff --git a/tasks/todo.md b/tasks/todo.md index 4e7605c..9aa1b49 100644 --- a/tasks/todo.md +++ b/tasks/todo.md @@ -17,6 +17,7 @@ - ✅ 3.3.13 — `save-global-settings-sync` reportet jetzt `returnValue=false` bei Fehlern + debugLog statt silent swallow; TOCTOU bei .bak-Refresh in beiden Pfaden (main.js + lib/config-store.js _atomicWrite) entkoppelt: bak-Read-Failure failt nicht mehr den ganzen Save (deep-audit findings HIGH-2 + MED-4) - ✅ 3.3.14 — Parser-null-payload guard: `uploadFile` normalisiert payload zu `{}` falls `JSON.parse('null')` o.ä.; `parseDoodstreamResult` + `parseByseResult` haben defensive guards für direct callers + 7 neue Unit-Tests (null/non-object, malformed entries, fileRejected/accountError flips, valid filecode happy path) - ✅ 3.3.15 — Cancellation latency fix: nach `_sleep(800)` in der rotation-while-loop wird `signal.aborted`/`stopAfterActive` re-checkt bevor das ganze override-resolution-Setup läuft (deep-audit MED-5) +- ✅ 3.3.16 — Auto-Rotation für die anderen 3 internen Logs (`upload-debug.log` 25 MB, `account-rotation.log` 10 MB, `doodstream-debug.log` 10 MB), je 2 Backups — alle nutzen `lib/log-rotation.js` (zuvor nur `fileuploader.log` rotiert) ## Open items (priorisiert)