From 7e8029027e5eadb890a45750ce738e94af110391 Mon Sep 17 00:00:00 2001 From: Edouard Vanbelle Date: Sun, 23 Aug 2026 17:19:08 +0200 Subject: [PATCH] fix(dedup): log the manifest reap predicate at info, not debug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reap statement is assembled from the registered reference sources, so it cannot be grepped out of the source tree — and it DELETES manifests. Hiding it behind a debug filter an operator has to know to enable was the wrong default: if what GC considers "referenced" ever changes, that has to be visible on the next boot without anyone going looking for it. Reported in testing: `RUST_LOG=info,oxicloud::dedup=debug` did not surface it, while a global `RUST_LOG=debug` did — at the cost of an unusably noisy boot. Rather than have operators carry a special filter for a line describing a destructive statement, promote it. The statement is whitespace-collapsed into a single `statement` field so a multi-line query does not sprawl across the boot log, and the registered `sources` are logged alongside it — that list is what actually determines the predicate, so a change to it is the thing worth noticing. Co-Authored-By: Claude Opus 5 (1M context) --- src/infrastructure/services/dedup_service.rs | 21 +++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/infrastructure/services/dedup_service.rs b/src/infrastructure/services/dedup_service.rs index cc1b68db..af416b19 100644 --- a/src/infrastructure/services/dedup_service.rs +++ b/src/infrastructure/services/dedup_service.rs @@ -619,9 +619,16 @@ impl DedupService { self.backend.initialize().await?; // The reap statement is assembled from the registered reference - // sources, so it is not greppable in the source tree. Log it once so an - // operator can read — or paste into psql — exactly what GC will delete. - tracing::debug!( + // sources, so it is not greppable in the source tree. It DELETES + // manifests, so log it unconditionally at info rather than hiding it + // behind a filter an operator has to know to enable — if what GC + // considers "referenced" ever changes, that must be visible on the + // next boot without anyone going looking. + // + // Whitespace-collapsed to a single field so a multi-line query does + // not sprawl across the boot log; expand it with + // `sed 's/ AND / AND\n /g'` or just paste it into psql. + tracing::info!( target: "oxicloud::dedup", sources = ?self .reference_registry @@ -629,8 +636,12 @@ impl DedupService { .iter() .map(|s| s.source_name()) .collect::>(), - "manifest reap statement:\n{}", - self.manifest_reap_sql, + statement = %self + .manifest_reap_sql + .split_whitespace() + .collect::>() + .join(" "), + "🧹 manifest reap predicate registered" ); let blob_count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM storage.blobs")