From 0b63ad6556e89bb82caad5d619808f03f37fd3a6 Mon Sep 17 00:00:00 2001 From: zhom <2717306+zhom@users.noreply.github.com> Date: Wed, 26 Nov 2025 20:21:17 +0400 Subject: [PATCH] refactor: add proper logging --- package.json | 1 + pnpm-lock.yaml | 10 + src-tauri/Cargo.lock | 303 ++++++++++++++++++ src-tauri/Cargo.toml | 3 +- src-tauri/capabilities/default.json | 3 +- src-tauri/src/api_client.rs | 102 +++--- src-tauri/src/app_auto_updater.rs | 149 ++++----- src-tauri/src/auto_updater.rs | 31 +- src-tauri/src/bin/proxy_server.rs | 37 ++- src-tauri/src/browser.rs | 20 +- src-tauri/src/browser_runner.rs | 293 ++++++++++------- src-tauri/src/browser_version_manager.rs | 14 +- src-tauri/src/camoufox_manager.rs | 8 +- src-tauri/src/downloaded_browsers_registry.rs | 115 +++---- src-tauri/src/downloader.rs | 18 +- src-tauri/src/extraction.rs | 100 +++--- src-tauri/src/group_manager.rs | 6 +- src-tauri/src/lib.rs | 137 +++++--- src-tauri/src/platform_browser.rs | 94 +++--- src-tauri/src/profile/manager.rs | 116 ++++--- src-tauri/src/profile_importer.rs | 2 +- src-tauri/src/proxy_manager.rs | 42 +-- src-tauri/src/proxy_runner.rs | 2 +- src-tauri/src/proxy_server.rs | 64 ++-- src-tauri/src/settings_manager.rs | 6 +- src-tauri/src/version_updater.rs | 26 +- src/app/layout.tsx | 6 + src/lib/logger.ts | 42 +++ 28 files changed, 1119 insertions(+), 631 deletions(-) create mode 100644 src/lib/logger.ts diff --git a/package.json b/package.json index 80b92ed..f4c6615 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@tauri-apps/plugin-deep-link": "^2.4.5", "@tauri-apps/plugin-dialog": "^2.4.2", "@tauri-apps/plugin-fs": "~2.4.4", + "@tauri-apps/plugin-log": "^2.7.1", "@tauri-apps/plugin-opener": "^2.5.2", "ahooks": "^3.9.6", "class-variance-authority": "^0.7.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 58e602c..50f3067 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,9 @@ importers: '@tauri-apps/plugin-fs': specifier: ~2.4.4 version: 2.4.4 + '@tauri-apps/plugin-log': + specifier: ^2.7.1 + version: 2.7.1 '@tauri-apps/plugin-opener': specifier: ^2.5.2 version: 2.5.2 @@ -1777,6 +1780,9 @@ packages: '@tauri-apps/plugin-fs@2.4.4': resolution: {integrity: sha512-MTorXxIRmOnOPT1jZ3w96vjSuScER38ryXY88vl5F0uiKdnvTKKTtaEjTEo8uPbl4e3gnUtfsDVwC7h77GQLvQ==} + '@tauri-apps/plugin-log@2.7.1': + resolution: {integrity: sha512-jdb+o0wxQc8PjnLktgGpOs9Dh1YupaOGDXzO+Y8peA1UZ1ep3eXv4E1oiJ7nIQVN0XUFDDhnn3aBszl8ijhR+A==} + '@tauri-apps/plugin-opener@2.5.2': resolution: {integrity: sha512-ei/yRRoCklWHImwpCcDK3VhNXx+QXM9793aQ64YxpqVF0BDuuIlXhZgiAkc15wnPVav+IbkYhmDJIv5R326Mew==} @@ -4398,6 +4404,10 @@ snapshots: dependencies: '@tauri-apps/api': 2.9.0 + '@tauri-apps/plugin-log@2.7.1': + dependencies: + '@tauri-apps/api': 2.9.0 + '@tauri-apps/plugin-opener@2.5.2': dependencies: '@tauri-apps/api': 2.9.0 diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 5cdd1c3..4d3f395 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -43,6 +43,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.16", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "1.1.4" @@ -67,6 +78,23 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "android_log-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" + +[[package]] +name = "android_logger" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3" +dependencies = [ + "android_log-sys", + "env_filter", + "log", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -153,6 +181,12 @@ dependencies = [ "password-hash", ] +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "ashpd" version = "0.11.0" @@ -445,6 +479,18 @@ dependencies = [ "serde_core", ] +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake2" version = "0.10.6" @@ -494,6 +540,29 @@ dependencies = [ "piper", ] +[[package]] +name = "borsh" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" +dependencies = [ + "borsh-derive", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" +dependencies = [ + "once_cell", + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "brotli" version = "8.0.2" @@ -521,6 +590,40 @@ version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +[[package]] +name = "byte-unit" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6d47a4e2961fb8721bcfc54feae6455f2f64e7054f9bc67e875f0e77f4c58d" +dependencies = [ + "rust_decimal", + "schemars 1.1.0", + "serde", + "utf8-width", +] + +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "bytemuck" version = "1.24.0" @@ -1210,6 +1313,7 @@ dependencies = [ "hyper-util", "lazy_static", "libc", + "log", "lzma-rs", "msi-extract", "objc2 0.6.3", @@ -1225,6 +1329,7 @@ dependencies = [ "tauri-plugin-deep-link", "tauri-plugin-dialog", "tauri-plugin-fs", + "tauri-plugin-log", "tauri-plugin-macos-permissions", "tauri-plugin-opener", "tauri-plugin-shell", @@ -1340,6 +1445,16 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -1403,6 +1518,15 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "fern" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" +dependencies = [ + "log", +] + [[package]] name = "field-offset" version = "0.3.6" @@ -1499,6 +1623,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futf" version = "0.1.5" @@ -1945,6 +2075,9 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] [[package]] name = "hashbrown" @@ -2584,6 +2717,9 @@ name = "log" version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +dependencies = [ + "value-bag", +] [[package]] name = "lzma-rs" @@ -2889,6 +3025,15 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "objc-sys" version = "0.3.5" @@ -3679,6 +3824,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "quick-xml" version = "0.37.5" @@ -3712,6 +3877,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.7.3" @@ -3897,6 +4068,15 @@ version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] + [[package]] name = "reqwest" version = "0.12.24" @@ -3979,6 +4159,35 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rkyv" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "rust-ini" version = "0.21.3" @@ -3989,6 +4198,22 @@ dependencies = [ "ordered-multimap", ] +[[package]] +name = "rust_decimal" +version = "1.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35affe401787a9bd846712274d97654355d21b2a2c092a3139aabe31e9022282" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand 0.8.5", + "rkyv", + "serde", + "serde_json", +] + [[package]] name = "rustc_version" version = "0.4.1" @@ -4137,6 +4362,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "security-framework" version = "2.11.1" @@ -4444,6 +4675,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" version = "0.3.11" @@ -4727,6 +4964,12 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tar" version = "0.4.44" @@ -4936,6 +5179,28 @@ dependencies = [ "url", ] +[[package]] +name = "tauri-plugin-log" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5709c792b8630290b5d9811a1f8fe983dd925fc87c7fc7f4923616458cd00b6" +dependencies = [ + "android_logger", + "byte-unit", + "fern", + "log", + "objc2 0.6.3", + "objc2-foundation 0.3.2", + "serde", + "serde_json", + "serde_repr", + "swift-rs", + "tauri", + "tauri-plugin", + "thiserror 2.0.17", + "time", +] + [[package]] name = "tauri-plugin-macos-permissions" version = "2.3.0" @@ -5183,7 +5448,9 @@ checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", "itoa", + "libc", "num-conv", + "num_threads", "powerfmt", "serde", "time-core", @@ -5225,6 +5492,21 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.48.0" @@ -5633,6 +5915,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -5657,6 +5945,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "value-bag" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" + [[package]] name = "vcpkg" version = "0.2.15" @@ -6560,6 +6854,15 @@ dependencies = [ "x11-dl", ] +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "x11" version = "2.21.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 8b61f2b..a36f2a6 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -33,7 +33,8 @@ tauri-plugin-shell = "2" tauri-plugin-deep-link = "2" tauri-plugin-dialog = "2" tauri-plugin-macos-permissions = "2" - +tauri-plugin-log = "2" +log = "0.4" directories = "6" reqwest = { version = "0.12", features = ["json", "stream", "socks"] } diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 2580b72..35934c4 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -29,6 +29,7 @@ "macos-permissions:allow-request-microphone-permission", "macos-permissions:allow-request-camera-permission", "macos-permissions:allow-check-microphone-permission", - "macos-permissions:allow-check-camera-permission" + "macos-permissions:allow-check-camera-permission", + "log:default" ] } diff --git a/src-tauri/src/api_client.rs b/src-tauri/src/api_client.rs index 1ef2d44..263ef31 100644 --- a/src-tauri/src/api_client.rs +++ b/src-tauri/src/api_client.rs @@ -407,8 +407,8 @@ impl ApiClient { let text = response.text().await?; let mut page_releases: Vec = serde_json::from_str(&text).map_err(|e| { - eprintln!("Failed to parse GitHub API response (page {page}): {e}"); - eprintln!( + log::error!("Failed to parse GitHub API response (page {page}): {e}"); + log::error!( "Response text (first 500 chars): {}", if text.len() > 500 { &text[..500] @@ -487,13 +487,13 @@ impl ApiClient { let content = fs::read_to_string(&cache_file).ok()?; if let Ok(cached) = serde_json::from_str::(&content) { // Always return cached releases regardless of age - they're always valid - println!("Using cached versions for {browser}"); + log::info!("Using cached versions for {browser}"); return Some(cached.releases); } // Backward compatibility: legacy caches stored just an array of version strings if let Ok(legacy_versions) = serde_json::from_str::>(&content) { - println!("Using legacy cached versions for {browser}; upgrading in-memory"); + log::info!("Using legacy cached versions for {browser}; upgrading in-memory"); let releases: Vec = legacy_versions .into_iter() .map(|version| BrowserRelease { @@ -548,7 +548,7 @@ impl ApiClient { let content = serde_json::to_string_pretty(&cached_data)?; fs::write(&cache_file, content)?; - println!("Cached {} versions for {}", releases.len(), browser); + log::info!("Cached {} versions for {}", releases.len(), browser); Ok(()) } @@ -564,7 +564,7 @@ impl ApiClient { let cached_data: CachedGithubData = serde_json::from_str(&content).ok()?; // Always use cached GitHub releases - cache never expires, only gets updated with new versions - println!("Using cached GitHub releases for {browser}"); + log::info!("Using cached GitHub releases for {browser}"); Some(cached_data.releases) } @@ -588,7 +588,7 @@ impl ApiClient { let content = serde_json::to_string_pretty(&cached_data)?; fs::write(&cache_file, content)?; - println!("Cached {} GitHub releases for {}", releases.len(), browser); + log::info!("Cached {} GitHub releases for {}", releases.len(), browser); Ok(()) } @@ -603,7 +603,7 @@ impl ApiClient { } } - println!("Fetching Firefox releases from Mozilla API..."); + log::info!("Fetching Firefox releases from Mozilla API..."); let url = format!("{}/firefox.json", self.firefox_api_base); let response = self @@ -648,7 +648,7 @@ impl ApiClient { // Cache the results (unless bypassing cache) if !no_caching { if let Err(e) = self.save_cached_versions("firefox", &releases) { - eprintln!("Failed to cache Firefox versions: {e}"); + log::error!("Failed to cache Firefox versions: {e}"); } } @@ -666,7 +666,7 @@ impl ApiClient { } } - println!("Fetching Firefox Developer Edition releases from Mozilla API..."); + log::info!("Fetching Firefox Developer Edition releases from Mozilla API..."); let url = format!("{}/devedition.json", self.firefox_dev_api_base); let response = self @@ -682,7 +682,7 @@ impl ApiClient { response.status(), url ); - eprintln!("{error_msg}"); + log::error!("{error_msg}"); return Err(error_msg.into()); } @@ -717,7 +717,7 @@ impl ApiClient { // Cache the results (unless bypassing cache) if !no_caching { if let Err(e) = self.save_cached_versions("firefox-developer", &releases) { - eprintln!("Failed to cache Firefox Developer versions: {e}"); + log::error!("Failed to cache Firefox Developer versions: {e}"); } } @@ -735,7 +735,7 @@ impl ApiClient { } } - println!("Fetching Mullvad releases from GitHub API"); + log::info!("Fetching Mullvad releases from GitHub API"); let base_url = format!( "{}/repos/mullvad/mullvad-browser/releases", self.github_api_base @@ -756,7 +756,7 @@ impl ApiClient { // Cache the results (unless bypassing cache) if !no_caching { if let Err(e) = self.save_cached_github_releases("mullvad", &releases) { - eprintln!("Failed to cache Mullvad releases: {e}"); + log::error!("Failed to cache Mullvad releases: {e}"); } } @@ -774,7 +774,7 @@ impl ApiClient { } } - println!("Fetching Zen releases from GitHub API"); + log::info!("Fetching Zen releases from GitHub API"); let base_url = format!( "{}/repos/zen-browser/desktop/releases", self.github_api_base @@ -792,7 +792,7 @@ impl ApiClient { if release.tag_name.to_lowercase() == "twilight" { if let Ok(has_update) = self.check_twilight_update(release).await { if has_update { - println!( + log::info!( "Detected update for Zen twilight release: {}", release.tag_name ); @@ -807,7 +807,7 @@ impl ApiClient { // Cache the results (unless bypassing cache) if !no_caching { if let Err(e) = self.save_cached_github_releases("zen", &releases) { - eprintln!("Failed to cache Zen releases: {e}"); + log::error!("Failed to cache Zen releases: {e}"); } } @@ -825,7 +825,7 @@ impl ApiClient { } } - println!("Fetching Brave releases from GitHub API"); + log::info!("Fetching Brave releases from GitHub API"); let base_url = format!( "{}/repos/brave/brave-browser/releases", self.github_api_base @@ -843,7 +843,7 @@ impl ApiClient { let has_compatible_asset = Self::has_compatible_brave_asset(&release.assets, &os); if has_compatible_asset { - println!("release.name: {:?}", release.name); + log::info!("release.name: {:?}", release.name); // Use the centralized nightly detection function release.is_nightly = is_browser_version_nightly("brave", &release.tag_name, Some(&release.name)); @@ -858,7 +858,7 @@ impl ApiClient { sort_github_releases(&mut filtered_releases); if let Err(e) = self.save_cached_github_releases("brave", &filtered_releases) { - eprintln!("Failed to cache Brave releases: {e}"); + log::error!("Failed to cache Brave releases: {e}"); } Ok(filtered_releases) @@ -978,7 +978,7 @@ impl ApiClient { } } - println!("Fetching Chromium releases..."); + log::info!("Fetching Chromium releases..."); // Get the latest version first let latest_version = self.fetch_chromium_latest_version().await?; @@ -1006,7 +1006,7 @@ impl ApiClient { // Cache the results (unless bypassing cache) if !no_caching { if let Err(e) = self.save_cached_versions("chromium", &releases) { - eprintln!("Failed to cache Chromium versions: {e}"); + log::error!("Failed to cache Chromium versions: {e}"); } } @@ -1020,7 +1020,7 @@ impl ApiClient { // Check cache first (unless bypassing) if !no_caching { if let Some(cached_releases) = self.load_cached_github_releases("camoufox") { - println!( + log::info!( "Using cached Camoufox releases, count: {}", cached_releases.len() ); @@ -1028,18 +1028,18 @@ impl ApiClient { } } - println!("Fetching Camoufox releases from GitHub API"); + log::info!("Fetching Camoufox releases from GitHub API"); let base_url = format!("{}/repos/daijro/camoufox/releases", self.github_api_base); let releases: Vec = self.fetch_github_releases_multiple_pages(&base_url).await?; - println!( + log::info!( "Fetched {} total Camoufox releases from GitHub", releases.len() ); // Get platform info to filter appropriate releases let (os, arch) = Self::get_platform_info(); - println!("Filtering for platform: {os}/{arch}"); + log::info!("Filtering for platform: {os}/{arch}"); // Filter releases that have assets compatible with the current platform let mut compatible_releases: Vec = releases @@ -1048,11 +1048,14 @@ impl ApiClient { .filter_map(|(i, release)| { let has_compatible = self.has_compatible_camoufox_asset(&release.assets, &os, &arch); if !has_compatible { - println!( + log::info!( "Release {} ({}) has no compatible assets for {}/{}", - i, release.tag_name, os, arch + i, + release.tag_name, + os, + arch ); - println!( + log::info!( " Available assets: {:?}", release.assets.iter().map(|a| &a.name).collect::>() ); @@ -1065,13 +1068,13 @@ impl ApiClient { }) .collect(); - println!( + log::info!( "After platform filtering: {} compatible releases", compatible_releases.len() ); // Sort by version (latest first) with debugging - println!( + log::info!( "Before sorting: {:?}", compatible_releases .iter() @@ -1080,7 +1083,7 @@ impl ApiClient { .collect::>() ); sort_github_releases(&mut compatible_releases); - println!( + log::info!( "After sorting: {:?}", compatible_releases .iter() @@ -1092,9 +1095,9 @@ impl ApiClient { // Cache the results (unless bypassing cache) if !no_caching { if let Err(e) = self.save_cached_github_releases("camoufox", &compatible_releases) { - eprintln!("Failed to cache Camoufox releases: {e}"); + log::error!("Failed to cache Camoufox releases: {e}"); } else { - println!("Cached {} Camoufox releases", compatible_releases.len()); + log::info!("Cached {} Camoufox releases", compatible_releases.len()); } } @@ -1112,7 +1115,7 @@ impl ApiClient { } } - println!("Fetching TOR releases from archive..."); + log::info!("Fetching TOR releases from archive..."); let url = format!("{}/", self.tor_archive_base); let html = self .client @@ -1177,7 +1180,7 @@ impl ApiClient { // Cache the results (unless bypassing cache) if !no_caching { if let Err(e) = self.save_cached_versions("tor-browser", &releases) { - eprintln!("Failed to cache TOR versions: {e}"); + log::error!("Failed to cache TOR versions: {e}"); } } @@ -1248,9 +1251,10 @@ impl ApiClient { // File size changed, update cache and return true let content = serde_json::to_string_pretty(¤t_info)?; fs::write(&twilight_cache_file, content)?; - println!( + log::info!( "Zen twilight release updated: file size changed from {} to {}", - cached_info.file_size, current_info.file_size + cached_info.file_size, + current_info.file_size ); return Ok(true); } @@ -1268,10 +1272,10 @@ impl ApiClient { let path = entry.path(); if path.is_file() { fs::remove_file(&path)?; - println!("Removed cache file: {path:?}"); + log::info!("Removed cache file: {path:?}"); } } - println!("All version cache cleared successfully"); + log::info!("All version cache cleared successfully"); } Ok(()) @@ -1474,7 +1478,7 @@ mod tests { let result = client.fetch_firefox_releases_with_caching(true).await; if let Err(e) = &result { - println!("Firefox API test error: {e}"); + log::info!("Firefox API test error: {e}"); } assert!(result.is_ok()); let releases = result.unwrap(); @@ -1516,7 +1520,7 @@ mod tests { .await; if let Err(e) = &result { - println!("Firefox Developer API test error: {e}"); + log::info!("Firefox Developer API test error: {e}"); } assert!(result.is_ok()); let releases = result.unwrap(); @@ -1651,7 +1655,7 @@ mod tests { let result = client.fetch_brave_releases_with_caching(true).await; if let Err(e) = &result { - println!("Brave API test error: {e}"); + log::info!("Brave API test error: {e}"); } assert!(result.is_ok()); let releases = result.unwrap(); @@ -1992,8 +1996,8 @@ mod tests { let v22 = VersionComponent::parse("135.0.5beta22"); let v24 = VersionComponent::parse("135.0.5beta24"); - println!("v22: {v22:?}"); - println!("v24: {v24:?}"); + log::info!("v22: {v22:?}"); + log::info!("v24: {v24:?}"); // v24 should be greater than v22 assert!( @@ -2016,7 +2020,7 @@ mod tests { sort_versions(&mut versions); - println!("Sorted versions: {versions:?}"); + log::info!("Sorted versions: {versions:?}"); // Should be sorted from newest to oldest assert_eq!(versions[0], "135.0.5beta24"); @@ -2031,8 +2035,8 @@ mod tests { let v22 = VersionComponent::parse("135.0beta22"); let v24 = VersionComponent::parse("135.0.1beta24"); - println!("User reported v22: {v22:?}"); - println!("User reported v24: {v24:?}"); + log::info!("User reported v22: {v22:?}"); + log::info!("User reported v24: {v24:?}"); // 135.0.1beta24 should be greater than 135.0beta22 (newer patch version) assert!( @@ -2045,7 +2049,7 @@ mod tests { sort_versions(&mut versions); - println!("User reported sorted versions: {versions:?}"); + log::info!("User reported sorted versions: {versions:?}"); // Should be sorted from newest to oldest assert_eq!( diff --git a/src-tauri/src/app_auto_updater.rs b/src-tauri/src/app_auto_updater.rs index 30289d4..0f70d1d 100644 --- a/src-tauri/src/app_auto_updater.rs +++ b/src-tauri/src/app_auto_updater.rs @@ -166,13 +166,13 @@ impl AppAutoUpdater { let current_version = Self::get_current_version(); let is_nightly = Self::is_nightly_build(); - println!("=== App Update Check ==="); - println!("Current version: {current_version}"); - println!("Is nightly build: {is_nightly}"); - println!("STABLE_RELEASE env: {:?}", option_env!("STABLE_RELEASE")); + log::info!("=== App Update Check ==="); + log::info!("Current version: {current_version}"); + log::info!("Is nightly build: {is_nightly}"); + log::info!("STABLE_RELEASE env: {:?}", option_env!("STABLE_RELEASE")); let releases = self.fetch_app_releases().await?; - println!("Fetched {} releases from GitHub", releases.len()); + log::info!("Fetched {} releases from GitHub", releases.len()); // Filter releases based on build type let filtered_releases: Vec<&AppRelease> = if is_nightly { @@ -181,7 +181,7 @@ impl AppAutoUpdater { .iter() .filter(|release| release.tag_name.starts_with("nightly-")) .collect(); - println!("Found {} nightly releases", nightly_releases.len()); + log::info!("Found {} nightly releases", nightly_releases.len()); nightly_releases } else { // For stable builds, look for stable releases (semver format) @@ -189,25 +189,26 @@ impl AppAutoUpdater { .iter() .filter(|release| release.tag_name.starts_with('v')) .collect(); - println!("Found {} stable releases", stable_releases.len()); + log::info!("Found {} stable releases", stable_releases.len()); stable_releases }; if filtered_releases.is_empty() { - println!("No releases found for build type (nightly: {is_nightly})"); + log::info!("No releases found for build type (nightly: {is_nightly})"); return Ok(None); } // Get the latest release let latest_release = filtered_releases[0]; - println!( + log::info!( "Latest release: {} ({})", - latest_release.tag_name, latest_release.name + latest_release.tag_name, + latest_release.name ); // Check if we need to update if self.should_update(¤t_version, &latest_release.tag_name, is_nightly) { - println!("Update available!"); + log::info!("Update available!"); // Find the appropriate asset for current platform if let Some(download_url) = self.get_download_url_for_platform(&latest_release.assets) { @@ -220,16 +221,17 @@ impl AppAutoUpdater { published_at: latest_release.published_at.clone(), }; - println!( + log::info!( "Update info prepared: {} -> {}", - update_info.current_version, update_info.new_version + update_info.current_version, + update_info.new_version ); return Ok(Some(update_info)); } else { - println!("No suitable download asset found for current platform"); + log::info!("No suitable download asset found for current platform"); } } else { - println!("No update needed"); + log::info!("No update needed"); } Ok(None) @@ -261,7 +263,7 @@ impl AppAutoUpdater { return false; } - println!( + log::info!( "Comparing versions: current={current_version}, new={new_version}, is_nightly={is_nightly}" ); @@ -273,20 +275,20 @@ impl AppAutoUpdater { ) { // Different commit hashes mean we should update let should_update = new_hash != current_hash; - println!("Nightly comparison: current_hash={current_hash}, new_hash={new_hash}, should_update={should_update}"); + log::info!("Nightly comparison: current_hash={current_hash}, new_hash={new_hash}, should_update={should_update}"); return should_update; } // If current version doesn't have nightly prefix but we're in nightly mode, // this could be a dev build or stable build upgrading to nightly if !current_version.starts_with("nightly-") { - println!("Upgrading from non-nightly to nightly: {new_version}"); + log::info!("Upgrading from non-nightly to nightly: {new_version}"); return true; } } else { // For stable builds, use semantic versioning comparison let should_update = self.is_version_newer(new_version, current_version); - println!("Stable comparison: {new_version} > {current_version} = {should_update}"); + log::info!("Stable comparison: {new_version} > {current_version} = {should_update}"); return should_update; } @@ -354,7 +356,7 @@ impl AppAutoUpdater { }; let exe_path_str = exe_path.to_string_lossy(); - println!("Detecting installation method for: {exe_path_str}"); + log::info!("Detecting installation method for: {exe_path_str}"); // Check if installed via package manager by querying package databases if let Some(exe_name) = exe_path.file_name().and_then(|n| n.to_str()) { @@ -365,7 +367,7 @@ impl AppAutoUpdater { if output.status.success() { let stdout = String::from_utf8_lossy(&output.stdout); if !stdout.trim().is_empty() && !stdout.contains("no path found") { - println!("Found DEB package owning the executable"); + log::info!("Found DEB package owning the executable"); return LinuxInstallationMethod::Deb; } } @@ -376,7 +378,7 @@ impl AppAutoUpdater { if output.status.success() { let stdout = String::from_utf8_lossy(&output.stdout); if !stdout.trim().is_empty() && !stdout.contains("not owned") { - println!("Found RPM package owning the executable"); + log::info!("Found RPM package owning the executable"); return LinuxInstallationMethod::Rpm; } } @@ -391,7 +393,7 @@ impl AppAutoUpdater { if output.status.success() { let stdout = String::from_utf8_lossy(&output.stdout); if !stdout.trim().is_empty() && stdout.contains(exe_name) { - println!("Found RPM package via {rpm_cmd}"); + log::info!("Found RPM package via {rpm_cmd}"); return LinuxInstallationMethod::Rpm; } } @@ -402,7 +404,7 @@ impl AppAutoUpdater { // Check installation location to infer method if exe_path_str.starts_with("/usr/bin/") || exe_path_str.starts_with("/usr/local/bin/") { // Likely installed via package manager or system-wide installation - println!("Executable in system directory, assuming package installation"); + log::info!("Executable in system directory, assuming package installation"); // Try to determine which package system is available if Command::new("dpkg").arg("--version").output().is_ok() { @@ -414,11 +416,11 @@ impl AppAutoUpdater { return LinuxInstallationMethod::Manual; } else if exe_path_str.contains("/.local/") || exe_path_str.starts_with("/home/") { // User-local installation - println!("Executable in user directory, assuming manual installation"); + log::info!("Executable in user directory, assuming manual installation"); return LinuxInstallationMethod::Manual; } - println!("Could not determine installation method"); + log::info!("Could not determine installation method"); LinuxInstallationMethod::Unknown } @@ -432,13 +434,13 @@ impl AppAutoUpdater { "unknown" }; - println!("Looking for platform-specific asset for arch: {arch}"); + log::info!("Looking for platform-specific asset for arch: {arch}"); #[cfg(target_os = "linux")] { // If we're running from an AppImage, disable auto-updates for safety if self.is_running_from_appimage() { - println!("Running from AppImage - auto-updates disabled for safety"); + log::info!("Running from AppImage - auto-updates disabled for safety"); return None; } } @@ -460,7 +462,7 @@ impl AppAutoUpdater { #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))] { - println!("Unsupported platform for auto-update"); + log::info!("Unsupported platform for auto-update"); None } } @@ -475,7 +477,7 @@ impl AppAutoUpdater { || asset.name.contains(&format!("_{arch}_")) || asset.name.contains(&format!("-{arch}-"))) { - println!("Found exact architecture match: {}", asset.name); + log::info!("Found exact architecture match: {}", asset.name); return Some(asset.browser_download_url.clone()); } } @@ -486,7 +488,7 @@ impl AppAutoUpdater { if asset.name.contains(".dmg") && (asset.name.contains("x86_64") || asset.name.contains("x86-64")) { - println!("Found x86_64 variant: {}", asset.name); + log::info!("Found x86_64 variant: {}", asset.name); return Some(asset.browser_download_url.clone()); } } @@ -498,7 +500,7 @@ impl AppAutoUpdater { if asset.name.contains(".dmg") && (asset.name.contains("arm64") || asset.name.contains("aarch64")) { - println!("Found arm64 variant: {}", asset.name); + log::info!("Found arm64 variant: {}", asset.name); return Some(asset.browser_download_url.clone()); } } @@ -511,7 +513,7 @@ impl AppAutoUpdater { || asset.name.to_lowercase().contains("darwin") || !asset.name.contains(".app.tar.gz")) { - println!("Found fallback DMG: {}", asset.name); + log::info!("Found fallback DMG: {}", asset.name); return Some(asset.browser_download_url.clone()); } } @@ -533,7 +535,7 @@ impl AppAutoUpdater { || asset.name.contains(&format!("_{arch}_")) || asset.name.contains(&format!("-{arch}-"))) { - println!("Found Windows {ext} with exact arch match: {}", asset.name); + log::info!("Found Windows {ext} with exact arch match: {}", asset.name); return Some(asset.browser_download_url.clone()); } } @@ -544,7 +546,7 @@ impl AppAutoUpdater { if asset.name.to_lowercase().ends_with(&format!(".{ext}")) && (asset.name.contains("x86_64") || asset.name.contains("x86-64")) { - println!("Found Windows {ext} with x86_64 variant: {}", asset.name); + log::info!("Found Windows {ext} with x86_64 variant: {}", asset.name); return Some(asset.browser_download_url.clone()); } } @@ -557,7 +559,7 @@ impl AppAutoUpdater { || asset.name.to_lowercase().contains("win32") || asset.name.to_lowercase().contains("win64")) { - println!("Found Windows {ext} fallback: {}", asset.name); + log::info!("Found Windows {ext} fallback: {}", asset.name); return Some(asset.browser_download_url.clone()); } } @@ -570,7 +572,7 @@ impl AppAutoUpdater { fn get_linux_download_url(&self, assets: &[AppReleaseAsset], arch: &str) -> Option { // Detect installation method to prioritize appropriate formats let installation_method = self.detect_linux_installation_method(); - println!("Detected Linux installation method: {installation_method:?}"); + log::info!("Detected Linux installation method: {installation_method:?}"); // Priority order based on installation method let extensions = match installation_method { @@ -578,7 +580,7 @@ impl AppAutoUpdater { LinuxInstallationMethod::Rpm => vec!["rpm", "tar.gz"], LinuxInstallationMethod::AppImage => { // AppImages should not auto-update for safety - println!("AppImage installation detected - auto-updates disabled"); + log::info!("AppImage installation detected - auto-updates disabled"); return None; } LinuxInstallationMethod::Manual | LinuxInstallationMethod::Unknown => { @@ -596,7 +598,7 @@ impl AppAutoUpdater { || asset.name.contains(&format!("_{arch}_")) || asset.name.contains(&format!("-{arch}-"))) { - println!("Found Linux {ext} with exact arch match: {}", asset.name); + log::info!("Found Linux {ext} with exact arch match: {}", asset.name); return Some(asset.browser_download_url.clone()); } } @@ -610,7 +612,7 @@ impl AppAutoUpdater { || asset.name.contains("x86-64") || asset.name.contains("amd64")) { - println!("Found Linux {ext} with x86_64 variant: {}", asset.name); + log::info!("Found Linux {ext} with x86_64 variant: {}", asset.name); return Some(asset.browser_download_url.clone()); } } @@ -623,7 +625,7 @@ impl AppAutoUpdater { if asset_name_lower.ends_with(&format!(".{ext}")) && (asset.name.contains("arm64") || asset.name.contains("aarch64")) { - println!("Found Linux {ext} with arm64 variant: {}", asset.name); + log::info!("Found Linux {ext} with arm64 variant: {}", asset.name); return Some(asset.browser_download_url.clone()); } } @@ -637,7 +639,7 @@ impl AppAutoUpdater { || asset_name_lower.contains("ubuntu") || asset_name_lower.contains("debian")) { - println!("Found Linux {ext} fallback: {}", asset.name); + log::info!("Found Linux {ext} fallback: {}", asset.name); return Some(asset.browser_download_url.clone()); } } @@ -967,12 +969,12 @@ impl AppAutoUpdater { .and_then(|ext| ext.to_str()) .unwrap_or(""); - println!("Installing Windows update with extension: {extension}"); + log::info!("Installing Windows update with extension: {extension}"); match extension { "msi" => { // Install MSI silently with enhanced error handling - println!("Running MSI installer: {}", installer_path.display()); + log::info!("Running MSI installer: {}", installer_path.display()); let mut cmd = Command::new("msiexec"); cmd.args([ @@ -995,10 +997,10 @@ impl AppAutoUpdater { let log_path = format!("{}.log", installer_path.to_str().unwrap()); let log_content = fs::read_to_string(&log_path).unwrap_or_default(); - println!("MSI installation failed with exit code: {exit_code}"); - println!("Error output: {error_msg}"); + log::info!("MSI installation failed with exit code: {exit_code}"); + log::info!("Error output: {error_msg}"); if !log_content.is_empty() { - println!( + log::info!( "Log file content (last 500 chars): {}", &log_content .chars() @@ -1016,11 +1018,11 @@ impl AppAutoUpdater { ); } - println!("MSI installation completed successfully"); + log::info!("MSI installation completed successfully"); } "exe" => { // Run exe installer silently with multiple fallback options - println!("Running EXE installer: {}", installer_path.display()); + log::info!("Running EXE installer: {}", installer_path.display()); // Try NSIS silent flag first (most common for Tauri) let mut success = false; @@ -1035,12 +1037,12 @@ impl AppAutoUpdater { ]; for args in nsis_args { - println!("Trying installer with args: {:?}", args); + log::info!("Trying installer with args: {:?}", args); let output = Command::new(installer_path).args(&args).output(); match output { Ok(output) if output.status.success() => { - println!( + log::info!( "EXE installation completed successfully with args: {:?}", args ); @@ -1054,13 +1056,14 @@ impl AppAutoUpdater { output.status.code().unwrap_or(-1), error_msg ); - println!("Installer failed with args {:?}: {}", args, last_error); + log::info!("Installer failed with args {:?}: {}", args, last_error); } Err(e) => { last_error = format!("Failed to execute installer: {e}"); - println!( + log::info!( "Failed to execute installer with args {:?}: {}", - args, last_error + args, + last_error ); } } @@ -1077,7 +1080,7 @@ impl AppAutoUpdater { } "zip" => { // Handle ZIP files by extracting and replacing the current executable - println!("Handling ZIP update: {}", installer_path.display()); + log::info!("Handling ZIP update: {}", installer_path.display()); let temp_extract_dir = installer_path.parent().unwrap().join("extracted"); fs::create_dir_all(&temp_extract_dir)?; @@ -1124,7 +1127,7 @@ impl AppAutoUpdater { // Clean up let _ = fs::remove_dir_all(&temp_extract_dir); - println!("ZIP update completed successfully"); + log::info!("ZIP update completed successfully"); } _ => { return Err(format!("Unsupported installer format: {extension}").into()); @@ -1141,7 +1144,7 @@ impl AppAutoUpdater { .and_then(|name| name.to_str()) .unwrap_or(""); - println!("Installing Linux update: {}", installer_path.display()); + log::info!("Installing Linux update: {}", installer_path.display()); // Handle compound extensions like .tar.gz if file_name.ends_with(".tar.gz") { @@ -1173,7 +1176,7 @@ impl AppAutoUpdater { &self, deb_path: &Path, ) -> Result<(), Box> { - println!("Installing DEB package: {}", deb_path.display()); + log::info!("Installing DEB package: {}", deb_path.display()); // Try different package managers in order of preference let package_managers = [ @@ -1186,23 +1189,23 @@ impl AppAutoUpdater { for (manager, args) in &package_managers { // Check if package manager exists if Command::new("which").arg(manager).output().is_ok() { - println!("Trying to install with {manager}"); + log::info!("Trying to install with {manager}"); let output = Command::new("pkexec").arg(manager).args(args).output(); match output { Ok(output) if output.status.success() => { - println!("DEB installation completed successfully with {manager}"); + log::info!("DEB installation completed successfully with {manager}"); return Ok(()); } Ok(output) => { let error_msg = String::from_utf8_lossy(&output.stderr); last_error = format!("{manager} failed: {error_msg}"); - println!("Installation failed with {manager}: {error_msg}"); + log::info!("Installation failed with {manager}: {error_msg}"); } Err(e) => { last_error = format!("Failed to execute {manager}: {e}"); - println!("Failed to execute {manager}: {e}"); + log::info!("Failed to execute {manager}: {e}"); } } } @@ -1217,7 +1220,7 @@ impl AppAutoUpdater { &self, rpm_path: &Path, ) -> Result<(), Box> { - println!("Installing RPM package: {}", rpm_path.display()); + log::info!("Installing RPM package: {}", rpm_path.display()); // Try different package managers in order of preference let package_managers = [ @@ -1232,23 +1235,23 @@ impl AppAutoUpdater { for (manager, args) in &package_managers { // Check if package manager exists if Command::new("which").arg(manager).output().is_ok() { - println!("Trying to install with {manager}"); + log::info!("Trying to install with {manager}"); let output = Command::new("pkexec").arg(manager).args(args).output(); match output { Ok(output) if output.status.success() => { - println!("RPM installation completed successfully with {manager}"); + log::info!("RPM installation completed successfully with {manager}"); return Ok(()); } Ok(output) => { let error_msg = String::from_utf8_lossy(&output.stderr); last_error = format!("{manager} failed: {error_msg}"); - println!("Installation failed with {manager}: {error_msg}"); + log::info!("Installation failed with {manager}: {error_msg}"); } Err(e) => { last_error = format!("Failed to execute {manager}: {e}"); - println!("Failed to execute {manager}: {e}"); + log::info!("Failed to execute {manager}: {e}"); } } } @@ -1263,7 +1266,7 @@ impl AppAutoUpdater { &self, appimage_path: &Path, ) -> Result<(), Box> { - println!("Installing AppImage: {}", appimage_path.display()); + log::info!("Installing AppImage: {}", appimage_path.display()); // This function should not be called for AppImages since we disable auto-updates for them // But if it somehow gets called, we'll handle it safely @@ -1297,7 +1300,7 @@ impl AppAutoUpdater { // Replace the AppImage fs::copy(appimage_path, ¤t_appimage)?; - println!("AppImage replacement completed successfully"); + log::info!("AppImage replacement completed successfully"); Ok(()) } @@ -1307,7 +1310,7 @@ impl AppAutoUpdater { &self, tarball_path: &Path, ) -> Result<(), Box> { - println!("Installing tarball: {}", tarball_path.display()); + log::info!("Installing tarball: {}", tarball_path.display()); let current_exe = self.get_current_app_path()?; let temp_extract_dir = tarball_path.parent().unwrap().join("extracted"); @@ -1369,7 +1372,7 @@ impl AppAutoUpdater { // Clean up let _ = fs::remove_dir_all(&temp_extract_dir); - println!("Tarball installation completed successfully"); + log::info!("Tarball installation completed successfully"); Ok(()) } @@ -1606,7 +1609,7 @@ pub async fn download_and_install_app_update( #[tauri::command] pub async fn check_for_app_updates_manual() -> Result, String> { - println!("Manual app update check triggered"); + log::info!("Manual app update check triggered"); let updater = AppAutoUpdater::instance(); updater .check_for_updates() @@ -1622,7 +1625,7 @@ mod tests { fn test_is_nightly_build() { // This will depend on whether STABLE_RELEASE is set during test compilation let is_nightly = AppAutoUpdater::is_nightly_build(); - println!("Is nightly build: {is_nightly}"); + log::info!("Is nightly build: {is_nightly}"); // The result should be true for test builds since STABLE_RELEASE is not set // unless the test is run in a stable release environment diff --git a/src-tauri/src/auto_updater.rs b/src-tauri/src/auto_updater.rs index 456e96f..10db798 100644 --- a/src-tauri/src/auto_updater.rs +++ b/src-tauri/src/auto_updater.rs @@ -109,13 +109,13 @@ impl AutoUpdater { let new_version = &update.new_version.parse::().unwrap(); let result = new_version - current_version; - println!( + log::info!( "Current version: {current_version}, New version: {new_version}, Result: {result}" ); if result > 400 { notifications.push(update); } else { - println!( + log::info!( "Skipping chromium update notification: only {result} new versions (need 400+)" ); } @@ -130,22 +130,23 @@ impl AutoUpdater { } pub async fn check_for_updates_with_progress(&self, app_handle: &tauri::AppHandle) { - println!("Starting auto-update check with progress..."); + log::info!("Starting auto-update check with progress..."); // Check for browser updates and trigger auto-downloads match self.check_for_updates().await { Ok(update_notifications) => { if !update_notifications.is_empty() { - println!( + log::info!( "Found {} browser updates to auto-download", update_notifications.len() ); // Trigger automatic downloads for each update for notification in update_notifications { - println!( + log::info!( "Auto-downloading {} version {}", - notification.browser, notification.new_version + notification.browser, + notification.new_version ); // Clone app_handle for the async task @@ -164,7 +165,7 @@ impl AutoUpdater { new_version.clone(), ) { true => { - println!("Browser {browser} {new_version} already downloaded, proceeding to auto-update profiles"); + log::info!("Browser {browser} {new_version} already downloaded, proceeding to auto-update profiles"); // Browser already exists, go straight to profile update match AutoUpdater::instance() @@ -176,19 +177,19 @@ impl AutoUpdater { .await { Ok(updated_profiles) => { - println!( + log::info!( "Auto-update completed for {} profiles: {:?}", updated_profiles.len(), updated_profiles ); } Err(e) => { - eprintln!("Failed to complete auto-update for {browser}: {e}"); + log::error!("Failed to complete auto-update for {browser}: {e}"); } } } false => { - println!("Downloading browser {browser} version {new_version}..."); + log::info!("Downloading browser {browser} version {new_version}..."); // Emit the auto-update event to trigger frontend handling let auto_update_event = serde_json::json!({ @@ -201,20 +202,20 @@ impl AutoUpdater { if let Err(e) = app_handle_clone.emit("browser-auto-update-available", &auto_update_event) { - eprintln!("Failed to emit auto-update event for {browser}: {e}"); + log::error!("Failed to emit auto-update event for {browser}: {e}"); } else { - println!("Emitted auto-update event for {browser}"); + log::info!("Emitted auto-update event for {browser}"); } } } }); } } else { - println!("No browser updates needed"); + log::info!("No browser updates needed"); } } Err(e) => { - eprintln!("Failed to check for browser updates: {e}"); + log::error!("Failed to check for browser updates: {e}"); } } } @@ -330,7 +331,7 @@ impl AutoUpdater { updated_profiles.push(profile.name); } Err(e) => { - eprintln!("Failed to update profile {}: {}", profile.name, e); + log::error!("Failed to update profile {}: {}", profile.name, e); } } } diff --git a/src-tauri/src/bin/proxy_server.rs b/src-tauri/src/bin/proxy_server.rs index f63efd1..54d7373 100644 --- a/src-tauri/src/bin/proxy_server.rs +++ b/src-tauri/src/bin/proxy_server.rs @@ -35,9 +35,9 @@ fn build_proxy_url( async fn main() { // Set up panic handler to log panics before process exits std::panic::set_hook(Box::new(|panic_info| { - eprintln!("PANIC in proxy worker: {:?}", panic_info); + log::error!("PANIC in proxy worker: {:?}", panic_info); if let Some(location) = panic_info.location() { - eprintln!( + log::error!( "Location: {}:{}:{}", location.file(), location.line(), @@ -45,7 +45,7 @@ async fn main() { ); } if let Some(s) = panic_info.payload().downcast_ref::<&str>() { - eprintln!("Message: {}", s); + log::error!("Message: {}", s); } })); @@ -142,6 +142,7 @@ async fn main() { match start_proxy_process(upstream_url, port).await { Ok(config) => { // Output the configuration as JSON for the Rust side to parse + // Use println! here because this needs to go to stdout for parsing println!( "{}", serde_json::json!({ @@ -162,6 +163,7 @@ async fn main() { if let Some(id) = stop_matches.get_one::("id") { match stop_proxy_process(id).await { Ok(success) => { + // Use println! here because this needs to go to stdout for parsing println!("{}", serde_json::json!({ "success": success })); process::exit(0); } @@ -187,12 +189,14 @@ async fn main() { let _ = stop_proxy_process(&config.id).await; } + // Use println! here because this needs to go to stdout for parsing println!("{}", serde_json::json!({ "success": true })); process::exit(0); } else { // Stop all proxies match stop_all_proxy_processes().await { Ok(_) => { + // Use println! here because this needs to go to stdout for parsing println!("{}", serde_json::json!({ "success": true })); process::exit(0); } @@ -204,10 +208,11 @@ async fn main() { } } else if proxy_matches.subcommand_matches("list").is_some() { let configs = donutbrowser::proxy_storage::list_proxy_configs(); + // Use println! here because this needs to go to stdout for parsing println!("{}", serde_json::to_string(&configs).unwrap()); process::exit(0); } else { - eprintln!("Invalid action. Use 'start', 'stop', or 'list'"); + log::error!("Invalid action. Use 'start', 'stop', or 'list'"); process::exit(1); } } else if let Some(worker_matches) = matches.subcommand_matches("proxy-worker") { @@ -219,39 +224,41 @@ async fn main() { .expect("action is required"); if action == "start" { - eprintln!("Proxy worker starting, looking for config id: {}", id); - eprintln!("Process PID: {}", std::process::id()); + log::error!("Proxy worker starting, looking for config id: {}", id); + log::error!("Process PID: {}", std::process::id()); let config = match get_proxy_config(id) { Some(config) => { - eprintln!( + log::error!( "Found config: id={}, port={:?}, upstream={}", - config.id, config.local_port, config.upstream_url + config.id, + config.local_port, + config.upstream_url ); config } None => { - eprintln!("Proxy configuration {} not found", id); + log::error!("Proxy configuration {} not found", id); process::exit(1); } }; // Run the proxy server - this should never return (infinite loop) - eprintln!("Starting proxy server for config id: {}", id); + log::error!("Starting proxy server for config id: {}", id); if let Err(e) = run_proxy_server(config).await { - eprintln!("Failed to run proxy server: {}", e); - eprintln!("Error details: {:?}", e); + log::error!("Failed to run proxy server: {}", e); + log::error!("Error details: {:?}", e); process::exit(1); } // This should never be reached - run_proxy_server has an infinite loop - eprintln!("ERROR: Proxy server returned unexpectedly (this should never happen)"); + log::error!("ERROR: Proxy server returned unexpectedly (this should never happen)"); process::exit(1); } else { - eprintln!("Invalid action for proxy-worker. Use 'start'"); + log::error!("Invalid action for proxy-worker. Use 'start'"); process::exit(1); } } else { - eprintln!("No command specified"); + log::error!("No command specified"); process::exit(1); } } diff --git a/src-tauri/src/browser.rs b/src-tauri/src/browser.rs index f75ba7d..8c00477 100644 --- a/src-tauri/src/browser.rs +++ b/src-tauri/src/browser.rs @@ -377,7 +377,7 @@ mod linux { pub fn prepare_executable(executable_path: &Path) -> Result<(), Box> { // On Linux, ensure the executable has proper permissions - println!("Setting execute permissions for: {:?}", executable_path); + log::info!("Setting execute permissions for: {:?}", executable_path); let metadata = std::fs::metadata(executable_path)?; let mut permissions = metadata.permissions(); @@ -388,7 +388,7 @@ mod linux { std::fs::set_permissions(executable_path, permissions)?; - println!( + log::info!( "Execute permissions set successfully for: {:?}", executable_path ); @@ -653,14 +653,14 @@ impl Browser for FirefoxBrowser { // Expected structure: binaries// let browser_dir = binaries_dir.join(self.browser_type.as_str()).join(version); - println!("Firefox browser checking version {version} in directory: {browser_dir:?}"); + log::info!("Firefox browser checking version {version} in directory: {browser_dir:?}"); if !browser_dir.exists() { - println!("Directory does not exist: {browser_dir:?}"); + log::info!("Directory does not exist: {browser_dir:?}"); return false; } - println!("Directory exists, checking for browser files..."); + log::info!("Directory exists, checking for browser files..."); #[cfg(target_os = "macos")] return macos::is_firefox_version_downloaded(&browser_dir); @@ -673,7 +673,7 @@ impl Browser for FirefoxBrowser { #[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))] { - println!("Unsupported platform for browser verification"); + log::info!("Unsupported platform for browser verification"); false } } @@ -768,14 +768,14 @@ impl Browser for ChromiumBrowser { // Expected structure: binaries// let browser_dir = binaries_dir.join(self.browser_type.as_str()).join(version); - println!("Chromium browser checking version {version} in directory: {browser_dir:?}"); + log::info!("Chromium browser checking version {version} in directory: {browser_dir:?}"); if !browser_dir.exists() { - println!("Directory does not exist: {browser_dir:?}"); + log::info!("Directory does not exist: {browser_dir:?}"); return false; } - println!("Directory exists, checking for browser files..."); + log::info!("Directory exists, checking for browser files..."); #[cfg(target_os = "macos")] return macos::is_chromium_version_downloaded(&browser_dir); @@ -788,7 +788,7 @@ impl Browser for ChromiumBrowser { #[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))] { - println!("Unsupported platform for browser verification"); + log::info!("Unsupported platform for browser verification"); false } } diff --git a/src-tauri/src/browser_runner.rs b/src-tauri/src/browser_runner.rs index 9f6dfce..6bdc7d0 100644 --- a/src-tauri/src/browser_runner.rs +++ b/src-tauri/src/browser_runner.rs @@ -125,7 +125,7 @@ impl BrowserRunner { if profile.browser == "camoufox" { // Get or create camoufox config let mut camoufox_config = profile.camoufox_config.clone().unwrap_or_else(|| { - println!( + log::info!( "No camoufox config found for profile {}, using default", profile.name ); @@ -138,7 +138,7 @@ impl BrowserRunner { .as_ref() .and_then(|id| PROXY_MANAGER.get_proxy_settings_by_id(id)); - println!( + log::info!( "Starting local proxy for Camoufox profile: {} (upstream: {})", profile.name, upstream_proxy @@ -159,7 +159,7 @@ impl BrowserRunner { .await .map_err(|e| { let error_msg = format!("Failed to start local proxy for Camoufox: {e}"); - eprintln!("{}", error_msg); + log::error!("{}", error_msg); error_msg })?; @@ -174,13 +174,14 @@ impl BrowserRunner { camoufox_config.geoip = Some(serde_json::Value::Bool(true)); } - println!( + log::info!( "Configured local proxy for Camoufox: {:?}, geoip: {:?}", - camoufox_config.proxy, camoufox_config.geoip + camoufox_config.proxy, + camoufox_config.geoip ); // Use the nodecar camoufox launcher - println!( + log::info!( "Launching Camoufox via nodecar for profile: {}", profile.name ); @@ -194,7 +195,7 @@ impl BrowserRunner { // For server-based Camoufox, we use the process_id let process_id = camoufox_result.processId.unwrap_or(0); - println!("Camoufox launched successfully with PID: {process_id}"); + log::info!("Camoufox launched successfully with PID: {process_id}"); // Update profile with the process info from camoufox result let mut updated_profile = profile.clone(); @@ -203,9 +204,9 @@ impl BrowserRunner { // Update the proxy manager with the correct PID if let Err(e) = PROXY_MANAGER.update_proxy_pid(0, process_id) { - println!("Warning: Failed to update proxy PID mapping: {e}"); + log::warn!("Warning: Failed to update proxy PID mapping: {e}"); } else { - println!("Updated proxy PID mapping from temp (0) to actual PID: {process_id}"); + log::info!("Updated proxy PID mapping from temp (0) to actual PID: {process_id}"); } // Save the updated profile @@ -214,19 +215,19 @@ impl BrowserRunner { let _ = crate::tag_manager::TAG_MANAGER.lock().map(|tm| { let _ = tm.rebuild_from_profiles(&self.profile_manager.list_profiles().unwrap_or_default()); }); - println!( + log::info!( "Updated profile with process info: {}", updated_profile.name ); - println!( + log::info!( "Emitting profile events for successful Camoufox launch: {}", updated_profile.name ); // Emit profile update event to frontend if let Err(e) = app_handle.emit("profile-updated", &updated_profile) { - println!("Warning: Failed to emit profile update event: {e}"); + log::warn!("Warning: Failed to emit profile update event: {e}"); } // Emit minimal running changed event to frontend with a small delay @@ -242,11 +243,12 @@ impl BrowserRunner { }; if let Err(e) = app_handle.emit("profile-running-changed", &payload) { - println!("Warning: Failed to emit profile running changed event: {e}"); + log::warn!("Warning: Failed to emit profile running changed event: {e}"); } else { - println!( + log::info!( "Successfully emitted profile-running-changed event for Camoufox {}: running={}", - updated_profile.name, payload.is_running + updated_profile.name, + payload.is_running ); } @@ -263,11 +265,11 @@ impl BrowserRunner { .get_browser_executable_path(profile) .expect("Failed to get executable path"); - println!("Executable path: {executable_path:?}"); + log::info!("Executable path: {executable_path:?}"); // Prepare the executable (set permissions, etc.) if let Err(e) = browser.prepare_executable(&executable_path) { - println!("Warning: Failed to prepare executable: {e}"); + log::warn!("Warning: Failed to prepare executable: {e}"); // Continue anyway, the error might not be critical } @@ -318,9 +320,11 @@ impl BrowserRunner { let launcher_pid = child.id(); - println!( + log::info!( "Launched browser with launcher PID: {} for profile: {} (ID: {})", - launcher_pid, profile.name, profile.id + launcher_pid, + profile.name, + profile.id ); // For TOR and Mullvad browsers, we need to find the actual browser process @@ -347,9 +351,11 @@ impl BrowserRunner { } if self.is_tor_or_mullvad_browser(process_name, process_cmd, &profile.browser) { - println!( + log::info!( "Found actual {} browser process: PID {} ({})", - profile.browser, pid_u32, process_name + profile.browser, + pid_u32, + process_name ); actual_pid = pid_u32; break; @@ -489,14 +495,15 @@ impl BrowserRunner { // which is already handled in the profile creation process } - println!( + log::info!( "Emitting profile events for successful launch: {} (ID: {})", - updated_profile.name, updated_profile.id + updated_profile.name, + updated_profile.id ); // Emit profile update event to frontend if let Err(e) = app_handle.emit("profile-updated", &updated_profile) { - println!("Warning: Failed to emit profile update event: {e}"); + log::warn!("Warning: Failed to emit profile update event: {e}"); } // Emit minimal running changed event to frontend with a small delay to ensure UI consistency @@ -511,11 +518,12 @@ impl BrowserRunner { }; if let Err(e) = app_handle.emit("profile-running-changed", &payload) { - println!("Warning: Failed to emit profile running changed event: {e}"); + log::warn!("Warning: Failed to emit profile running changed event: {e}"); } else { - println!( + log::info!( "Successfully emitted profile-running-changed event for {}: running={}", - updated_profile.name, payload.is_running + updated_profile.name, + payload.is_running ); } @@ -543,9 +551,10 @@ impl BrowserRunner { .await { Ok(Some(_camoufox_process)) => { - println!( + log::info!( "Opening URL in existing Camoufox process for profile: {} (ID: {})", - profile.name, profile.id + profile.name, + profile.id ); // For Camoufox, we need to launch a new instance with the URL since it doesn't support remote commands @@ -759,7 +768,7 @@ impl BrowserRunner { .await .map_err(|e| { let error_msg = format!("Failed to start local proxy: {e}"); - eprintln!("{}", error_msg); + log::error!("{}", error_msg); error_msg })?; @@ -819,9 +828,10 @@ impl BrowserRunner { url: Option, internal_proxy_settings: Option<&ProxySettings>, ) -> Result> { - println!( + log::info!( "launch_or_open_url called for profile: {} (ID: {})", - profile.name, profile.id + profile.name, + profile.id ); // Get the most up-to-date profile data @@ -834,9 +844,10 @@ impl BrowserRunner { .find(|p| p.id == profile.id) .unwrap_or_else(|| profile.clone()); - println!( + log::info!( "Checking browser status for profile: {} (ID: {})", - updated_profile.name, updated_profile.id + updated_profile.name, + updated_profile.id ); // Check if browser is already running @@ -855,24 +866,28 @@ impl BrowserRunner { .find(|p| p.id == profile.id) .unwrap_or_else(|| updated_profile.clone()); - println!( + log::info!( "Browser status check - Profile: {} (ID: {}), Running: {}, URL: {:?}, PID: {:?}", - final_profile.name, final_profile.id, is_running, url, final_profile.process_id + final_profile.name, + final_profile.id, + is_running, + url, + final_profile.process_id ); if is_running && url.is_some() { // Browser is running and we have a URL to open if let Some(url_ref) = url.as_ref() { - println!("Opening URL in existing browser: {url_ref}"); + log::info!("Opening URL in existing browser: {url_ref}"); // For TOR/Mullvad browsers, add extra verification if matches!( final_profile.browser.as_str(), "tor-browser" | "mullvad-browser" ) { - println!("TOR/Mullvad browser detected - ensuring we have correct PID"); + log::info!("TOR/Mullvad browser detected - ensuring we have correct PID"); if final_profile.process_id.is_none() { - println!( + log::info!( "ERROR: No PID found for running TOR/Mullvad browser - this should not happen" ); return Err("No PID found for running browser".into()); @@ -888,11 +903,11 @@ impl BrowserRunner { .await { Ok(()) => { - println!("Successfully opened URL in existing browser"); + log::info!("Successfully opened URL in existing browser"); Ok(final_profile) } Err(e) => { - println!("Failed to open URL in existing browser: {e}"); + log::info!("Failed to open URL in existing browser: {e}"); // For Mullvad and Tor browsers, don't fall back to new instance since they use -no-remote // and can't have multiple instances with the same profile @@ -901,7 +916,7 @@ impl BrowserRunner { Err(format!("Failed to open URL in existing {} browser. Cannot launch new instance due to profile conflict: {}", final_profile.browser, e).into()) } _ => { - println!("Falling back to new instance for browser: {}", final_profile.browser); + log::info!("Falling back to new instance for browser: {}", final_profile.browser); // Fallback to launching a new instance for other browsers self.launch_browser_internal(app_handle.clone(), &final_profile, url, internal_proxy_settings, None, false).await } @@ -910,7 +925,7 @@ impl BrowserRunner { } } else { // This case shouldn't happen since we checked is_some() above, but handle it gracefully - println!("URL was unexpectedly None, launching new browser instance"); + log::info!("URL was unexpectedly None, launching new browser instance"); self .launch_browser( app_handle.clone(), @@ -923,9 +938,9 @@ impl BrowserRunner { } else { // Browser is not running or no URL provided, launch new instance if !is_running { - println!("Launching new browser instance - browser not running"); + log::info!("Launching new browser instance - browser not running"); } else { - println!("Launching new browser instance - no URL provided"); + log::info!("Launching new browser instance - no URL provided"); } self .launch_browser_internal( @@ -974,9 +989,10 @@ impl BrowserRunner { let profile_data_path = profile.get_profile_data_path(&profiles_dir); let profile_path_str = profile_data_path.to_string_lossy(); - println!( + log::info!( "Attempting to kill Camoufox process for profile: {} (ID: {})", - profile.name, profile.id + profile.name, + profile.id ); match self @@ -985,9 +1001,10 @@ impl BrowserRunner { .await { Ok(Some(camoufox_process)) => { - println!( + log::info!( "Found Camoufox process: {} (PID: {:?})", - camoufox_process.id, camoufox_process.processId + camoufox_process.id, + camoufox_process.processId ); match self @@ -997,35 +1014,40 @@ impl BrowserRunner { { Ok(stopped) => { if stopped { - println!( + log::info!( "Successfully stopped Camoufox process: {} (PID: {:?})", - camoufox_process.id, camoufox_process.processId + camoufox_process.id, + camoufox_process.processId ); } else { - println!( + log::info!( "Failed to stop Camoufox process: {} (PID: {:?})", - camoufox_process.id, camoufox_process.processId + camoufox_process.id, + camoufox_process.processId ); } } Err(e) => { - println!( + log::info!( "Error stopping Camoufox process {}: {}", - camoufox_process.id, e + camoufox_process.id, + e ); } } } Ok(None) => { - println!( + log::info!( "No running Camoufox process found for profile: {} (ID: {})", - profile.name, profile.id + profile.name, + profile.id ); } Err(e) => { - println!( + log::info!( "Error finding Camoufox process for profile {}: {}", - profile.name, e + profile.name, + e ); } } @@ -1039,9 +1061,11 @@ impl BrowserRunner { .auto_updater .get_pending_update(&profile.browser, &profile.version) { - println!( + log::info!( "Found pending update for Camoufox profile {}: {} -> {}", - profile.name, profile.version, pending_update.new_version + profile.name, + profile.version, + pending_update.new_version ); // Update the profile to the new version @@ -1051,9 +1075,11 @@ impl BrowserRunner { &pending_update.new_version, ) { Ok(updated_profile_after_update) => { - println!( + log::info!( "Successfully updated Camoufox profile {} from version {} to {}", - profile.name, profile.version, pending_update.new_version + profile.name, + profile.version, + pending_update.new_version ); updated_profile = updated_profile_after_update; @@ -1062,13 +1088,14 @@ impl BrowserRunner { .auto_updater .dismiss_update_notification(&pending_update.id) { - eprintln!("Warning: Failed to dismiss pending update notification: {e}"); + log::warn!("Warning: Failed to dismiss pending update notification: {e}"); } } Err(e) => { - eprintln!( + log::error!( "Failed to apply pending update for Camoufox profile {}: {}", - profile.name, e + profile.name, + e ); // Continue with the original profile update (just clearing process_id) } @@ -1079,14 +1106,14 @@ impl BrowserRunner { .save_process_info(&updated_profile) .map_err(|e| format!("Failed to update profile: {e}"))?; - println!( + log::info!( "Emitting profile events for successful Camoufox kill: {}", updated_profile.name ); // Emit profile update event to frontend if let Err(e) = app_handle.emit("profile-updated", &updated_profile) { - println!("Warning: Failed to emit profile update event: {e}"); + log::warn!("Warning: Failed to emit profile update event: {e}"); } // Emit minimal running changed event to frontend immediately @@ -1101,17 +1128,19 @@ impl BrowserRunner { }; if let Err(e) = app_handle.emit("profile-running-changed", &payload) { - println!("Warning: Failed to emit profile running changed event: {e}"); + log::warn!("Warning: Failed to emit profile running changed event: {e}"); } else { - println!( + log::info!( "Successfully emitted profile-running-changed event for Camoufox {}: running={}", - updated_profile.name, payload.is_running + updated_profile.name, + payload.is_running ); } - println!( + log::info!( "Camoufox process cleanup completed for profile: {} (ID: {})", - profile.name, profile.id + profile.name, + profile.id ); // Consolidate browser versions after stopping a browser @@ -1120,9 +1149,9 @@ impl BrowserRunner { .consolidate_browser_versions(&app_handle) { if !consolidated.is_empty() { - println!("Post-stop version consolidation results:"); + log::info!("Post-stop version consolidation results:"); for action in &consolidated { - println!(" {action}"); + log::info!(" {action}"); } } } @@ -1216,25 +1245,29 @@ impl BrowserRunner { }; if profile_path_match { - println!( + log::info!( "Verified stored PID {} is valid for profile {} (ID: {})", - pid, profile.name, profile.id + pid, + profile.name, + profile.id ); pid } else { - println!("Stored PID {} doesn't match profile path for {} (ID: {}), searching for correct process", pid, profile.name, profile.id); + log::info!("Stored PID {} doesn't match profile path for {} (ID: {}), searching for correct process", pid, profile.name, profile.id); // Fall through to search for correct process self.find_browser_process_by_profile(profile)? } } else { - println!("Stored PID {} doesn't match browser type for {} (ID: {}), searching for correct process", pid, profile.name, profile.id); + log::info!("Stored PID {} doesn't match browser type for {} (ID: {}), searching for correct process", pid, profile.name, profile.id); // Fall through to search for correct process self.find_browser_process_by_profile(profile)? } } else { - println!( + log::info!( "Stored PID {} is no longer valid for profile {} (ID: {}), searching for correct process", - pid, profile.name, profile.id + pid, + profile.name, + profile.id ); // Fall through to search for correct process self.find_browser_process_by_profile(profile)? @@ -1244,11 +1277,11 @@ impl BrowserRunner { self.find_browser_process_by_profile(profile)? }; - println!("Attempting to kill browser process with PID: {pid}"); + log::info!("Attempting to kill browser process with PID: {pid}"); // Stop any associated proxy first if let Err(e) = PROXY_MANAGER.stop_proxy(app_handle.clone(), pid).await { - println!("Warning: Failed to stop proxy for PID {pid}: {e}"); + log::warn!("Warning: Failed to stop proxy for PID {pid}: {e}"); } // Kill the process using platform-specific implementation @@ -1273,9 +1306,11 @@ impl BrowserRunner { .auto_updater .get_pending_update(&profile.browser, &profile.version) { - println!( + log::info!( "Found pending update for profile {}: {} -> {}", - profile.name, profile.version, pending_update.new_version + profile.name, + profile.version, + pending_update.new_version ); // Update the profile to the new version @@ -1285,9 +1320,11 @@ impl BrowserRunner { &pending_update.new_version, ) { Ok(updated_profile_after_update) => { - println!( + log::info!( "Successfully updated profile {} from version {} to {}", - profile.name, profile.version, pending_update.new_version + profile.name, + profile.version, + pending_update.new_version ); updated_profile = updated_profile_after_update; @@ -1296,13 +1333,14 @@ impl BrowserRunner { .auto_updater .dismiss_update_notification(&pending_update.id) { - eprintln!("Warning: Failed to dismiss pending update notification: {e}"); + log::warn!("Warning: Failed to dismiss pending update notification: {e}"); } } Err(e) => { - eprintln!( + log::error!( "Failed to apply pending update for profile {}: {}", - profile.name, e + profile.name, + e ); // Continue with the original profile update (just clearing process_id) } @@ -1313,14 +1351,14 @@ impl BrowserRunner { .save_process_info(&updated_profile) .map_err(|e| format!("Failed to update profile: {e}"))?; - println!( + log::info!( "Emitting profile events for successful kill: {}", updated_profile.name ); // Emit profile update event to frontend if let Err(e) = app_handle.emit("profile-updated", &updated_profile) { - println!("Warning: Failed to emit profile update event: {e}"); + log::warn!("Warning: Failed to emit profile update event: {e}"); } // Emit minimal running changed event to frontend immediately @@ -1335,11 +1373,12 @@ impl BrowserRunner { }; if let Err(e) = app_handle.emit("profile-running-changed", &payload) { - println!("Warning: Failed to emit profile running changed event: {e}"); + log::warn!("Warning: Failed to emit profile running changed event: {e}"); } else { - println!( + log::info!( "Successfully emitted profile-running-changed event for {}: running={}", - updated_profile.name, payload.is_running + updated_profile.name, + payload.is_running ); } @@ -1349,9 +1388,9 @@ impl BrowserRunner { .consolidate_browser_versions(&app_handle) { if !consolidated.is_empty() { - println!("Post-stop version consolidation results:"); + log::info!("Post-stop version consolidation results:"); for action in &consolidated { - println!(" {action}"); + log::info!(" {action}"); } } } @@ -1369,9 +1408,10 @@ impl BrowserRunner { let profile_data_path = profile.get_profile_data_path(&profiles_dir); let profile_data_path_str = profile_data_path.to_string_lossy(); - println!( + log::info!( "Searching for {} browser process with profile path: {}", - profile.browser, profile_data_path_str + profile.browser, + profile_data_path_str ); for (pid, process) in system.processes() { @@ -1459,9 +1499,12 @@ impl BrowserRunner { if profile_path_match { let pid_u32 = pid.as_u32(); - println!( + log::info!( "Found matching {} browser process with PID: {} for profile: {} (ID: {})", - profile.browser, pid_u32, profile.name, profile.id + profile.browser, + pid_u32, + profile.name, + profile.id ); return Ok(pid_u32); } @@ -1492,18 +1535,18 @@ impl BrowserRunner { .find(|p| p.id.to_string() == profile_id) .ok_or_else(|| format!("Profile '{profile_id}' not found"))?; - println!("Opening URL '{url}' with profile '{profile_id}'"); + log::info!("Opening URL '{url}' with profile '{profile_id}'"); // Use launch_or_open_url which handles both launching new instances and opening in existing ones self .launch_or_open_url(app_handle, &profile, Some(url.clone()), None) .await .map_err(|e| { - println!("Failed to open URL with profile '{profile_id}': {e}"); + log::info!("Failed to open URL with profile '{profile_id}': {e}"); format!("Failed to open URL with profile: {e}") })?; - println!("Successfully opened URL '{url}' with profile '{profile_id}'"); + log::info!("Successfully opened URL '{url}' with profile '{profile_id}'"); Ok(()) } } @@ -1514,9 +1557,10 @@ pub async fn launch_browser_profile( profile: BrowserProfile, url: Option, ) -> Result { - println!( + log::info!( "Launch request received for profile: {} (ID: {})", - profile.name, profile.id + profile.name, + profile.id ); let browser_runner = BrowserRunner::instance(); @@ -1539,9 +1583,10 @@ pub async fn launch_browser_profile( } }; - println!( + log::info!( "Resolved profile for launch: {} (ID: {})", - profile_for_launch.name, profile_for_launch.id + profile_for_launch.name, + profile_for_launch.id ); // Always start a local proxy before launching (non-Camoufox handled here; Camoufox has its own flow) @@ -1596,7 +1641,7 @@ pub async fn launch_browser_profile( .map_err(|e| format!("Failed to update profile proxy: {e}"))?; } - println!( + log::info!( "Local proxy prepared for profile: {} on port: {} (upstream: {})", profile_for_launch.name, internal_proxy.port, @@ -1608,21 +1653,22 @@ pub async fn launch_browser_profile( } Err(e) => { let error_msg = format!("Failed to start local proxy: {e}"); - eprintln!("{}", error_msg); + log::error!("{}", error_msg); // DO NOT launch browser if proxy startup fails - all browsers must use local proxy return Err(error_msg); } } } - println!( + log::info!( "Starting browser launch for profile: {} (ID: {})", - profile_for_launch.name, profile_for_launch.id + profile_for_launch.name, + profile_for_launch.id ); // Launch browser or open URL in existing instance let updated_profile = browser_runner.launch_or_open_url(app_handle.clone(), &profile_for_launch, url, internal_proxy_settings.as_ref()).await.map_err(|e| { - println!("Browser launch failed for profile: {}, error: {}", profile_for_launch.name, e); + log::info!("Browser launch failed for profile: {}, error: {}", profile_for_launch.name, e); // Emit a failure event to clear loading states in the frontend #[derive(serde::Serialize)] @@ -1636,7 +1682,7 @@ pub async fn launch_browser_profile( }; if let Err(e) = app_handle.emit("profile-running-changed", &payload) { - println!("Warning: Failed to emit profile running changed event: {e}"); + log::warn!("Warning: Failed to emit profile running changed event: {e}"); } // Check if this is an architecture compatibility issue @@ -1648,9 +1694,10 @@ pub async fn launch_browser_profile( format!("Failed to launch browser or open URL: {e}") })?; - println!( + log::info!( "Browser launch completed for profile: {} (ID: {})", - updated_profile.name, updated_profile.id + updated_profile.name, + updated_profile.id ); // Now update the proxy with the correct PID if we have one @@ -1676,9 +1723,10 @@ pub async fn kill_browser_profile( app_handle: tauri::AppHandle, profile: BrowserProfile, ) -> Result<(), String> { - println!( + log::info!( "Kill request received for profile: {} (ID: {})", - profile.name, profile.id + profile.name, + profile.id ); let browser_runner = BrowserRunner::instance(); @@ -1688,14 +1736,15 @@ pub async fn kill_browser_profile( .await { Ok(()) => { - println!( + log::info!( "Successfully killed browser profile: {} (ID: {})", - profile.name, profile.id + profile.name, + profile.id ); Ok(()) } Err(e) => { - println!("Failed to kill browser profile {}: {}", profile.name, e); + log::info!("Failed to kill browser profile {}: {}", profile.name, e); // Emit a failure event to clear loading states in the frontend #[derive(serde::Serialize)] @@ -1710,7 +1759,7 @@ pub async fn kill_browser_profile( }; if let Err(e) = app_handle.emit("profile-running-changed", &payload) { - println!("Warning: Failed to emit profile running changed event: {e}"); + log::warn!("Warning: Failed to emit profile running changed event: {e}"); } Err(format!("Failed to kill browser: {e}")) diff --git a/src-tauri/src/browser_version_manager.rs b/src-tauri/src/browser_version_manager.rs index 3a912f3..cd17ebf 100644 --- a/src-tauri/src/browser_version_manager.rs +++ b/src-tauri/src/browser_version_manager.rs @@ -277,7 +277,7 @@ impl BrowserVersionManager { .api_client .save_cached_versions(browser, &merged_releases) { - eprintln!("Failed to save merged cache for {browser}: {e}"); + log::error!("Failed to save merged cache for {browser}: {e}"); } } @@ -534,7 +534,7 @@ impl BrowserVersionManager { }) .collect(); if let Err(e) = self.api_client.save_cached_versions(browser, &releases) { - eprintln!("Failed to save updated cache for {browser}: {e}"); + log::error!("Failed to save updated cache for {browser}: {e}"); } Ok(new_versions_count) @@ -922,7 +922,7 @@ impl BrowserVersionManager { .collect(); // Always save so that other callers without release_name can classify correctly if let Err(e) = self.api_client.save_cached_versions("brave", &converted) { - eprintln!("Failed to persist Brave versions cache: {e}"); + log::error!("Failed to persist Brave versions cache: {e}"); } Ok(releases.into_iter().map(|r| r.tag_name).collect()) @@ -947,7 +947,7 @@ impl BrowserVersionManager { }) .collect(); if let Err(e) = self.api_client.save_cached_versions("brave", &converted) { - eprintln!("Failed to persist Brave versions cache: {e}"); + log::error!("Failed to persist Brave versions cache: {e}"); } Ok(releases) @@ -1271,7 +1271,7 @@ mod tests { let unsupported_result = service.get_download_info("unsupported", "1.0.0"); assert!(unsupported_result.is_err()); - println!("Download info test passed for all browsers"); + log::info!("Download info test passed for all browsers"); } } @@ -1307,7 +1307,7 @@ pub async fn fetch_browser_versions_cached_first( .fetch_browser_versions_detailed(&browser_str_clone, false) .await { - eprintln!("Background version update failed for {browser_str_clone}: {e}"); + log::error!("Background version update failed for {browser_str_clone}: {e}"); } }); } @@ -1339,7 +1339,7 @@ pub async fn fetch_browser_versions_with_count_cached_first( .fetch_browser_versions_with_count(&browser_str_clone, false) .await { - eprintln!("Background version update failed for {browser_str_clone}: {e}"); + log::error!("Background version update failed for {browser_str_clone}: {e}"); } }); } diff --git a/src-tauri/src/camoufox_manager.rs b/src-tauri/src/camoufox_manager.rs index 16bd6e2..a176425 100644 --- a/src-tauri/src/camoufox_manager.rs +++ b/src-tauri/src/camoufox_manager.rs @@ -206,7 +206,7 @@ impl CamoufoxManager { url: Option<&str>, ) -> Result> { let custom_config = if let Some(existing_fingerprint) = &config.fingerprint { - println!("Using existing fingerprint from profile metadata"); + log::info!("Using existing fingerprint from profile metadata"); existing_fingerprint.clone() } else { return Err("No fingerprint provided".into()); @@ -266,18 +266,18 @@ impl CamoufoxManager { } // Execute nodecar sidecar command - println!("Executing nodecar command with args: {args:?}"); + log::info!("Executing nodecar command with args: {args:?}"); let output = sidecar_command.output().await?; if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); let stdout = String::from_utf8_lossy(&output.stdout); - println!("nodecar camoufox failed - stdout: {stdout}, stderr: {stderr}"); + log::info!("nodecar camoufox failed - stdout: {stdout}, stderr: {stderr}"); return Err(format!("nodecar camoufox failed: {stderr}").into()); } let stdout = String::from_utf8_lossy(&output.stdout); - println!("nodecar camoufox output: {stdout}"); + log::info!("nodecar camoufox output: {stdout}"); // Parse the JSON output let launch_result: CamoufoxLaunchResult = serde_json::from_str(&stdout) diff --git a/src-tauri/src/downloaded_browsers_registry.rs b/src-tauri/src/downloaded_browsers_registry.rs index 39d3b88..5a64066 100644 --- a/src-tauri/src/downloaded_browsers_registry.rs +++ b/src-tauri/src/downloaded_browsers_registry.rs @@ -122,7 +122,7 @@ impl DownloadedBrowsersRegistry { let browser_type = match BrowserType::from_str(browser) { Ok(bt) => bt, Err(_) => { - println!("Invalid browser type: {browser}"); + log::info!("Invalid browser type: {browser}"); return false; } }; @@ -146,7 +146,7 @@ impl DownloadedBrowsersRegistry { // If files don't exist but registry thinks they do, clean up the registry if !files_exist { - println!("Cleaning up stale registry entry for {browser} {version}"); + log::info!("Cleaning up stale registry entry for {browser} {version}"); self.remove_browser(browser, version); let _ = self.save(); // Don't fail if save fails, just log } @@ -166,7 +166,7 @@ impl DownloadedBrowsersRegistry { pub fn mark_download_started(&self, browser: &str, version: &str, file_path: PathBuf) { // Only mark download started, don't add to registry yet // The browser will be added to registry only after verification succeeds - println!( + log::info!( "Marking download started for {}:{} at {}", browser, version, @@ -187,7 +187,7 @@ impl DownloadedBrowsersRegistry { file_path, }; self.add_browser(info); - println!("Browser {browser}:{version} successfully added to registry after verification"); + log::info!("Browser {browser}:{version} successfully added to registry after verification"); Ok(()) } @@ -268,7 +268,7 @@ impl DownloadedBrowsersRegistry { let pending_updates = match self.auto_updater.get_pending_update_versions() { Ok(updates) => updates, Err(e) => { - eprintln!("Warning: Failed to get pending updates for cleanup: {e}"); + log::warn!("Warning: Failed to get pending updates for cleanup: {e}"); std::collections::HashSet::new() } }; @@ -283,13 +283,13 @@ impl DownloadedBrowsersRegistry { // Don't remove if it's used by any active profile if active_set.contains(&browser_version) { - println!("Keeping: {browser} {version} (in use by profile)"); + log::info!("Keeping: {browser} {version} (in use by profile)"); continue; } // Don't remove if it's currently running (even if not in active profiles) if running_set.contains(&browser_version) { - println!("Keeping: {browser} {version} (currently running)"); + log::info!("Keeping: {browser} {version} (currently running)"); continue; } @@ -300,14 +300,14 @@ impl DownloadedBrowsersRegistry { let has_running_profile_for_browser = running_profiles.iter().any(|(b, _)| b == browser); if has_running_profile_for_browser { - println!("Keeping: {browser} {version} (pending update for running profile)"); + log::info!("Keeping: {browser} {version} (pending update for running profile)"); continue; } } // Mark for removal to_remove.push(browser_version); - println!("Marking for removal: {browser} {version} (not used by any profile)"); + log::info!("Marking for removal: {browser} {version} (not used by any profile)"); } } } @@ -315,21 +315,21 @@ impl DownloadedBrowsersRegistry { // Remove unused binaries and their version folders for (browser, version) in to_remove { if let Err(e) = self.cleanup_failed_download(&browser, &version) { - eprintln!("Failed to cleanup unused binary {browser}:{version}: {e}"); + log::error!("Failed to cleanup unused binary {browser}:{version}: {e}"); } else { // After removing the binary, also remove the empty version folder if let Err(e) = self.remove_empty_version_folder(&browser, &version) { - eprintln!("Failed to remove empty version folder for {browser}:{version}: {e}"); + log::error!("Failed to remove empty version folder for {browser}:{version}: {e}"); } cleaned_up.push(format!("{browser} {version}")); - println!("Successfully removed unused binary: {browser} {version}"); + log::info!("Successfully removed unused binary: {browser} {version}"); } } if cleaned_up.is_empty() { - println!("No unused binaries found to clean up"); + log::info!("No unused binaries found to clean up"); } else { - println!("Cleaned up {} unused binaries", cleaned_up.len()); + log::info!("Cleaned up {} unused binaries", cleaned_up.len()); } Ok(cleaned_up) @@ -374,7 +374,7 @@ impl DownloadedBrowsersRegistry { // Files don't exist, remove from registry if let Some(_removed) = self.remove_browser(&browser_str, &version) { cleaned_up.push(format!("{browser_str} {version}")); - println!("Removed stale registry entry for {browser_str} {version}"); + log::info!("Removed stale registry entry for {browser_str} {version}"); } } } @@ -529,7 +529,7 @@ impl DownloadedBrowsersRegistry { if entries.next().is_none() { // Directory is empty, remove it fs::remove_dir(&version_dir)?; - println!("Removed empty version folder: {}", version_dir.display()); + log::info!("Removed empty version folder: {}", version_dir.display()); // Also check if the browser folder is now empty and remove it too let browser_dir = binaries_dir.join(browser); @@ -537,7 +537,7 @@ impl DownloadedBrowsersRegistry { if let Ok(mut browser_entries) = fs::read_dir(&browser_dir) { if browser_entries.next().is_none() { fs::remove_dir(&browser_dir)?; - println!("Removed empty browser folder: {}", browser_dir.display()); + log::info!("Removed empty browser folder: {}", browser_dir.display()); } } } @@ -618,7 +618,7 @@ impl DownloadedBrowsersRegistry { // Remove empty version directories for (version_path, version_name) in empty_version_dirs { if let Err(e) = fs::remove_dir(&version_path) { - eprintln!( + log::error!( "Failed to remove empty version folder {}: {e}", version_path.display() ); @@ -626,7 +626,7 @@ impl DownloadedBrowsersRegistry { cleaned_up.push(format!( "Removed empty version folder: {browser_name}/{version_name}" )); - println!("Removed empty version folder: {}", version_path.display()); + log::info!("Removed empty version folder: {}", version_path.display()); } } @@ -635,13 +635,13 @@ impl DownloadedBrowsersRegistry { if let Ok(mut entries) = fs::read_dir(&browser_path) { if entries.next().is_none() { if let Err(e) = fs::remove_dir(&browser_path) { - eprintln!( + log::error!( "Failed to remove empty browser folder {}: {e}", browser_path.display() ); } else { cleaned_up.push(format!("Removed empty browser folder: {browser_name}")); - println!("Removed empty browser folder: {}", browser_path.display()); + log::info!("Removed empty browser folder: {}", browser_path.display()); } } } @@ -656,7 +656,7 @@ impl DownloadedBrowsersRegistry { &self, app_handle: &tauri::AppHandle, ) -> Result, Box> { - println!("Starting browser version consolidation..."); + log::info!("Starting browser version consolidation..."); let profiles = self .profile_manager @@ -691,15 +691,16 @@ impl DownloadedBrowsersRegistry { if browser.is_version_downloaded(&profile.version, &binaries_dir) { available_versions.push(profile.version.clone()); } else { - println!( + log::info!( "Profile '{}' references version {} that doesn't exist on disk", - profile.name, profile.version + profile.name, + profile.version ); } } if available_versions.is_empty() { - println!("No available versions found for {browser_name}, skipping consolidation"); + log::info!("No available versions found for {browser_name}, skipping consolidation"); continue; } @@ -710,7 +711,7 @@ impl DownloadedBrowsersRegistry { }); let latest_version = &available_versions[0]; - println!("Latest available version for {browser_name}: {latest_version}"); + log::info!("Latest available version for {browser_name}: {latest_version}"); // Check which profiles need to be updated to the latest version let mut profiles_to_update = Vec::new(); @@ -723,9 +724,10 @@ impl DownloadedBrowsersRegistry { profiles_to_update.push(profile); older_versions_to_remove.insert(profile.version.clone()); } else { - println!( + log::info!( "Skipping version update for running profile: {} ({})", - profile.name, profile.version + profile.name, + profile.version ); } } @@ -744,21 +746,21 @@ impl DownloadedBrowsersRegistry { )); } Err(e) => { - eprintln!("Failed to update profile '{}': {}", profile.name, e); + log::error!("Failed to update profile '{}': {}", profile.name, e); } } } // Remove older version binaries that are no longer needed for old_version in &older_versions_to_remove { - println!("Consolidating: removing old version {browser_name} {old_version}"); + log::info!("Consolidating: removing old version {browser_name} {old_version}"); match self.cleanup_failed_download(browser_name, old_version) { Ok(_) => { consolidated.push(format!("Removed old version: {browser_name} {old_version}")); - println!("Successfully removed old version: {browser_name} {old_version}"); + log::info!("Successfully removed old version: {browser_name} {old_version}"); } Err(e) => { - eprintln!("Failed to cleanup old version {browser_name} {old_version}: {e}"); + log::error!("Failed to cleanup old version {browser_name} {old_version}: {e}"); } } } @@ -770,7 +772,7 @@ impl DownloadedBrowsersRegistry { .save() .map_err(|e| format!("Failed to save registry after consolidation: {e}"))?; - println!( + log::info!( "Browser version consolidation completed: {} actions taken", consolidated.len() ); @@ -793,9 +795,10 @@ impl DownloadedBrowsersRegistry { let browser_type = match BrowserType::from_str(&profile.browser) { Ok(bt) => bt, Err(_) => { - println!( + log::info!( "Warning: Invalid browser type '{}' for profile '{}'", - profile.browser, profile.name + profile.browser, + profile.name ); continue; } @@ -817,7 +820,7 @@ impl DownloadedBrowsersRegistry { return Err("Failed to get base directories".into()); }; - println!( + log::info!( "binaries_dir: {binaries_dir:?} for profile: {}", profile.name ); @@ -839,7 +842,7 @@ impl DownloadedBrowsersRegistry { // First, clean up any stale registry entries if let Ok(cleaned_up) = self.verify_and_cleanup_stale_entries() { if !cleaned_up.is_empty() { - println!( + log::info!( "Cleaned up {} stale registry entries: {}", cleaned_up.len(), cleaned_up.join(", ") @@ -850,9 +853,9 @@ impl DownloadedBrowsersRegistry { // Consolidate browser versions - keep only latest version per browser if let Ok(consolidated) = self.consolidate_browser_versions(app_handle) { if !consolidated.is_empty() { - println!("Version consolidation results:"); + log::info!("Version consolidation results:"); for action in &consolidated { - println!(" {action}"); + log::info!(" {action}"); } } } @@ -861,7 +864,7 @@ impl DownloadedBrowsersRegistry { let mut downloaded = Vec::new(); for (profile_name, browser, version) in missing_binaries { - println!("Downloading missing binary for profile '{profile_name}': {browser} {version}"); + log::info!("Downloading missing binary for profile '{profile_name}': {browser} {version}"); match crate::downloader::download_browser( app_handle.clone(), @@ -882,31 +885,31 @@ impl DownloadedBrowsersRegistry { { Ok(updated_profiles) => { if !updated_profiles.is_empty() { - println!( + log::info!( "Successfully updated {} profiles to version {}:", updated_profiles.len(), version ); for update_msg in updated_profiles { - println!(" {update_msg}"); + log::info!(" {update_msg}"); } } } Err(e) => { - eprintln!("CRITICAL: Failed to update profiles to version {version}: {e}"); - eprintln!("This may cause profile version inconsistencies and cleanup issues"); + log::error!("CRITICAL: Failed to update profiles to version {version}: {e}"); + log::error!("This may cause profile version inconsistencies and cleanup issues"); } } } Err(e) => { - eprintln!("Failed to download {browser} {version} for profile '{profile_name}': {e}"); + log::error!("Failed to download {browser} {version} for profile '{profile_name}': {e}"); } } } // Check if GeoIP database is missing for Camoufox profiles if self.geoip_downloader.check_missing_geoip_database()? { - println!("GeoIP database is missing for Camoufox profiles, downloading..."); + log::info!("GeoIP database is missing for Camoufox profiles, downloading..."); match self .geoip_downloader @@ -915,10 +918,10 @@ impl DownloadedBrowsersRegistry { { Ok(_) => { downloaded.push("GeoIP database for Camoufox".to_string()); - println!("GeoIP database downloaded successfully"); + log::info!("GeoIP database downloaded successfully"); } Err(e) => { - eprintln!("Failed to download GeoIP database: {e}"); + log::error!("Failed to download GeoIP database: {e}"); // Don't fail the entire operation if GeoIP download fails } } @@ -945,9 +948,10 @@ impl DownloadedBrowsersRegistry { if profile.browser == browser && profile.version != version { // Check if profile is currently running if profile.process_id.is_some() { - println!( + log::info!( "Skipping version update for running profile: {} ({})", - profile.name, profile.version + profile.name, + profile.version ); continue; } @@ -963,18 +967,19 @@ impl DownloadedBrowsersRegistry { "Updated profile '{}' from {} to {}", profile.name, profile.version, version )); - println!( + log::info!( "Successfully updated profile '{}' to version {}", - profile.name, version + profile.name, + version ); // Save registry after each profile update to ensure consistency if let Err(e) = self.save() { - eprintln!("Warning: Failed to save registry after profile update: {e}"); + log::warn!("Warning: Failed to save registry after profile update: {e}"); } } Err(e) => { - eprintln!("Failed to update profile '{}': {}", profile.name, e); + log::error!("Failed to update profile '{}': {}", profile.name, e); } } } @@ -1016,7 +1021,7 @@ lazy_static::lazy_static! { static ref DOWNLOADED_BROWSERS_REGISTRY: DownloadedBrowsersRegistry = { let registry = DownloadedBrowsersRegistry::new(); if let Err(e) = registry.load() { - eprintln!("Warning: Failed to load downloaded browsers registry: {e}"); + log::warn!("Warning: Failed to load downloaded browsers registry: {e}"); } registry }; diff --git a/src-tauri/src/downloader.rs b/src-tauri/src/downloader.rs index fe87c30..3efaf63 100644 --- a/src-tauri/src/downloader.rs +++ b/src-tauri/src/downloader.rs @@ -104,7 +104,7 @@ impl Downloader { let releases = match self.api_client.fetch_zen_releases_with_caching(true).await { Ok(releases) => releases, Err(e) => { - eprintln!("Failed to fetch Zen releases: {e}"); + log::error!("Failed to fetch Zen releases: {e}"); return Err(format!("Failed to fetch Zen releases from GitHub API: {e}. This might be due to GitHub API rate limiting or network issues. Please try again later.").into()); } }; @@ -644,7 +644,7 @@ impl Downloader { return Ok(version); } else { // Registry says it's downloaded but files don't exist - clean up registry - println!("Registry indicates {browser_str} {version} is downloaded, but files are missing. Cleaning up registry entry."); + log::info!("Registry indicates {browser_str} {version} is downloaded, but files are missing. Cleaning up registry entry."); self.registry.remove_browser(&browser_str, &version); self .registry @@ -764,7 +764,7 @@ impl Downloader { let _ = app_handle.emit("download-progress", &progress); // Verify the browser was downloaded correctly - println!("Verifying download for browser: {browser_str}, version: {version}"); + log::info!("Verifying download for browser: {browser_str}, version: {version}"); // Use the browser's own verification method if !browser.is_version_downloaded(&version, &binaries_dir) { @@ -838,7 +838,7 @@ impl Downloader { .registry .mark_download_completed(&browser_str, &version, browser_dir.clone()) { - eprintln!("Warning: Could not mark {browser_str} {version} as completed in registry: {e}"); + log::warn!("Warning: Could not mark {browser_str} {version} as completed in registry: {e}"); } self .registry @@ -850,7 +850,7 @@ impl Downloader { let archive_path = browser_dir.join(&download_info.filename); if archive_path.exists() { if let Err(e) = std::fs::remove_file(&archive_path) { - println!("Warning: Could not delete archive file after verification: {e}"); + log::warn!("Warning: Could not delete archive file after verification: {e}"); } } } @@ -859,7 +859,7 @@ impl Downloader { if browser_str == "camoufox" { // Check if GeoIP database is already available if !crate::geoip_downloader::GeoIPDownloader::is_geoip_database_available() { - println!("Downloading GeoIP database for Camoufox..."); + log::info!("Downloading GeoIP database for Camoufox..."); match self .geoip_downloader @@ -867,15 +867,15 @@ impl Downloader { .await { Ok(_) => { - println!("GeoIP database downloaded successfully"); + log::info!("GeoIP database downloaded successfully"); } Err(e) => { - eprintln!("Failed to download GeoIP database: {e}"); + log::error!("Failed to download GeoIP database: {e}"); // Don't fail the browser download if GeoIP download fails } } } else { - println!("GeoIP database already available"); + log::info!("GeoIP database already available"); } } diff --git a/src-tauri/src/extraction.rs b/src-tauri/src/extraction.rs index af3436f..b9ed33c 100644 --- a/src-tauri/src/extraction.rs +++ b/src-tauri/src/extraction.rs @@ -55,7 +55,7 @@ impl Extractor { // If the executable is not in the expected subdirectory, create the structure if !exe_path.starts_with(&expected_subdir) { - println!("Reorganizing directory structure for {}", browser_type); + log::info!("Reorganizing directory structure for {}", browser_type); // Create the expected subdirectory std::fs::create_dir_all(&expected_subdir)?; @@ -78,19 +78,19 @@ impl Extractor { // Move the file/directory if let Err(e) = std::fs::rename(&path, &target_path) { - println!( + log::info!( "Warning: Failed to move {} to {}: {}", path.display(), target_path.display(), e ); } else { - println!("Moved {} to {}", path.display(), target_path.display()); + log::info!("Moved {} to {}", path.display(), target_path.display()); } } } - println!("Directory structure reorganized for {}", browser_type); + log::info!("Directory structure reorganized for {}", browser_type); } Ok(()) @@ -117,7 +117,7 @@ impl Extractor { }; let _ = app_handle.emit("download-progress", &progress); - println!( + log::info!( "Starting extraction of {} for browser {} version {}", archive_path.display(), browser_type.as_str(), @@ -132,7 +132,7 @@ impl Extractor { e ) })?; - println!("Detected format: {actual_format}"); + log::info!("Detected format: {actual_format}"); let extraction_result = match actual_format.as_str() { "dmg" => { @@ -210,7 +210,7 @@ impl Extractor { match extraction_result { Ok(path) => { - println!( + log::info!( "Successfully extracted {} {} to: {}", browser_type.as_str(), version, @@ -219,7 +219,7 @@ impl Extractor { Ok(path) } Err(e) => { - eprintln!( + log::error!( "Extraction failed for {} {}: {}", browser_type.as_str(), version, @@ -337,7 +337,7 @@ impl Extractor { dmg_path: &Path, dest_dir: &Path, ) -> Result> { - println!( + log::info!( "Extracting DMG: {} to {}", dmg_path.display(), dest_dir.display() @@ -353,7 +353,7 @@ impl Extractor { )); create_dir_all(&mount_point)?; - println!("Created mount point: {}", mount_point.display()); + log::info!("Created mount point: {}", mount_point.display()); // Mount the DMG let output = Command::new("hdiutil") @@ -369,7 +369,7 @@ impl Extractor { if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); let stdout = String::from_utf8_lossy(&output.stdout); - println!("Failed to mount DMG. stdout: {stdout}, stderr: {stderr}"); + log::info!("Failed to mount DMG. stdout: {stdout}, stderr: {stderr}"); // Clean up mount point before returning error let _ = fs::remove_dir_all(&mount_point); @@ -377,7 +377,7 @@ impl Extractor { return Err(format!("Failed to mount DMG: {stderr}").into()); } - println!("Successfully mounted DMG"); + log::info!("Successfully mounted DMG"); // Find the .app directory in the mount point let app_result = self.find_app_in_directory(&mount_point).await; @@ -385,7 +385,7 @@ impl Extractor { let app_entry = match app_result { Ok(app_path) => app_path, Err(e) => { - println!("Failed to find .app in mount point: {e}"); + log::info!("Failed to find .app in mount point: {e}"); // Try to unmount before returning error let _ = Command::new("hdiutil") @@ -397,12 +397,12 @@ impl Extractor { } }; - println!("Found .app bundle: {}", app_entry.display()); + log::info!("Found .app bundle: {}", app_entry.display()); // Copy the .app to the destination let app_path = dest_dir.join(app_entry.file_name().unwrap()); - println!("Copying .app to: {}", app_path.display()); + log::info!("Copying .app to: {}", app_path.display()); let output = Command::new("cp") .args([ @@ -414,7 +414,7 @@ impl Extractor { if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); - println!("Failed to copy app: {stderr}"); + log::info!("Failed to copy app: {stderr}"); // Unmount before returning error let _ = Command::new("hdiutil") @@ -425,7 +425,7 @@ impl Extractor { return Err(format!("Failed to copy app: {stderr}").into()); } - println!("Successfully copied .app bundle"); + log::info!("Successfully copied .app bundle"); // Remove quarantine attributes let _ = Command::new("xattr") @@ -436,7 +436,7 @@ impl Extractor { .args(["-cr", app_path.to_str().unwrap()]) .output(); - println!("Removed quarantine attributes"); + log::info!("Removed quarantine attributes"); // Unmount the DMG let output = Command::new("hdiutil") @@ -445,10 +445,10 @@ impl Extractor { if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); - println!("Warning: Failed to unmount DMG: {stderr}"); + log::warn!("Warning: Failed to unmount DMG: {stderr}"); // Don't fail if unmount fails - the extraction was successful } else { - println!("Successfully unmounted DMG"); + log::info!("Successfully unmounted DMG"); } // Clean up mount point directory @@ -486,7 +486,7 @@ impl Extractor { if path.is_dir() { if let Some(extension) = path.extension() { if extension == "app" { - println!("Found .app bundle at depth {}: {}", depth, path.display()); + log::info!("Found .app bundle at depth {}: {}", depth, path.display()); return Ok(path); } } @@ -535,7 +535,7 @@ impl Extractor { zip_path: &Path, dest_dir: &Path, ) -> Result> { - println!("Extracting ZIP archive: {}", zip_path.display()); + log::info!("Extracting ZIP archive: {}", zip_path.display()); std::fs::create_dir_all(dest_dir)?; let file = File::open(zip_path) @@ -544,7 +544,7 @@ impl Extractor { let mut archive = zip::ZipArchive::new(BufReader::new(file)) .map_err(|e| format!("Failed to read ZIP archive {}: {}", zip_path.display(), e))?; - println!("ZIP archive contains {} files", archive.len()); + log::info!("ZIP archive contains {} files", archive.len()); for i in 0..archive.len() { let mut entry = archive @@ -591,7 +591,7 @@ impl Extractor { } } - println!("ZIP extraction completed. Searching for executable..."); + log::info!("ZIP extraction completed. Searching for executable..."); self .find_extracted_executable(dest_dir) .await @@ -603,7 +603,7 @@ impl Extractor { tar_path: &Path, dest_dir: &Path, ) -> Result> { - println!("Extracting tar.gz archive: {}", tar_path.display()); + log::info!("Extracting tar.gz archive: {}", tar_path.display()); std::fs::create_dir_all(dest_dir)?; let file = File::open(tar_path)?; @@ -615,7 +615,7 @@ impl Extractor { // Set executable permissions for extracted files self.set_executable_permissions_recursive(dest_dir).await?; - println!("tar.gz extraction completed. Searching for executable..."); + log::info!("tar.gz extraction completed. Searching for executable..."); self.find_extracted_executable(dest_dir).await } @@ -624,7 +624,7 @@ impl Extractor { tar_path: &Path, dest_dir: &Path, ) -> Result> { - println!("Extracting tar.bz2 archive: {}", tar_path.display()); + log::info!("Extracting tar.bz2 archive: {}", tar_path.display()); std::fs::create_dir_all(dest_dir)?; let file = File::open(tar_path)?; @@ -636,7 +636,7 @@ impl Extractor { // Set executable permissions for extracted files self.set_executable_permissions_recursive(dest_dir).await?; - println!("tar.bz2 extraction completed. Searching for executable..."); + log::info!("tar.bz2 extraction completed. Searching for executable..."); self.find_extracted_executable(dest_dir).await } @@ -645,7 +645,7 @@ impl Extractor { tar_path: &Path, dest_dir: &Path, ) -> Result> { - println!("Extracting tar.xz archive: {}", tar_path.display()); + log::info!("Extracting tar.xz archive: {}", tar_path.display()); std::fs::create_dir_all(dest_dir)?; let file = File::open(tar_path)?; @@ -671,7 +671,7 @@ impl Extractor { // Set executable permissions for extracted files self.set_executable_permissions_recursive(dest_dir).await?; - println!("tar.xz extraction completed. Searching for executable..."); + log::info!("tar.xz extraction completed. Searching for executable..."); self.find_extracted_executable(dest_dir).await } @@ -680,7 +680,7 @@ impl Extractor { msi_path: &Path, dest_dir: &Path, ) -> Result> { - println!("Extracting MSI archive: {}", msi_path.display()); + log::info!("Extracting MSI archive: {}", msi_path.display()); std::fs::create_dir_all(dest_dir)?; // Extract MSI in a separate scope to avoid Send issues @@ -689,7 +689,7 @@ impl Extractor { extractor.to(dest_dir); } - println!("MSI extraction completed. Searching for executable..."); + log::info!("MSI extraction completed. Searching for executable..."); self.find_extracted_executable(dest_dir).await } @@ -812,7 +812,7 @@ impl Extractor { &self, dest_dir: &Path, ) -> Result> { - println!("Searching for .app bundle in: {}", dest_dir.display()); + log::info!("Searching for .app bundle in: {}", dest_dir.display()); // Use the enhanced recursive search match self.find_app_in_directory(dest_dir).await { @@ -820,7 +820,7 @@ impl Extractor { // Check if the app is in a subdirectory and move it to the root if needed let app_parent = app_path.parent().unwrap(); if app_parent != dest_dir { - println!( + log::info!( "Found .app in subdirectory, moving to root: {} -> {}", app_path.display(), dest_dir.display() @@ -837,15 +837,15 @@ impl Extractor { } } - println!("Successfully moved .app to: {}", target_path.display()); + log::info!("Successfully moved .app to: {}", target_path.display()); Ok(target_path) } else { - println!("Found .app at root level: {}", app_path.display()); + log::info!("Found .app at root level: {}", app_path.display()); Ok(app_path) } } Err(e) => { - println!("Failed to find .app bundle: {e}"); + log::info!("Failed to find .app bundle: {e}"); Err("No .app found after extraction".into()) } } @@ -856,7 +856,7 @@ impl Extractor { &self, dest_dir: &Path, ) -> Result> { - println!( + log::info!( "Searching for Windows executable in: {}", dest_dir.display() ); @@ -877,7 +877,7 @@ impl Extractor { for exe_name in &priority_exe_names { let exe_path = dest_dir.join(exe_name); if exe_path.exists() { - println!("Found priority executable: {}", exe_path.display()); + log::info!("Found priority executable: {}", exe_path.display()); return Ok(exe_path); } } @@ -885,7 +885,7 @@ impl Extractor { // Recursively search for executables with depth limit match self.find_windows_executable_recursive(dest_dir, 0, 3).await { Ok(exe_path) => { - println!( + log::info!( "Found executable via recursive search: {}", exe_path.display() ); @@ -983,7 +983,7 @@ impl Extractor { &self, dest_dir: &Path, ) -> Result> { - println!("Searching for Linux executable in: {}", dest_dir.display()); + log::info!("Searching for Linux executable in: {}", dest_dir.display()); // Enhanced list of common browser executable names let exe_names = [ @@ -1031,7 +1031,7 @@ impl Extractor { for exe_name in &exe_names { let exe_path = dest_dir.join(exe_name); if exe_path.exists() && self.is_executable(&exe_path) { - println!("Found executable at root level: {}", exe_path.display()); + log::info!("Found executable at root level: {}", exe_path.display()); return Ok(exe_path); } } @@ -1078,7 +1078,7 @@ impl Extractor { for exe_name in &exe_names { let exe_path = subdir_path.join(exe_name); if exe_path.exists() && self.is_executable(&exe_path) { - println!("Found executable in subdirectory: {}", exe_path.display()); + log::info!("Found executable in subdirectory: {}", exe_path.display()); return Ok(exe_path); } } @@ -1091,7 +1091,7 @@ impl Extractor { let path = entry.path(); if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) { if file_name.ends_with(".AppImage") && self.is_executable(&path) { - println!("Found AppImage: {}", path.display()); + log::info!("Found AppImage: {}", path.display()); return Ok(path); } } @@ -1099,15 +1099,15 @@ impl Extractor { } // Last resort: recursive search for any executable file - println!("Performing recursive search for executables..."); + log::info!("Performing recursive search for executables..."); match self.find_any_executable_recursive(dest_dir, 0).await { Ok(path) => { - println!("Found executable via recursive search: {}", path.display()); + log::info!("Found executable via recursive search: {}", path.display()); Ok(path) } Err(e) => { // List all files in the directory for debugging - println!("Failed to find executable. Directory contents:"); + log::info!("Failed to find executable. Directory contents:"); if let Ok(entries) = fs::read_dir(dest_dir) { for entry in entries.flatten() { let path = entry.path(); @@ -1116,7 +1116,7 @@ impl Extractor { } else { false }; - println!(" {} (executable: {})", path.display(), is_exec); + log::info!(" {} (executable: {})", path.display(), is_exec); } } Err( @@ -1220,7 +1220,7 @@ impl Extractor { || name_lower.contains("camoufox") || file_name.ends_with(".AppImage") { - println!( + log::info!( "Found priority executable at depth {}: {}", depth, path.display() @@ -1262,7 +1262,7 @@ impl Extractor { a_name.len().cmp(&b_name.len()) }); - println!( + log::info!( "Found potential executable at depth {}: {}", depth, potential_executables[0].display() diff --git a/src-tauri/src/group_manager.rs b/src-tauri/src/group_manager.rs index ce92a0b..c842582 100644 --- a/src-tauri/src/group_manager.rs +++ b/src-tauri/src/group_manager.rs @@ -120,7 +120,7 @@ impl GroupManager { // Emit event for reactive UI updates if let Err(e) = app_handle.emit("groups-changed", ()) { - eprintln!("Failed to emit groups-changed event: {e}"); + log::error!("Failed to emit groups-changed event: {e}"); } Ok(group) @@ -156,7 +156,7 @@ impl GroupManager { // Emit event for reactive UI updates if let Err(e) = app_handle.emit("groups-changed", ()) { - eprintln!("Failed to emit groups-changed event: {e}"); + log::error!("Failed to emit groups-changed event: {e}"); } Ok(updated_group) @@ -180,7 +180,7 @@ impl GroupManager { // Emit event for reactive UI updates if let Err(e) = app_handle.emit("groups-changed", ()) { - eprintln!("Failed to emit groups-changed event: {e}"); + log::error!("Failed to emit groups-changed event: {e}"); } Ok(()) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 768f2e0..18b1be2 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -3,6 +3,7 @@ use std::env; use std::sync::Mutex; use tauri::{Emitter, Manager, Runtime, WebviewUrl, WebviewWindow, WebviewWindowBuilder}; use tauri_plugin_deep_link::DeepLinkExt; +use tauri_plugin_log::{Target, TargetKind}; // Store pending URLs that need to be handled when the window is ready static PENDING_URLS: Mutex> = Mutex::new(Vec::new()); @@ -152,7 +153,7 @@ async fn warm_up_nodecar(app: tauri::AppHandle) -> Result<(), String> { match timeout(Duration::from_secs(120), exec_future).await { Ok(Ok(_output)) => { let duration = start_time.elapsed(); - println!( + log::info!( "Nodecar warm-up (frontend-triggered) completed in {:.2}s", duration.as_secs_f64() ); @@ -165,11 +166,11 @@ async fn warm_up_nodecar(app: tauri::AppHandle) -> Result<(), String> { #[tauri::command] async fn handle_url_open(app: tauri::AppHandle, url: String) -> Result<(), String> { - println!("handle_url_open called with URL: {url}"); + log::info!("handle_url_open called with URL: {url}"); // Check if the main window exists and is ready if let Some(window) = app.get_webview_window("main") { - println!("Main window exists"); + log::debug!("Main window exists"); // Try to show and focus the window first let _ = window.show(); @@ -181,7 +182,7 @@ async fn handle_url_open(app: tauri::AppHandle, url: String) -> Result<(), Strin .map_err(|e| format!("Failed to emit URL open event: {e}"))?; } else { // Window doesn't exist yet - add to pending URLs - println!("Main window doesn't exist, adding URL to pending list"); + log::debug!("Main window doesn't exist, adding URL to pending list"); let mut pending = PENDING_URLS.lock().unwrap(); pending.push(url); } @@ -259,14 +260,49 @@ pub fn run() { let startup_url = args.iter().find(|arg| arg.starts_with("http")).cloned(); if let Some(url) = startup_url.clone() { - println!("Found startup URL in command line: {url}"); + log::info!("Found startup URL in command line: {url}"); let mut pending = PENDING_URLS.lock().unwrap(); pending.push(url.clone()); } + // Configure logging plugin with separate logs for dev and production + let log_file_name = if cfg!(debug_assertions) { + "DonutBrowserDev" + } else { + "DonutBrowser" + }; + tauri::Builder::default() + .plugin( + tauri_plugin_log::Builder::new() + .clear_targets() // Clear default targets to avoid duplicates + .target(Target::new(TargetKind::Stdout)) + .target(Target::new(TargetKind::Webview)) + .target(Target::new(TargetKind::LogDir { + file_name: Some(log_file_name.to_string()), + })) + .max_file_size(100_000) // 100KB + .level(log::LevelFilter::Info) + .format(|out, message, record| { + use chrono::Local; + let now = Local::now(); + let timestamp = format!( + "{}.{:03}", + now.format("%Y-%m-%d %H:%M:%S"), + now.timestamp_subsec_millis() + ); + out.finish(format_args!( + "[{}][{}][{}] {}", + timestamp, + record.target(), + record.level(), + message + )) + }) + .build(), + ) .plugin(tauri_plugin_single_instance::init(|_, args, _cwd| { - println!("Single instance triggered with args: {args:?}"); + log::info!("Single instance triggered with args: {args:?}"); })) .plugin(tauri_plugin_deep_link::init()) .plugin(tauri_plugin_fs::init()) @@ -293,7 +329,7 @@ pub fn run() { #[cfg(target_os = "macos")] { if let Err(e) = window.set_transparent_titlebar(true) { - eprintln!("Failed to set transparent titlebar: {e}"); + log::warn!("Failed to set transparent titlebar: {e}"); } } @@ -304,7 +340,7 @@ pub fn run() { { // For Windows, register all deep links at runtime if let Err(e) = app.deep_link().register_all() { - eprintln!("Failed to register deep links: {e}"); + log::warn!("Failed to register deep links: {e}"); } } @@ -312,7 +348,7 @@ pub fn run() { { // On macOS, try to register deep links for development builds if let Err(e) = app.deep_link().register_all() { - eprintln!( + log::debug!( "Note: Deep link registration failed on macOS (this is normal for production): {e}" ); } @@ -322,11 +358,11 @@ pub fn run() { let handle = handle.clone(); move |event| { let urls = event.urls(); - println!("Deep link event received with {} URLs", urls.len()); + log::info!("Deep link event received with {} URLs", urls.len()); for url in urls { let url_string = url.to_string(); - println!("Deep link received: {url_string}"); + log::info!("Deep link received: {url_string}"); // Clone the handle for each async task let handle_clone = handle.clone(); @@ -334,7 +370,7 @@ pub fn run() { // Handle the URL asynchronously tauri::async_runtime::spawn(async move { if let Err(e) = handle_url_open(handle_clone, url_string.clone()).await { - eprintln!("Failed to handle deep link URL: {e}"); + log::error!("Failed to handle deep link URL: {e}"); } }); } @@ -344,9 +380,9 @@ pub fn run() { if let Some(startup_url) = startup_url { let handle_clone = handle.clone(); tauri::async_runtime::spawn(async move { - println!("Processing startup URL from command line: {startup_url}"); + log::info!("Processing startup URL from command line: {startup_url}"); if let Err(e) = handle_url_open(handle_clone, startup_url.clone()).await { - eprintln!("Failed to handle startup URL: {e}"); + log::error!("Failed to handle startup URL: {e}"); } }); } @@ -366,7 +402,7 @@ pub fn run() { { let updater_guard = version_updater.lock().await; if let Err(e) = updater_guard.start_background_updates().await { - eprintln!("Failed to start background updates: {e}"); + log::error!("Failed to start background updates: {e}"); } } }); @@ -397,9 +433,9 @@ pub fn run() { }; for url in pending_urls { - println!("Processing pending URL: {url}"); + log::info!("Processing pending URL: {url}"); if let Err(e) = handle_url_open(handle_pending.clone(), url).await { - eprintln!("Failed to handle pending URL: {e}"); + log::error!("Failed to handle pending URL: {e}"); } } }); @@ -414,35 +450,36 @@ pub fn run() { let registry = crate::downloaded_browsers_registry::DownloadedBrowsersRegistry::instance(); if let Err(e) = registry.cleanup_unused_binaries() { - eprintln!("Periodic cleanup failed: {e}"); + log::error!("Periodic cleanup failed: {e}"); } else { - println!("Periodic cleanup completed successfully"); + log::debug!("Periodic cleanup completed successfully"); } } }); let app_handle_update = app.handle().clone(); tauri::async_runtime::spawn(async move { - println!("Starting app update check at startup..."); + log::info!("Starting app update check at startup..."); let updater = app_auto_updater::AppAutoUpdater::instance(); match updater.check_for_updates().await { Ok(Some(update_info)) => { - println!( + log::info!( "App update available: {} -> {}", - update_info.current_version, update_info.new_version + update_info.current_version, + update_info.new_version ); // Emit update available event to the frontend if let Err(e) = app_handle_update.emit("app-update-available", &update_info) { - eprintln!("Failed to emit app update event: {e}"); + log::error!("Failed to emit app update event: {e}"); } else { - println!("App update event emitted successfully"); + log::debug!("App update event emitted successfully"); } } Ok(None) => { - println!("No app updates available"); + log::debug!("No app updates available"); } Err(e) => { - eprintln!("Failed to check for app updates: {e}"); + log::error!("Failed to check for app updates: {e}"); } } }); @@ -461,7 +498,7 @@ pub fn run() { // Cleanup completed silently } Err(e) => { - eprintln!("Error during Camoufox cleanup: {e}"); + log::error!("Error during Camoufox cleanup: {e}"); } } } @@ -476,22 +513,24 @@ pub fn run() { let geoip_downloader = crate::geoip_downloader::GeoIPDownloader::instance(); match geoip_downloader.check_missing_geoip_database() { Ok(true) => { - println!("GeoIP database is missing for Camoufox profiles, downloading at startup..."); + log::info!( + "GeoIP database is missing for Camoufox profiles, downloading at startup..." + ); let geoip_downloader = GeoIPDownloader::instance(); if let Err(e) = geoip_downloader .download_geoip_database(&app_handle_geoip) .await { - eprintln!("Failed to download GeoIP database at startup: {e}"); + log::error!("Failed to download GeoIP database at startup: {e}"); } else { - println!("GeoIP database downloaded successfully at startup"); + log::info!("GeoIP database downloaded successfully at startup"); } } Ok(false) => { // No Camoufox profiles or GeoIP database already available } Err(e) => { - eprintln!("Failed to check GeoIP database status at startup: {e}"); + log::error!("Failed to check GeoIP database status at startup: {e}"); } } }); @@ -510,14 +549,14 @@ pub fn run() { { Ok(dead_pids) => { if !dead_pids.is_empty() { - println!( + log::info!( "Cleaned up proxies for {} dead browser processes", dead_pids.len() ); } } Err(e) => { - eprintln!("Error during proxy cleanup: {e}"); + log::error!("Error during proxy cleanup: {e}"); } } } @@ -538,7 +577,7 @@ pub fn run() { let profiles = match runner.profile_manager.list_profiles() { Ok(p) => p, Err(e) => { - println!("Warning: Failed to list profiles in status checker: {e}"); + log::warn!("Failed to list profiles in status checker: {e}"); continue; } }; @@ -558,9 +597,11 @@ pub fn run() { // Only emit event if state actually changed if last_state != is_running { - println!( + log::debug!( "Status checker detected change for profile {}: {} -> {}", - profile.name, last_state, is_running + profile.name, + last_state, + is_running ); #[derive(serde::Serialize)] @@ -575,11 +616,12 @@ pub fn run() { }; if let Err(e) = app_handle_status.emit("profile-running-changed", &payload) { - println!("Warning: Failed to emit profile running changed event: {e}"); + log::warn!("Failed to emit profile running changed event: {e}"); } else { - println!( + log::debug!( "Status checker emitted profile-running-changed event for {}: running={}", - profile.name, is_running + profile.name, + is_running ); } @@ -590,10 +632,7 @@ pub fn run() { } } Err(e) => { - println!( - "Warning: Status check failed for profile {}: {}", - profile.name, e - ); + log::warn!("Status check failed for profile {}: {}", profile.name, e); continue; } } @@ -609,12 +648,12 @@ pub fn run() { match crate::settings_manager::get_app_settings(app_handle_api.clone()).await { Ok(settings) => { if settings.api_enabled { - println!("API is enabled in settings, starting API server..."); + log::info!("API is enabled in settings, starting API server..."); match crate::api_server::start_api_server_internal(settings.api_port, &app_handle_api) .await { Ok(port) => { - println!("API server started successfully on port {port}"); + log::info!("API server started successfully on port {port}"); // Emit success toast to frontend if let Err(e) = app_handle_api.emit( "show-toast", @@ -625,11 +664,11 @@ pub fn run() { description: Some(format!("API server running on port {port}")), }, ) { - eprintln!("Failed to emit API start toast: {e}"); + log::error!("Failed to emit API start toast: {e}"); } } Err(e) => { - eprintln!("Failed to start API server at startup: {e}"); + log::error!("Failed to start API server at startup: {e}"); // Emit error toast to frontend if let Err(toast_err) = app_handle_api.emit( "show-toast", @@ -640,14 +679,14 @@ pub fn run() { description: Some(format!("Error: {e}")), }, ) { - eprintln!("Failed to emit API error toast: {toast_err}"); + log::error!("Failed to emit API error toast: {toast_err}"); } } } } } Err(e) => { - eprintln!("Failed to load app settings for API startup: {e}"); + log::error!("Failed to load app settings for API startup: {e}"); } } }); diff --git a/src-tauri/src/platform_browser.rs b/src-tauri/src/platform_browser.rs index 7dd7a43..34b92be 100644 --- a/src-tauri/src/platform_browser.rs +++ b/src-tauri/src/platform_browser.rs @@ -47,7 +47,7 @@ pub mod macos { executable_path: &std::path::Path, args: &[String], ) -> Result> { - println!("Launching browser on macOS: {executable_path:?} with args: {args:?}"); + log::info!("Launching browser on macOS: {executable_path:?} with args: {args:?}"); // If the executable is inside an app bundle, launch via Launch Services so // macOS recognizes the real application for privacy permissions (e.g. Screen Recording). // This ensures TCC prompts are attributed to the browser app, not our launcher. @@ -93,7 +93,7 @@ pub mod macos { let profile_data_path = profile.get_profile_data_path(profiles_dir); // First try: Use Firefox remote command - println!("Trying Firefox remote command for PID: {pid}"); + log::info!("Trying Firefox remote command for PID: {pid}"); let browser = create_browser(browser_type); if let Ok(executable_path) = browser.get_executable_path(browser_dir) { let remote_args = vec![ @@ -107,17 +107,17 @@ pub mod macos { match remote_output { Ok(output) if output.status.success() => { - println!("Firefox remote command succeeded"); + log::info!("Firefox remote command succeeded"); return Ok(()); } Ok(output) => { let stderr = String::from_utf8_lossy(&output.stderr); - println!( + log::info!( "Firefox remote command failed with stderr: {stderr}, trying AppleScript fallback" ); } Err(e) => { - println!("Firefox remote command error: {e}, trying AppleScript fallback"); + log::info!("Firefox remote command error: {e}, trying AppleScript fallback"); } } } @@ -195,12 +195,12 @@ end try "# ); - println!("Executing AppleScript fallback for Firefox-based browser (PID: {pid})..."); + log::info!("Executing AppleScript fallback for Firefox-based browser (PID: {pid})..."); let output = Command::new("osascript").args(["-e", &script]).output()?; if !output.status.success() { let error_msg = String::from_utf8_lossy(&output.stderr); - println!("AppleScript failed: {error_msg}"); + log::info!("AppleScript failed: {error_msg}"); return Err( format!( "Both Firefox remote command and AppleScript failed. AppleScript error: {error_msg}" @@ -208,7 +208,7 @@ end try .into(), ); } else { - println!("AppleScript succeeded"); + log::info!("AppleScript succeeded"); } Ok(()) @@ -217,13 +217,13 @@ end try pub async fn kill_browser_process_impl( pid: u32, ) -> Result<(), Box> { - println!("Attempting to kill browser process with PID: {pid}"); + log::info!("Attempting to kill browser process with PID: {pid}"); // For Chromium-based browsers, use immediate aggressive termination // Chromium browsers are notoriously difficult to kill on macOS due to process spawning // Step 1: Immediate SIGKILL on main process (no graceful shutdown for Chromium) - println!("Starting immediate SIGKILL for PID: {pid}"); + log::info!("Starting immediate SIGKILL for PID: {pid}"); let _ = Command::new("kill") .args(["-KILL", &pid.to_string()]) .output(); @@ -261,7 +261,7 @@ end try // Check if main process still exists if system.process(Pid::from(pid as usize)).is_some() { - println!("Main process {pid} still running, using pattern-based termination"); + log::info!("Main process {pid} still running, using pattern-based termination"); // Kill by common Chromium process patterns let chromium_patterns = [ @@ -302,7 +302,7 @@ end try if system.process(Pid::from(pid as usize)).is_some() { // Last resort: try system kill command with different signals - println!("Process {pid} extremely persistent, trying system-level termination"); + log::info!("Process {pid} extremely persistent, trying system-level termination"); let _ = Command::new("/bin/kill").args(["-KILL", &pid_str]).output(); @@ -322,12 +322,12 @@ end try let system = System::new_all(); if system.process(Pid::from(pid as usize)).is_some() { - println!("WARNING: Process {pid} could not be terminated despite aggressive attempts"); + log::info!("WARNING: Process {pid} could not be terminated despite aggressive attempts"); // Don't return error - let the UI update anyway since we tried everything } } - println!("Aggressive browser termination completed for PID: {pid}"); + log::info!("Aggressive browser termination completed for PID: {pid}"); Ok(()) } @@ -335,11 +335,11 @@ end try async fn kill_chromium_process_tree_aggressive( pid: u32, ) -> Result<(), Box> { - println!("Killing comprehensive process tree for PID: {pid}"); + log::info!("Killing comprehensive process tree for PID: {pid}"); // Get all descendant processes using recursive process tree discovery let descendant_pids = get_all_descendant_pids(pid).await; - println!( + log::info!( "Found {} descendant processes to terminate", descendant_pids.len() ); @@ -347,7 +347,7 @@ end try // Kill all descendants first (reverse order - children before parents) for &desc_pid in descendant_pids.iter().rev() { if desc_pid != pid { - println!("Terminating descendant process: {desc_pid}"); + log::info!("Terminating descendant process: {desc_pid}"); let _ = Command::new("kill") .args(["-KILL", &desc_pid.to_string()]) .output(); @@ -381,7 +381,7 @@ end try // Helper function to kill all Chromium-related processes by name patterns async fn kill_all_chromium_processes_by_name( ) -> Result<(), Box> { - println!("Killing all Chromium-related processes by name patterns"); + log::info!("Killing all Chromium-related processes by name patterns"); let chromium_patterns = [ "Chrome", @@ -444,10 +444,10 @@ end try ) -> Result<(), Box> { let pid = profile.process_id.unwrap(); - println!("Opening URL in TOR/Mullvad browser using file-based approach (PID: {pid})"); + log::info!("Opening URL in TOR/Mullvad browser using file-based approach (PID: {pid})"); // Method 1: Try using a temporary HTML file approach - println!("Attempting file-based URL opening for TOR/Mullvad browser"); + log::info!("Attempting file-based URL opening for TOR/Mullvad browser"); let temp_dir = std::env::temp_dir(); let temp_file_name = format!("donut_browser_url_{}.html", std::process::id()); @@ -472,7 +472,7 @@ end try match std::fs::write(&temp_file_path, html_content) { Ok(()) => { - println!("Created temporary HTML file: {temp_file_path:?}"); + log::info!("Created temporary HTML file: {temp_file_path:?}"); let browser = create_browser(browser_type.clone()); if let Ok(executable_path) = browser.get_executable_path(browser_dir) { @@ -493,15 +493,15 @@ end try match open_result { Ok(output) if output.status.success() => { - println!("Successfully opened URL using file-based approach"); + log::info!("Successfully opened URL using file-based approach"); return Ok(()); } Ok(output) => { let stderr = String::from_utf8_lossy(&output.stderr); - println!("File-based approach failed: {stderr}"); + log::info!("File-based approach failed: {stderr}"); } Err(e) => { - println!("File-based approach error: {e}"); + log::info!("File-based approach error: {e}"); } } } @@ -509,12 +509,12 @@ end try let _ = std::fs::remove_file(&temp_file_path); } Err(e) => { - println!("Failed to create temporary HTML file: {e}"); + log::info!("Failed to create temporary HTML file: {e}"); } } // Method 2: Try using the 'open' command directly with the URL - println!("Attempting direct URL opening with 'open' command"); + log::info!("Attempting direct URL opening with 'open' command"); let browser = create_browser(browser_type.clone()); if let Ok(executable_path) = browser.get_executable_path(browser_dir) { @@ -524,15 +524,15 @@ end try match direct_open_result { Ok(output) if output.status.success() => { - println!("Successfully opened URL using direct 'open' command"); + log::info!("Successfully opened URL using direct 'open' command"); return Ok(()); } Ok(output) => { let stderr = String::from_utf8_lossy(&output.stderr); - println!("Direct 'open' command failed: {stderr}"); + log::info!("Direct 'open' command failed: {stderr}"); } Err(e) => { - println!("Direct 'open' command error: {e}"); + log::info!("Direct 'open' command error: {e}"); } } } @@ -561,7 +561,7 @@ end try let pid = profile.process_id.unwrap(); // First, try using the browser's built-in URL opening capability - println!("Trying Chromium URL opening for PID: {pid}"); + log::info!("Trying Chromium URL opening for PID: {pid}"); let browser = create_browser(browser_type); if let Ok(executable_path) = browser.get_executable_path(browser_dir) { @@ -575,15 +575,15 @@ end try match remote_output { Ok(output) if output.status.success() => { - println!("Chromium URL opening succeeded"); + log::info!("Chromium URL opening succeeded"); return Ok(()); } Ok(output) => { let stderr = String::from_utf8_lossy(&output.stderr); - println!("Chromium URL opening failed: {stderr}, trying AppleScript"); + log::info!("Chromium URL opening failed: {stderr}, trying AppleScript"); } Err(e) => { - println!("Chromium URL opening error: {e}, trying AppleScript"); + log::info!("Chromium URL opening error: {e}, trying AppleScript"); } } } @@ -661,17 +661,17 @@ end try "# ); - println!("Executing AppleScript for Chromium-based browser (PID: {pid})..."); + log::info!("Executing AppleScript for Chromium-based browser (PID: {pid})..."); let output = Command::new("osascript").args(["-e", &script]).output()?; if !output.status.success() { let error_msg = String::from_utf8_lossy(&output.stderr); - println!("AppleScript failed: {error_msg}"); + log::info!("AppleScript failed: {error_msg}"); return Err( format!("Failed to open URL in existing Chromium-based browser: {error_msg}").into(), ); } else { - println!("AppleScript succeeded"); + log::info!("AppleScript succeeded"); } Ok(()) @@ -722,9 +722,10 @@ pub mod windows { executable_path: &std::path::Path, args: &[String], ) -> Result> { - println!( + log::info!( "Launching browser on Windows: {:?} with args: {:?}", - executable_path, args + executable_path, + args ); // Check if the executable exists @@ -763,7 +764,7 @@ pub mod windows { .spawn() .map_err(|e| format!("Failed to launch browser process: {}", e))?; - println!( + log::info!( "Successfully launched browser process with PID: {}", child.id() ); @@ -930,7 +931,7 @@ pub mod windows { let system = System::new_all(); if let Some(process) = system.process(Pid::from(pid as usize)) { if process.kill() { - println!("Successfully killed browser process with PID: {pid}"); + log::info!("Successfully killed browser process with PID: {pid}"); return Ok(()); } } @@ -946,7 +947,7 @@ pub mod windows { match output { Ok(result) => { if result.status.success() { - println!("Successfully killed browser process with PID: {pid} using taskkill"); + log::info!("Successfully killed browser process with PID: {pid} using taskkill"); Ok(()) } else { Err( @@ -981,9 +982,10 @@ pub mod linux { executable_path: &std::path::Path, args: &[String], ) -> Result> { - println!( + log::info!( "Launching browser on Linux: {:?} with args: {:?}", - executable_path, args + executable_path, + args ); // Check if the executable exists and is executable @@ -1047,7 +1049,7 @@ pub mod linux { // Set the combined LD_LIBRARY_PATH if !ld_library_path.is_empty() { cmd.env("LD_LIBRARY_PATH", ld_library_path.join(":")); - println!("Set LD_LIBRARY_PATH to: {}", ld_library_path.join(":")); + log::info!("Set LD_LIBRARY_PATH to: {}", ld_library_path.join(":")); } } @@ -1064,7 +1066,7 @@ pub mod linux { // Disable GPU acceleration if running in headless environments if std::env::var("DISPLAY").is_err() || std::env::var("WAYLAND_DISPLAY").is_err() { - println!("No display detected, browser may fail to start"); + log::info!("No display detected, browser may fail to start"); } // Attempt to spawn with better error handling for architecture issues @@ -1188,7 +1190,7 @@ pub mod linux { return Err(format!("Process {} not found", pid).into()); } - println!("Successfully killed browser process with PID: {pid}"); + log::info!("Successfully killed browser process with PID: {pid}"); Ok(()) } } diff --git a/src-tauri/src/profile/manager.rs b/src-tauri/src/profile/manager.rs index 0316c2a..6dc78d8 100644 --- a/src-tauri/src/profile/manager.rs +++ b/src-tauri/src/profile/manager.rs @@ -61,7 +61,7 @@ impl ProfileManager { camoufox_config: Option, group_id: Option, ) -> Result> { - println!("Attempting to create profile: {name}"); + log::info!("Attempting to create profile: {name}"); // Check if a profile with this name already exists (case insensitive) let existing_profiles = self.list_profiles()?; @@ -86,7 +86,7 @@ impl ProfileManager { // For Camoufox profiles, generate fingerprint during creation let final_camoufox_config = if browser == "camoufox" { let mut config = camoufox_config.unwrap_or_else(|| { - println!("Creating default Camoufox config for profile: {name}"); + log::info!("Creating default Camoufox config for profile: {name}"); crate::camoufox_manager::CamoufoxConfig::default() }); @@ -110,7 +110,7 @@ impl ProfileManager { let binary_path = browser_dir.join("camoufox"); config.executable_path = Some(binary_path.to_string_lossy().to_string()); - println!("Set Camoufox executable path: {:?}", config.executable_path); + log::info!("Set Camoufox executable path: {:?}", config.executable_path); } // Pass upstream proxy information to config for fingerprint generation @@ -137,7 +137,7 @@ impl ProfileManager { ) }; config.proxy = Some(proxy_url); - println!( + log::info!( "Using upstream proxy for Camoufox fingerprint generation: {}://{}:{}", proxy_settings.proxy_type.to_lowercase(), proxy_settings.host, @@ -148,7 +148,7 @@ impl ProfileManager { // Generate fingerprint if not already provided if config.fingerprint.is_none() { - println!("Generating fingerprint for Camoufox profile: {name}"); + log::info!("Generating fingerprint for Camoufox profile: {name}"); // Use the camoufox launcher to generate the config @@ -174,7 +174,7 @@ impl ProfileManager { { Ok(generated_fingerprint) => { config.fingerprint = Some(generated_fingerprint); - println!("Successfully generated fingerprint for profile: {name}"); + log::info!("Successfully generated fingerprint for profile: {name}"); } Err(e) => { return Err( @@ -183,7 +183,7 @@ impl ProfileManager { } } } else { - println!("Using provided fingerprint for Camoufox profile: {name}"); + log::info!("Using provided fingerprint for Camoufox profile: {name}"); } // Clear the proxy from config after fingerprint generation @@ -217,7 +217,7 @@ impl ProfileManager { return Err(format!("Failed to create profile file for '{name}'").into()); } - println!("Profile '{name}' created successfully with ID: {profile_id}"); + log::info!("Profile '{name}' created successfully with ID: {profile_id}"); // Create user.js with common Firefox preferences and apply proxy settings if provided if let Some(proxy_id_ref) = &proxy_id { @@ -234,7 +234,7 @@ impl ProfileManager { // Emit profile creation event if let Err(e) = app_handle.emit("profiles-changed", ()) { - println!("Warning: Failed to emit profiles-changed event: {e}"); + log::warn!("Warning: Failed to emit profiles-changed event: {e}"); } Ok(profile) @@ -320,7 +320,7 @@ impl ProfileManager { // Emit profile rename event if let Err(e) = app_handle.emit("profiles-changed", ()) { - println!("Warning: Failed to emit profiles-changed event: {e}"); + log::warn!("Warning: Failed to emit profiles-changed event: {e}"); } Ok(profile) @@ -331,7 +331,7 @@ impl ProfileManager { app_handle: &tauri::AppHandle, profile_id: &str, ) -> Result<(), Box> { - println!("Attempting to delete profile with ID: {profile_id}"); + log::info!("Attempting to delete profile with ID: {profile_id}"); // Find the profile by ID let profile_uuid = @@ -354,9 +354,9 @@ impl ProfileManager { // Delete the entire UUID directory (contains both metadata.json and profile data) if profile_uuid_dir.exists() { - println!("Deleting profile directory: {}", profile_uuid_dir.display()); + log::info!("Deleting profile directory: {}", profile_uuid_dir.display()); fs::remove_dir_all(&profile_uuid_dir)?; - println!("Profile directory deleted successfully"); + log::info!("Profile directory deleted successfully"); } // Verify deletion was successful @@ -364,9 +364,10 @@ impl ProfileManager { return Err(format!("Failed to completely delete profile '{}'", profile.name).into()); } - println!( + log::info!( "Profile '{}' (ID: {}) deleted successfully", - profile.name, profile_id + profile.name, + profile_id ); // Rebuild tag suggestions after deletion @@ -376,12 +377,12 @@ impl ProfileManager { // Always perform cleanup after profile deletion to remove unused binaries if let Err(e) = DownloadedBrowsersRegistry::instance().cleanup_unused_binaries() { - println!("Warning: Failed to cleanup unused binaries after profile deletion: {e}"); + log::warn!("Warning: Failed to cleanup unused binaries after profile deletion: {e}"); } // Emit profile deletion event if let Err(e) = app_handle.emit("profiles-changed", ()) { - println!("Warning: Failed to emit profiles-changed event: {e}"); + log::warn!("Warning: Failed to emit profiles-changed event: {e}"); } Ok(()) @@ -434,7 +435,7 @@ impl ProfileManager { // Emit profile update event if let Err(e) = app_handle.emit("profiles-changed", ()) { - println!("Warning: Failed to emit profiles-changed event: {e}"); + log::warn!("Warning: Failed to emit profiles-changed event: {e}"); } Ok(profile) @@ -475,7 +476,7 @@ impl ProfileManager { // Emit profile group assignment event if let Err(e) = app_handle.emit("profiles-changed", ()) { - println!("Warning: Failed to emit profiles-changed event: {e}"); + log::warn!("Warning: Failed to emit profiles-changed event: {e}"); } Ok(()) @@ -515,7 +516,7 @@ impl ProfileManager { // Emit profile tags update event if let Err(e) = app_handle.emit("profiles-changed", ()) { - println!("Warning: Failed to emit profiles-changed event: {e}"); + log::warn!("Warning: Failed to emit profiles-changed event: {e}"); } Ok(profile) @@ -558,7 +559,7 @@ impl ProfileManager { // Emit profile deletion event if let Err(e) = app_handle.emit("profiles-changed", ()) { - println!("Warning: Failed to emit profiles-changed event: {e}"); + log::warn!("Warning: Failed to emit profiles-changed event: {e}"); } Ok(()) @@ -610,14 +611,15 @@ impl ProfileManager { format!("Failed to save profile: {e}").into() })?; - println!( + log::info!( "Camoufox configuration updated for profile '{}' (ID: {}).", - profile.name, profile_id + profile.name, + profile_id ); // Emit profile config update event if let Err(e) = app_handle.emit("profiles-changed", ()) { - println!("Warning: Failed to emit profiles-changed event: {e}"); + log::warn!("Warning: Failed to emit profiles-changed event: {e}"); } Ok(()) @@ -692,12 +694,12 @@ impl ProfileManager { // Emit profile update event so frontend UIs can refresh immediately (e.g. proxy manager) if let Err(e) = app_handle.emit("profile-updated", &profile) { - println!("Warning: Failed to emit profile update event: {e}"); + log::warn!("Warning: Failed to emit profile update event: {e}"); } // Emit general profiles changed event for profile list updates if let Err(e) = app_handle.emit("profiles-changed", ()) { - println!("Warning: Failed to emit profiles-changed event: {e}"); + log::warn!("Warning: Failed to emit profiles-changed event: {e}"); } Ok(profile) @@ -822,7 +824,7 @@ impl ProfileManager { // Found a matching process found_pid = Some(pid.as_u32()); is_running = true; - println!( + log::info!( "Found browser process with PID: {} for profile: {}", pid.as_u32(), profile.name @@ -856,14 +858,14 @@ impl ProfileManager { if merged.process_id != Some(pid) { merged.process_id = Some(pid); if let Err(e) = self.save_profile(&merged) { - println!("Warning: Failed to update profile with new PID: {e}"); + log::warn!("Warning: Failed to update profile with new PID: {e}"); } } } else if merged.process_id.is_some() { // Clear the PID if no process found merged.process_id = None; if let Err(e) = self.save_profile(&merged) { - println!("Warning: Failed to clear profile PID: {e}"); + log::warn!("Warning: Failed to clear profile PID: {e}"); } // Stop any associated proxy immediately when the browser stops @@ -876,7 +878,7 @@ impl ProfileManager { // Emit profile update event to frontend if let Err(e) = app_handle.emit("profile-updated", &merged) { - println!("Warning: Failed to emit profile update event: {e}"); + log::warn!("Warning: Failed to emit profile update event: {e}"); } } @@ -916,17 +918,18 @@ impl ProfileManager { if latest.process_id != camoufox_process.processId { latest.process_id = camoufox_process.processId; if let Err(e) = self.save_profile(&latest) { - println!("Warning: Failed to update Camoufox profile with process info: {e}"); + log::warn!("Warning: Failed to update Camoufox profile with process info: {e}"); } // Emit profile update event to frontend if let Err(e) = app_handle.emit("profile-updated", &latest) { - println!("Warning: Failed to emit profile update event: {e}"); + log::warn!("Warning: Failed to emit profile update event: {e}"); } - println!( + log::info!( "Camoufox process has started for profile '{}' with PID: {:?}", - profile.name, camoufox_process.processId + profile.name, + camoufox_process.processId ); } } @@ -951,7 +954,7 @@ impl ProfileManager { if let Some(old_pid) = latest.process_id { latest.process_id = None; if let Err(e) = self.save_profile(&latest) { - println!("Warning: Failed to clear Camoufox profile process info: {e}"); + log::warn!("Warning: Failed to clear Camoufox profile process info: {e}"); } // Stop any proxy tied to this old PID immediately @@ -961,7 +964,7 @@ impl ProfileManager { // Emit profile update event to frontend if let Err(e) = app_handle.emit("profile-updated", &latest) { - println!("Warning: Failed to emit profile update event: {e}"); + log::warn!("Warning: Failed to emit profile update event: {e}"); } } } @@ -969,7 +972,7 @@ impl ProfileManager { } Err(e) => { // Error checking status, assume not running and clear process ID - println!("Warning: Failed to check Camoufox status via nodecar: {e}"); + log::warn!("Warning: Failed to check Camoufox status via nodecar: {e}"); let profiles_dir = self.get_profiles_dir(); let profile_uuid_dir = profiles_dir.join(profile.id.to_string()); let metadata_file = profile_uuid_dir.join("metadata.json"); @@ -987,7 +990,9 @@ impl ProfileManager { if let Some(old_pid) = latest.process_id { latest.process_id = None; if let Err(e2) = self.save_profile(&latest) { - println!("Warning: Failed to clear Camoufox profile process info after error: {e2}"); + log::warn!( + "Warning: Failed to clear Camoufox profile process info after error: {e2}" + ); } // Best-effort stop of proxy tied to old PID @@ -997,7 +1002,7 @@ impl ProfileManager { // Emit profile update event to frontend if let Err(e3) = app_handle.emit("profile-updated", &latest) { - println!("Warning: Failed to emit profile update event: {e3}"); + log::warn!("Warning: Failed to emit profile update event: {e3}"); } } } @@ -1086,7 +1091,7 @@ impl ProfileManager { // Remove prefs.js if it exists to ensure Firefox reads user.js instead // Firefox may cache proxy settings in prefs.js, so we need to clear it if prefs_js_path.exists() { - println!("Removing prefs.js to ensure Firefox reads updated user.js settings"); + log::info!("Removing prefs.js to ensure Firefox reads updated user.js settings"); let _ = fs::remove_file(&prefs_js_path); } @@ -1109,16 +1114,19 @@ impl ProfileManager { let proxy_url = if let Some(internal) = internal_proxy { // Use internal proxy (local proxy) as the primary proxy // This is the local proxy that forwards to the upstream proxy - println!( + log::info!( "Applying local proxy settings to Firefox profile: {}:{}", - internal.host, internal.port + internal.host, + internal.port ); format!("HTTP {}:{}", internal.host, internal.port) } else { // Use user-configured proxy directly (upstream proxy) - println!( + log::info!( "Applying upstream proxy settings to Firefox profile: {}:{} ({})", - proxy.host, proxy.port, proxy.proxy_type + proxy.host, + proxy.port, + proxy.proxy_type ); match proxy.proxy_type.as_str() { "http" => format!("HTTP {}:{}", proxy.host, proxy.port), @@ -1136,13 +1144,13 @@ impl ProfileManager { // Save PAC file in UUID directory let pac_path = uuid_dir.join("proxy.pac"); - println!( + log::info!( "Creating PAC file at: {} with proxy: {}", pac_path.display(), proxy_url ); fs::write(&pac_path, &pac_content)?; - println!( + log::info!( "Created PAC file at: {} with content: {}", pac_path.display(), pac_content @@ -1162,8 +1170,8 @@ impl ProfileManager { format!("file://{}", pac_path_absolute.to_string_lossy()) }; - println!("PAC file path (absolute): {}", pac_path_absolute.display()); - println!("PAC file URL for Firefox: {}", pac_url); + log::info!("PAC file path (absolute): {}", pac_path_absolute.display()); + log::info!("PAC file URL for Firefox: {}", pac_url); preferences.extend([ "user_pref(\"network.proxy.type\", 2);".to_string(), @@ -1183,16 +1191,18 @@ impl ProfileManager { // Write settings to user.js file let user_js_content = preferences.join("\n"); fs::write(user_js_path, &user_js_content)?; - println!("Updated user.js with proxy settings. PAC URL: {}", pac_url); + log::info!("Updated user.js with proxy settings. PAC URL: {}", pac_url); if let Some(internal) = internal_proxy { - println!( + log::info!( "Firefox will use LOCAL proxy: {}:{} (which forwards to upstream)", - internal.host, internal.port + internal.host, + internal.port ); } else { - println!( + log::info!( "Firefox will use UPSTREAM proxy directly: {}:{}", - proxy.host, proxy.port + proxy.host, + proxy.port ); } diff --git a/src-tauri/src/profile_importer.rs b/src-tauri/src/profile_importer.rs index 32686ce..3c61b25 100644 --- a/src-tauri/src/profile_importer.rs +++ b/src-tauri/src/profile_importer.rs @@ -566,7 +566,7 @@ impl ProfileImporter { // Save the profile metadata self.profile_manager.save_profile(&profile)?; - println!( + log::info!( "Successfully imported profile '{}' from '{}'", new_profile_name, source_path.display() diff --git a/src-tauri/src/proxy_manager.rs b/src-tauri/src/proxy_manager.rs index 191661f..59eb82b 100644 --- a/src-tauri/src/proxy_manager.rs +++ b/src-tauri/src/proxy_manager.rs @@ -85,7 +85,7 @@ impl ProxyManager { // Load stored proxies on initialization if let Err(e) = manager.load_stored_proxies() { - eprintln!("Warning: Failed to load stored proxies: {e}"); + log::warn!("Failed to load stored proxies: {e}"); } manager @@ -222,11 +222,11 @@ impl ProxyManager { let proxies_dir = self.get_proxies_dir(); if !proxies_dir.exists() { - eprintln!("Proxies directory does not exist: {:?}", proxies_dir); + log::debug!("Proxies directory does not exist: {:?}", proxies_dir); return Ok(()); // No proxies directory yet } - eprintln!("Loading stored proxies from: {:?}", proxies_dir); + log::debug!("Loading stored proxies from: {:?}", proxies_dir); let mut stored_proxies = self.stored_proxies.lock().unwrap(); let mut loaded_count = 0; @@ -242,18 +242,19 @@ impl ProxyManager { Ok(content) => { match serde_json::from_str::(&content) { Ok(proxy) => { - eprintln!("Loaded stored proxy: {} ({})", proxy.name, proxy.id); + log::debug!("Loaded stored proxy: {} ({})", proxy.name, proxy.id); stored_proxies.insert(proxy.id.clone(), proxy); loaded_count += 1; } Err(e) => { // Check if this is a ProxyConfig file (from proxy_storage.rs) - skip it if serde_json::from_str::(&content).is_ok() { - eprintln!("Skipping ProxyConfig file (not a StoredProxy): {:?}", path); + log::debug!("Skipping ProxyConfig file (not a StoredProxy): {:?}", path); } else { - eprintln!( + log::warn!( "Failed to parse proxy file {:?} as StoredProxy: {}", - path, e + path, + e ); error_count += 1; } @@ -261,16 +262,17 @@ impl ProxyManager { } } Err(e) => { - eprintln!("Failed to read proxy file {:?}: {}", path, e); + log::warn!("Failed to read proxy file {:?}: {}", path, e); error_count += 1; } } } } - eprintln!( + log::info!( "Loaded {} stored proxies ({} errors)", - loaded_count, error_count + loaded_count, + error_count ); Ok(()) } @@ -321,12 +323,12 @@ impl ProxyManager { } if let Err(e) = self.save_proxy(&stored_proxy) { - eprintln!("Warning: Failed to save proxy: {e}"); + log::warn!("Failed to save proxy: {e}"); } // Emit event for reactive UI updates if let Err(e) = app_handle.emit("proxies-changed", ()) { - eprintln!("Failed to emit proxies-changed event: {e}"); + log::error!("Failed to emit proxies-changed event: {e}"); } Ok(stored_proxy) @@ -388,12 +390,12 @@ impl ProxyManager { }; if let Err(e) = self.save_proxy(&updated_proxy) { - eprintln!("Warning: Failed to save proxy: {e}"); + log::warn!("Failed to save proxy: {e}"); } // Emit event for reactive UI updates if let Err(e) = app_handle.emit("proxies-changed", ()) { - eprintln!("Failed to emit proxies-changed event: {e}"); + log::error!("Failed to emit proxies-changed event: {e}"); } Ok(updated_proxy) @@ -413,12 +415,12 @@ impl ProxyManager { } if let Err(e) = self.delete_proxy_file(proxy_id) { - eprintln!("Warning: Failed to delete proxy file: {e}"); + log::warn!("Failed to delete proxy file: {e}"); } // Emit event for reactive UI updates if let Err(e) = app_handle.emit("proxies-changed", ()) { - eprintln!("Failed to emit proxies-changed event: {e}"); + log::error!("Failed to emit proxies-changed event: {e}"); } Ok(()) @@ -835,7 +837,7 @@ impl ProxyManager { if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); - eprintln!("Proxy stop error: {stderr}"); + log::warn!("Proxy stop error: {stderr}"); // We still return Ok since we've already removed the proxy from our tracking } @@ -851,7 +853,7 @@ impl ProxyManager { // Emit event for reactive UI updates if let Err(e) = app_handle.emit("proxies-changed", ()) { - eprintln!("Failed to emit proxies-changed event: {e}"); + log::error!("Failed to emit proxies-changed event: {e}"); } Ok(()) @@ -890,13 +892,13 @@ impl ProxyManager { }; for dead_pid in &dead_pids { - println!("Cleaning up proxy for dead browser process PID: {dead_pid}"); + log::info!("Cleaning up proxy for dead browser process PID: {dead_pid}"); let _ = self.stop_proxy(app_handle.clone(), *dead_pid).await; } // Emit event for reactive UI updates if let Err(e) = app_handle.emit("proxies-changed", ()) { - eprintln!("Failed to emit proxies-changed event: {e}"); + log::error!("Failed to emit proxies-changed event: {e}"); } Ok(dead_pids) diff --git a/src-tauri/src/proxy_runner.rs b/src-tauri/src/proxy_runner.rs index e37256b..b071eaa 100644 --- a/src-tauri/src/proxy_runner.rs +++ b/src-tauri/src/proxy_runner.rs @@ -47,7 +47,7 @@ pub async fn start_proxy_process( { let log_path = std::path::PathBuf::from("/tmp").join(format!("donut-proxy-{}.log", id)); if let Ok(file) = std::fs::File::create(&log_path) { - eprintln!("Proxy worker stderr will be logged to: {:?}", log_path); + log::error!("Proxy worker stderr will be logged to: {:?}", log_path); cmd.stderr(Stdio::from(file)); } else { cmd.stderr(Stdio::null()); diff --git a/src-tauri/src/proxy_server.rs b/src-tauri/src/proxy_server.rs index 6d092d3..e06568a 100644 --- a/src-tauri/src/proxy_server.rs +++ b/src-tauri/src/proxy_server.rs @@ -105,7 +105,7 @@ async fn handle_connect( return Ok(response); } Err(e) => { - eprintln!("Failed to connect to {}: {}", target_addr, e); + log::error!("Failed to connect to {}: {}", target_addr, e); let mut response = Response::new(Full::new(Bytes::from(format!("Connection failed: {}", e)))); *response.status_mut() = StatusCode::BAD_GATEWAY; @@ -135,7 +135,7 @@ async fn handle_connect( Ok(response) } Err(e) => { - eprintln!("HTTP proxy CONNECT failed: {}", e); + log::error!("HTTP proxy CONNECT failed: {}", e); let mut response = Response::new(Full::new(Bytes::from(format!( "Proxy connection failed: {}", e @@ -173,7 +173,7 @@ async fn handle_connect( Ok(response) } Err(e) => { - eprintln!("SOCKS connection failed: {}", e); + log::error!("SOCKS connection failed: {}", e); let mut response = Response::new(Full::new(Bytes::from(format!( "SOCKS connection failed: {}", e @@ -306,7 +306,7 @@ async fn handle_http( match build_reqwest_client_with_proxy(upstream) { Ok(c) => c, Err(e) => { - eprintln!("Failed to create proxy client: {}", e); + log::error!("Failed to create proxy client: {}", e); let mut response = Response::new(Full::new(Bytes::from(format!( "Proxy configuration error: {}", e @@ -385,7 +385,7 @@ async fn handle_http( Ok(hyper_response) } Err(e) => { - eprintln!("Request failed: {}", e); + log::error!("Request failed: {}", e); let mut response = Response::new(Full::new(Bytes::from(format!("Request failed: {}", e)))); *response.status_mut() = StatusCode::BAD_GATEWAY; Ok(response) @@ -426,7 +426,7 @@ fn build_reqwest_client_with_proxy( } pub async fn run_proxy_server(config: ProxyConfig) -> Result<(), Box> { - eprintln!( + log::error!( "Proxy worker starting, looking for config id: {}", config.id ); @@ -435,28 +435,30 @@ pub async fn run_proxy_server(config: ProxyConfig) -> Result<(), Box c, None => { - eprintln!("Config not found for id: {}", config.id); + log::error!("Config not found for id: {}", config.id); return Err("Config not found".into()); } }; - eprintln!( + log::error!( "Found config: id={}, port={:?}, upstream={}", - config.id, config.local_port, config.upstream_url + config.id, + config.local_port, + config.upstream_url ); - eprintln!("Starting proxy server for config id: {}", config.id); + log::error!("Starting proxy server for config id: {}", config.id); // Determine the bind address let bind_addr = SocketAddr::from(([127, 0, 0, 1], config.local_port.unwrap_or(0))); - eprintln!("Attempting to bind proxy server to {}", bind_addr); + log::error!("Attempting to bind proxy server to {}", bind_addr); // Bind to the port let listener = TcpListener::bind(bind_addr).await?; let actual_port = listener.local_addr()?.port(); - eprintln!("Successfully bound to port {}", actual_port); + log::error!("Successfully bound to port {}", actual_port); // Update config with actual port and local_url let mut updated_config = config.clone(); @@ -464,12 +466,12 @@ pub async fn run_proxy_server(config: ProxyConfig) -> Result<(), Box Result<(), Box Result<(), Box Result<(), Box Result<(), Box { - eprintln!("Error accepting connection: {:?}", e); + log::error!("Error accepting connection: {:?}", e); // Continue accepting connections even if one fails // Add a small delay to avoid busy-waiting on errors tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; @@ -689,24 +691,24 @@ async fn handle_connect_from_buffer( .await?; client_stream.flush().await?; - eprintln!("DEBUG: Sent 200 Connection Established response, starting tunnel"); + log::error!("DEBUG: Sent 200 Connection Established response, starting tunnel"); // Now tunnel data bidirectionally // Split streams for bidirectional copying let (mut client_read, mut client_write) = tokio::io::split(client_stream); let (mut target_read, mut target_write) = tokio::io::split(target_stream); - eprintln!("DEBUG: Starting bidirectional tunnel"); + log::error!("DEBUG: Starting bidirectional tunnel"); // Spawn two tasks to forward data in both directions let client_to_target = tokio::spawn(async move { let result = tokio::io::copy(&mut client_read, &mut target_write).await; match result { Ok(bytes) => { - eprintln!("DEBUG: Tunneled {} bytes from client->target", bytes); + log::error!("DEBUG: Tunneled {} bytes from client->target", bytes); } Err(e) => { - eprintln!("Error forwarding client->target: {:?}", e); + log::error!("Error forwarding client->target: {:?}", e); } } }); @@ -715,10 +717,10 @@ async fn handle_connect_from_buffer( let result = tokio::io::copy(&mut target_read, &mut client_write).await; match result { Ok(bytes) => { - eprintln!("DEBUG: Tunneled {} bytes from target->client", bytes); + log::error!("DEBUG: Tunneled {} bytes from target->client", bytes); } Err(e) => { - eprintln!("Error forwarding target->client: {:?}", e); + log::error!("Error forwarding target->client: {:?}", e); } } }); @@ -726,10 +728,10 @@ async fn handle_connect_from_buffer( // Wait for either direction to finish (connection closed) tokio::select! { _ = client_to_target => { - eprintln!("DEBUG: Client->target tunnel closed"); + log::error!("DEBUG: Client->target tunnel closed"); } _ = target_to_client => { - eprintln!("DEBUG: Target->client tunnel closed"); + log::error!("DEBUG: Target->client tunnel closed"); } } diff --git a/src-tauri/src/settings_manager.rs b/src-tauri/src/settings_manager.rs index ed763b8..207e06a 100644 --- a/src-tauri/src/settings_manager.rs +++ b/src-tauri/src/settings_manager.rs @@ -110,17 +110,17 @@ impl SettingsManager { Ok(settings) => { // Save the settings back to ensure any missing fields are written with defaults if let Err(e) = self.save_settings(&settings) { - eprintln!("Warning: Failed to update settings file with defaults: {e}"); + log::warn!("Warning: Failed to update settings file with defaults: {e}"); } Ok(settings) } Err(e) => { - eprintln!("Warning: Failed to parse settings file, using defaults: {e}"); + log::warn!("Warning: Failed to parse settings file, using defaults: {e}"); let default_settings = AppSettings::default(); // Try to save default settings to fix the corrupted file if let Err(save_error) = self.save_settings(&default_settings) { - eprintln!("Warning: Failed to save default settings: {save_error}"); + log::warn!("Warning: Failed to save default settings: {save_error}"); } Ok(default_settings) diff --git a/src-tauri/src/version_updater.rs b/src-tauri/src/version_updater.rs index d306dc9..fb3aae5 100644 --- a/src-tauri/src/version_updater.rs +++ b/src-tauri/src/version_updater.rs @@ -129,14 +129,14 @@ impl VersionUpdater { let should_update = state.last_update_time == 0 || elapsed_secs >= update_interval_secs; if should_update { - println!( + log::debug!( "Background update needed: last_update={}, elapsed={}h, required={}h", state.last_update_time, elapsed_secs / 3600, state.update_interval_hours ); } else { - println!( + log::debug!( "Background update not needed: last_update={}, elapsed={}h, required={}h", state.last_update_time, elapsed_secs / 3600, @@ -152,12 +152,12 @@ impl VersionUpdater { ) -> Result<(), Box> { // Only run if an update is actually needed if !Self::should_run_background_update() { - println!("No startup version update needed"); + log::debug!("No startup version update needed"); return Ok(()); } if let Some(ref app_handle) = self.app_handle { - println!("Running startup version update..."); + log::info!("Running startup version update..."); match self.update_all_browser_versions(app_handle).await { Ok(_) => { @@ -168,13 +168,13 @@ impl VersionUpdater { }; if let Err(e) = Self::save_background_update_state(&state) { - eprintln!("Failed to save background update state: {e}"); + log::error!("Failed to save background update state: {e}"); } else { - println!("Startup version update completed successfully"); + log::info!("Startup version update completed successfully"); } } Err(e) => { - eprintln!("Startup version update failed: {e}"); + log::error!("Startup version update failed: {e}"); return Err(e); } } @@ -280,11 +280,11 @@ impl VersionUpdater { }; if let Err(e) = app_handle.emit("version-update-progress", &initial_progress) { - eprintln!("Failed to emit initial progress: {e}"); + log::error!("Failed to emit initial progress: {e}"); } for (index, browser) in supported_browsers.iter().enumerate() { - println!("Updating browser versions for: {browser}"); + log::debug!("Updating browser versions for: {browser}"); // Emit progress update for current browser let progress = VersionUpdateProgress { @@ -297,7 +297,7 @@ impl VersionUpdater { }; if let Err(e) = app_handle.emit("version-update-progress", &progress) { - eprintln!("Failed to emit progress for {browser}: {e}"); + log::error!("Failed to emit progress for {browser}: {e}"); } match self.update_browser_versions(browser).await { @@ -323,7 +323,7 @@ impl VersionUpdater { }; if let Err(e) = app_handle.emit("version-update-progress", &progress) { - eprintln!("Failed to emit progress with versions for {browser}: {e}"); + log::error!("Failed to emit progress with versions for {browser}: {e}"); } } Err(e) => { @@ -393,7 +393,7 @@ impl VersionUpdater { }; if let Err(e) = Self::save_background_update_state(&state) { - eprintln!("Failed to save background update state after manual update: {e}"); + log::error!("Failed to save background update state after manual update: {e}"); } Ok(results) @@ -506,7 +506,7 @@ pub async fn clear_all_version_cache_and_refetch( .auto_updater .save_auto_update_state(&final_state) { - eprintln!("Warning: Failed to re-enable browsers after cache clear: {e}"); + log::warn!("Failed to re-enable browsers after cache clear: {e}"); } result?; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index a4a5a44..7d225f9 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,10 +2,12 @@ import { Geist, Geist_Mono } from "next/font/google"; import "@/styles/globals.css"; import "flag-icons/css/flag-icons.min.css"; +import { useEffect } from "react"; import { CustomThemeProvider } from "@/components/theme-provider"; import { Toaster } from "@/components/ui/sonner"; import { TooltipProvider } from "@/components/ui/tooltip"; import { WindowDragArea } from "@/components/window-drag-area"; +import { setupLogging } from "@/lib/logger"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -22,6 +24,10 @@ export default function RootLayout({ }: Readonly<{ children: React.ReactNode; }>) { + useEffect(() => { + void setupLogging(); + }, []); + return ( { + error(`${message} ${args.map((arg) => JSON.stringify(arg)).join(" ")}`); + }, + warn: (message: string, ...args: unknown[]) => { + warn(`${message} ${args.map((arg) => JSON.stringify(arg)).join(" ")}`); + }, + info: (message: string, ...args: unknown[]) => { + info(`${message} ${args.map((arg) => JSON.stringify(arg)).join(" ")}`); + }, + debug: (message: string, ...args: unknown[]) => { + debug(`${message} ${args.map((arg) => JSON.stringify(arg)).join(" ")}`); + }, + log: (message: string, ...args: unknown[]) => { + trace(`${message} ${args.map((arg) => JSON.stringify(arg)).join(" ")}`); + }, +};