From 3c2b151d985d9b9bf996eed9c4b7f9f1c4b98edf Mon Sep 17 00:00:00 2001 From: Vlad Ilyushchenko Date: Wed, 17 Jun 2026 15:54:15 +0100 Subject: [PATCH] Quiet only test-only drainer setup-failure log BackgroundDrainer.run() logged every setup failure at ERROR with a full stack trace. The @TestOnly no-arg drainer constructs with a null slot and zero segment size, so it fails fast by design as soon as it runs; BackgroundDrainerPoolListenerTest and BackgroundDrainerPoolRaceTest each emit a burst of these stack traces that floods the test console. Keep ERROR for real orphan slots. In production a drainer always carries a non-null slot path from OrphanScanner, and a setup failure there means unacked data buffered on disk could not be drained to the server -- a durability concern operators must see. Demoting that to DEBUG would hide a real signal, so only the synthetic null-slot test path is quieted to DEBUG, guarded by isDebugEnabled() so SLF4J allocates no varargs array and formats no message when DEBUG is off. The failure stays observable regardless of log level: run() still drops the .failed sentinel via OrphanScanner.markFailed(), sets the FAILED outcome (counted by the pool), and records lastErrorMessage. --- .../qwp/client/sf/cursor/BackgroundDrainer.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/io/questdb/client/cutlass/qwp/client/sf/cursor/BackgroundDrainer.java b/core/src/main/java/io/questdb/client/cutlass/qwp/client/sf/cursor/BackgroundDrainer.java index 9bffdf1f..d54a01dc 100644 --- a/core/src/main/java/io/questdb/client/cutlass/qwp/client/sf/cursor/BackgroundDrainer.java +++ b/core/src/main/java/io/questdb/client/cutlass/qwp/client/sf/cursor/BackgroundDrainer.java @@ -313,7 +313,18 @@ public void run() { outcome = DrainOutcome.STOPPED; } catch (Throwable t) { String msg = t.getMessage(); - LOG.error("drainer setup failed for slot {}: {}", slotPath, msg, t); + if (slotPath != null) { + // Real orphan slot: a setup failure means unacked data on disk + // could not be drained to the server -- a durability concern + // that stays at ERROR so operators see it. + LOG.error("drainer setup failed for slot {}: {}", slotPath, msg, t); + } else if (LOG.isDebugEnabled()) { + // Only @TestOnly drainers carry a null slot (zero segment size); + // they fast-fail by design and would otherwise flood CI logs. + // The isDebugEnabled() guard avoids the varargs array and the + // message formatting when DEBUG is off, so it makes no garbage. + LOG.debug("drainer setup failed for slot {}: {}", slotPath, msg, t); + } lastErrorMessage = msg; try { OrphanScanner.markFailed(slotPath, "setup: " + msg);