From f7f58f08060dee84a5d41f1f84ca466f2ee062c6 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Thu, 13 Aug 2026 23:16:30 +0200 Subject: [PATCH] Move debug logs in `.tailwindcss` folder (#20416) Instead of writing debug logs (triggered by using `DEBUG=*`) in the root of the project as `tailwindcss-.log`, we will write them to `.tailwindcss/logs/scanner--.log` instead. The reasoning for this is that we won't pollute the root of the project. Another reason is that if you don't ignore `.log` files via `.gitignore`, it could be that you end up in a loop if you use `DEBUG=* vite` because a new `.log` file might trigger a new build. We noticed this while looking at https://github.com/tailwindlabs/tailwindcss/discussions/20382. The `.tailwindcss` folder will come with a `.gitignore` file that ignores everything (`*`). ## Test plan 1. Nothing really changed here, all tests should pass Testing this in a local project, it looks like this: file-35bfc43606c556f2380a161c7595d103 --- crates/oxide/src/scanner/init_tracing.rs | 46 ++++++++++++++++++++---- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/crates/oxide/src/scanner/init_tracing.rs b/crates/oxide/src/scanner/init_tracing.rs index 2a570ff20..dd4c1d071 100644 --- a/crates/oxide/src/scanner/init_tracing.rs +++ b/crates/oxide/src/scanner/init_tracing.rs @@ -37,20 +37,52 @@ pub fn init_tracing() { return; } - let file_path = format!("tailwindcss-{}.log", std::process::id()); - let file = OpenOptions::new() + let root = Path::new(".tailwindcss"); + let logs_dir = root.join("logs"); + if let Err(err) = std::fs::create_dir_all(&logs_dir) { + eprintln!( + "{} Failed to create {}, skipping debug logs ({err})", + dim("[DEBUG]"), + highlight(&logs_dir.display().to_string()) + ); + return; + } + + // Ensure everything inside `.tailwindcss/` is ignored by git. The file is only created if it + // doesn't exist yet, an existing `.gitignore` is left untouched. + if let Ok(mut file) = std::fs::File::create_new(root.join(".gitignore")) { + _ = file.write_all(b"*\n"); + } + + let file_path = logs_dir.join(format!( + "scanner-{}-{}.log", + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .map(|d| d.as_millis()) + .unwrap_or(0), + std::process::id() + )); + let file = match OpenOptions::new() .create(true) .append(true) .open(&file_path) - .unwrap_or_else(|_| panic!("Failed to open {file_path}")); + { + Ok(file) => file, + Err(err) => { + eprintln!( + "{} Failed to create {}, skipping debug logs ({err})", + dim("[DEBUG]"), + highlight(&file_path.display().to_string()) + ); + return; + } + }; - let file_path = Path::new(&file_path); - let absolute_file_path = dunce::canonicalize(file_path) - .unwrap_or_else(|_| panic!("Failed to canonicalize {file_path:?}")); + let absolute_file_path = dunce::canonicalize(&file_path).unwrap_or_else(|_| file_path.clone()); eprintln!( "{} Writing debug info to: {}\n", dim("[DEBUG]"), - highlight(absolute_file_path.as_path().to_str().unwrap()) + highlight(&absolute_file_path.display().to_string()) ); let file = Arc::new(Mutex::new(file));