desktop: use tracing for logging (#13135)
This commit is contained in:
104
packages/desktop/src-tauri/Cargo.lock
generated
104
packages/desktop/src-tauri/Cargo.lock
generated
@@ -535,8 +535,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
|
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"serde",
|
"serde",
|
||||||
|
"wasm-bindgen",
|
||||||
"windows-link 0.2.1",
|
"windows-link 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2491,6 +2493,15 @@ dependencies = [
|
|||||||
"syn 2.0.110",
|
"syn 2.0.110",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matchers"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
|
||||||
|
dependencies = [
|
||||||
|
"regex-automata",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matches"
|
name = "matches"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
@@ -2691,6 +2702,15 @@ dependencies = [
|
|||||||
"zbus",
|
"zbus",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nu-ansi-term"
|
||||||
|
version = "0.50.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.61.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-conv"
|
name = "num-conv"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -3065,6 +3085,7 @@ dependencies = [
|
|||||||
name = "opencode-desktop"
|
name = "opencode-desktop"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
"comrak",
|
"comrak",
|
||||||
"dirs",
|
"dirs",
|
||||||
"futures",
|
"futures",
|
||||||
@@ -3096,6 +3117,9 @@ dependencies = [
|
|||||||
"tauri-plugin-window-state",
|
"tauri-plugin-window-state",
|
||||||
"tauri-specta",
|
"tauri-specta",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"tracing-appender",
|
||||||
|
"tracing-subscriber",
|
||||||
"uuid",
|
"uuid",
|
||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"windows 0.61.3",
|
"windows 0.61.3",
|
||||||
@@ -4412,6 +4436,15 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sharded-slab"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shared_child"
|
name = "shared_child"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
@@ -5472,6 +5505,15 @@ dependencies = [
|
|||||||
"syn 2.0.110",
|
"syn 2.0.110",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiff"
|
name = "tiff"
|
||||||
version = "0.10.3"
|
version = "0.10.3"
|
||||||
@@ -5745,9 +5787,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.41"
|
version = "0.1.44"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
|
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tracing-attributes",
|
"tracing-attributes",
|
||||||
@@ -5755,10 +5797,22 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-attributes"
|
name = "tracing-appender"
|
||||||
version = "0.1.30"
|
version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
|
checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"thiserror 2.0.17",
|
||||||
|
"time",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-attributes"
|
||||||
|
version = "0.1.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -5767,11 +5821,41 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-core"
|
name = "tracing-core"
|
||||||
version = "0.1.34"
|
version = "0.1.36"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
|
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"valuable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-log"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-subscriber"
|
||||||
|
version = "0.3.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
|
||||||
|
dependencies = [
|
||||||
|
"matchers",
|
||||||
|
"nu-ansi-term",
|
||||||
|
"once_cell",
|
||||||
|
"regex-automata",
|
||||||
|
"sharded-slab",
|
||||||
|
"smallvec",
|
||||||
|
"thread_local",
|
||||||
|
"tracing",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5964,6 +6048,12 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "valuable"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version-compare"
|
name = "version-compare"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ specta = "=2.0.0-rc.22"
|
|||||||
specta-typescript = "0.0.9"
|
specta-typescript = "0.0.9"
|
||||||
tauri-specta = { version = "=2.0.0-rc.21", features = ["derive", "typescript"] }
|
tauri-specta = { version = "=2.0.0-rc.21", features = ["derive", "typescript"] }
|
||||||
dirs = "6.0.0"
|
dirs = "6.0.0"
|
||||||
|
tracing = "0.1"
|
||||||
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
|
tracing-appender = "0.2"
|
||||||
|
chrono = "0.4"
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
gtk = "0.18.2"
|
gtk = "0.18.2"
|
||||||
|
|||||||
@@ -6,10 +6,7 @@ use tauri_plugin_shell::{
|
|||||||
use tauri_plugin_store::StoreExt;
|
use tauri_plugin_store::StoreExt;
|
||||||
use tokio::sync::oneshot;
|
use tokio::sync::oneshot;
|
||||||
|
|
||||||
use crate::{
|
use crate::constants::{SETTINGS_STORE, WSL_ENABLED_KEY};
|
||||||
LogState,
|
|
||||||
constants::{MAX_LOG_ENTRIES, SETTINGS_STORE, WSL_ENABLED_KEY},
|
|
||||||
};
|
|
||||||
|
|
||||||
const CLI_INSTALL_DIR: &str = ".opencode/bin";
|
const CLI_INSTALL_DIR: &str = ".opencode/bin";
|
||||||
const CLI_BINARY_NAME: &str = "opencode";
|
const CLI_BINARY_NAME: &str = "opencode";
|
||||||
@@ -29,7 +26,7 @@ pub async fn get_config(app: &AppHandle) -> Option<Config> {
|
|||||||
create_command(app, "debug config", &[])
|
create_command(app, "debug config", &[])
|
||||||
.output()
|
.output()
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| eprintln!("Failed to read OC config: {e}"))
|
.inspect_err(|e| tracing::warn!("Failed to read OC config: {e}"))
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|out| String::from_utf8(out.stdout.to_vec()).ok())
|
.and_then(|out| String::from_utf8(out.stdout.to_vec()).ok())
|
||||||
.and_then(|s| serde_json::from_str::<Config>(&s).ok())
|
.and_then(|s| serde_json::from_str::<Config>(&s).ok())
|
||||||
@@ -104,12 +101,12 @@ pub fn install_cli(app: tauri::AppHandle) -> Result<String, String> {
|
|||||||
|
|
||||||
pub fn sync_cli(app: tauri::AppHandle) -> Result<(), String> {
|
pub fn sync_cli(app: tauri::AppHandle) -> Result<(), String> {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
println!("Skipping CLI sync for debug build");
|
tracing::debug!("Skipping CLI sync for debug build");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if !is_cli_installed() {
|
if !is_cli_installed() {
|
||||||
println!("No CLI installation found, skipping sync");
|
tracing::info!("No CLI installation found, skipping sync");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,21 +129,21 @@ pub fn sync_cli(app: tauri::AppHandle) -> Result<(), String> {
|
|||||||
let app_version = app.package_info().version.clone();
|
let app_version = app.package_info().version.clone();
|
||||||
|
|
||||||
if cli_version >= app_version {
|
if cli_version >= app_version {
|
||||||
println!(
|
tracing::info!(
|
||||||
"CLI version {} is up to date (app version: {}), skipping sync",
|
%cli_version, %app_version,
|
||||||
cli_version, app_version
|
"CLI is up to date, skipping sync"
|
||||||
);
|
);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
println!(
|
tracing::info!(
|
||||||
"CLI version {} is older than app version {}, syncing",
|
%cli_version, %app_version,
|
||||||
cli_version, app_version
|
"CLI is older than app version, syncing"
|
||||||
);
|
);
|
||||||
|
|
||||||
install_cli(app)?;
|
install_cli(app)?;
|
||||||
|
|
||||||
println!("Synced installed CLI");
|
tracing::info!("Synced installed CLI");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -207,7 +204,7 @@ pub fn create_command(app: &tauri::AppHandle, args: &str, extra_env: &[(&str, St
|
|||||||
|
|
||||||
if cfg!(windows) {
|
if cfg!(windows) {
|
||||||
if is_wsl_enabled(app) {
|
if is_wsl_enabled(app) {
|
||||||
println!("WSL is enabled, spawning CLI server in WSL.");
|
tracing::info!("WSL is enabled, spawning CLI server in WSL");
|
||||||
let version = app.package_info().version.to_string();
|
let version = app.package_info().version.to_string();
|
||||||
let mut script = vec![
|
let mut script = vec![
|
||||||
"set -e".to_string(),
|
"set -e".to_string(),
|
||||||
@@ -280,38 +277,9 @@ pub fn serve(
|
|||||||
port: u32,
|
port: u32,
|
||||||
password: &str,
|
password: &str,
|
||||||
) -> (CommandChild, oneshot::Receiver<TerminatedPayload>) {
|
) -> (CommandChild, oneshot::Receiver<TerminatedPayload>) {
|
||||||
let log_state = app.state::<LogState>();
|
|
||||||
let log_state_clone = log_state.inner().clone();
|
|
||||||
|
|
||||||
let (exit_tx, exit_rx) = oneshot::channel::<TerminatedPayload>();
|
let (exit_tx, exit_rx) = oneshot::channel::<TerminatedPayload>();
|
||||||
|
|
||||||
println!("spawning sidecar on port {port}");
|
tracing::info!(port, "Spawning sidecar");
|
||||||
|
|
||||||
if let Ok(mut logs) = log_state_clone.0.lock() {
|
|
||||||
let args =
|
|
||||||
format!("--print-logs --log-level WARN serve --hostname {hostname} --port {port}");
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
{
|
|
||||||
logs.push_back(format!("[SPAWN] sidecar=opencode-cli args=\"{args}\"\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
{
|
|
||||||
let sidecar = get_sidecar_path(app);
|
|
||||||
let shell = get_user_shell();
|
|
||||||
let cmd = if shell.ends_with("/nu") {
|
|
||||||
format!("^\"{}\" {}", sidecar.display(), args)
|
|
||||||
} else {
|
|
||||||
format!("\"{}\" {}", sidecar.display(), args)
|
|
||||||
};
|
|
||||||
logs.push_back(format!("[SPAWN] shell=\"{shell}\" argv=\"-il -c {cmd}\"\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
while logs.len() > MAX_LOG_ENTRIES {
|
|
||||||
logs.pop_front();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let envs = [
|
let envs = [
|
||||||
("OPENCODE_SERVER_USERNAME", "opencode".to_string()),
|
("OPENCODE_SERVER_USERNAME", "opencode".to_string()),
|
||||||
@@ -332,50 +300,22 @@ pub fn serve(
|
|||||||
match event {
|
match event {
|
||||||
CommandEvent::Stdout(line_bytes) => {
|
CommandEvent::Stdout(line_bytes) => {
|
||||||
let line = String::from_utf8_lossy(&line_bytes);
|
let line = String::from_utf8_lossy(&line_bytes);
|
||||||
print!("{line}");
|
tracing::info!(target: "sidecar", "{line}");
|
||||||
|
|
||||||
// Store log in shared state
|
|
||||||
if let Ok(mut logs) = log_state_clone.0.lock() {
|
|
||||||
logs.push_back(format!("[STDOUT] {}", line));
|
|
||||||
// Keep only the last MAX_LOG_ENTRIES
|
|
||||||
while logs.len() > MAX_LOG_ENTRIES {
|
|
||||||
logs.pop_front();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
CommandEvent::Stderr(line_bytes) => {
|
CommandEvent::Stderr(line_bytes) => {
|
||||||
let line = String::from_utf8_lossy(&line_bytes);
|
let line = String::from_utf8_lossy(&line_bytes);
|
||||||
eprint!("{line}");
|
tracing::info!(target: "sidecar", "{line}");
|
||||||
|
|
||||||
// Store log in shared state
|
|
||||||
if let Ok(mut logs) = log_state_clone.0.lock() {
|
|
||||||
logs.push_back(format!("[STDERR] {}", line));
|
|
||||||
// Keep only the last MAX_LOG_ENTRIES
|
|
||||||
while logs.len() > MAX_LOG_ENTRIES {
|
|
||||||
logs.pop_front();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
CommandEvent::Error(err) => {
|
CommandEvent::Error(err) => {
|
||||||
eprintln!("{err}");
|
tracing::error!(target: "sidecar", "{err}");
|
||||||
|
|
||||||
if let Ok(mut logs) = log_state_clone.0.lock() {
|
|
||||||
logs.push_back(format!("[ERROR] {err}\n"));
|
|
||||||
while logs.len() > MAX_LOG_ENTRIES {
|
|
||||||
logs.pop_front();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
CommandEvent::Terminated(payload) => {
|
CommandEvent::Terminated(payload) => {
|
||||||
if let Ok(mut logs) = log_state_clone.0.lock() {
|
tracing::info!(
|
||||||
logs.push_back(format!(
|
target: "sidecar",
|
||||||
"[EXIT] code={:?} signal={:?}\n",
|
code = ?payload.code,
|
||||||
payload.code, payload.signal
|
signal = ?payload.signal,
|
||||||
));
|
"Sidecar terminated"
|
||||||
while logs.len() > MAX_LOG_ENTRIES {
|
);
|
||||||
logs.pop_front();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(tx) = exit_tx.take() {
|
if let Some(tx) = exit_tx.take() {
|
||||||
let _ = tx.send(payload);
|
let _ = tx.send(payload);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ pub const SETTINGS_STORE: &str = "opencode.settings.dat";
|
|||||||
pub const DEFAULT_SERVER_URL_KEY: &str = "defaultServerUrl";
|
pub const DEFAULT_SERVER_URL_KEY: &str = "defaultServerUrl";
|
||||||
pub const WSL_ENABLED_KEY: &str = "wslEnabled";
|
pub const WSL_ENABLED_KEY: &str = "wslEnabled";
|
||||||
pub const UPDATER_ENABLED: bool = option_env!("TAURI_SIGNING_PRIVATE_KEY").is_some();
|
pub const UPDATER_ENABLED: bool = option_env!("TAURI_SIGNING_PRIVATE_KEY").is_some();
|
||||||
pub const MAX_LOG_ENTRIES: usize = 200;
|
|
||||||
|
|
||||||
pub fn window_state_flags() -> StateFlags {
|
pub fn window_state_flags() -> StateFlags {
|
||||||
StateFlags::all() - StateFlags::DECORATIONS - StateFlags::VISIBLE
|
StateFlags::all() - StateFlags::DECORATIONS - StateFlags::VISIBLE
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ use std::io::{Error, Result};
|
|||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use windows::Win32::Foundation::{CloseHandle, HANDLE};
|
use windows::Win32::Foundation::{CloseHandle, HANDLE};
|
||||||
use windows::Win32::System::JobObjects::{
|
use windows::Win32::System::JobObjects::{
|
||||||
AssignProcessToJobObject, CreateJobObjectW, JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,
|
AssignProcessToJobObject, CreateJobObjectW, JobObjectExtendedLimitInformation,
|
||||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION, JobObjectExtendedLimitInformation,
|
SetInformationJobObject, JOBOBJECT_EXTENDED_LIMIT_INFORMATION,
|
||||||
SetInformationJobObject,
|
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,
|
||||||
};
|
};
|
||||||
use windows::Win32::System::Threading::{OpenProcess, PROCESS_SET_QUOTA, PROCESS_TERMINATE};
|
use windows::Win32::System::Threading::{OpenProcess, PROCESS_SET_QUOTA, PROCESS_TERMINATE};
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ impl JobObjectState {
|
|||||||
error: Mutex::new(None),
|
error: Mutex::new(None),
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Failed to create job object: {e}");
|
tracing::error!("Failed to create job object: {e}");
|
||||||
Self {
|
Self {
|
||||||
job: Mutex::new(None),
|
job: Mutex::new(None),
|
||||||
error: Mutex::new(Some(format!("Failed to create job object: {e}"))),
|
error: Mutex::new(Some(format!("Failed to create job object: {e}"))),
|
||||||
@@ -123,11 +123,11 @@ impl JobObjectState {
|
|||||||
pub fn assign_pid(&self, pid: u32) {
|
pub fn assign_pid(&self, pid: u32) {
|
||||||
if let Some(job) = self.job.lock().unwrap().as_ref() {
|
if let Some(job) = self.job.lock().unwrap().as_ref() {
|
||||||
if let Err(e) = job.assign_pid(pid) {
|
if let Err(e) = job.assign_pid(pid) {
|
||||||
eprintln!("Failed to assign process {pid} to job object: {e}");
|
tracing::error!(pid, "Failed to assign process to job object: {e}");
|
||||||
*self.error.lock().unwrap() =
|
*self.error.lock().unwrap() =
|
||||||
Some(format!("Failed to assign process to job object: {e}"));
|
Some(format!("Failed to assign process to job object: {e}"));
|
||||||
} else {
|
} else {
|
||||||
println!("Assigned process {pid} to job object for automatic cleanup");
|
tracing::info!(pid, "Assigned process to job object for automatic cleanup");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ mod constants;
|
|||||||
mod job_object;
|
mod job_object;
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub mod linux_display;
|
pub mod linux_display;
|
||||||
|
mod logging;
|
||||||
mod markdown;
|
mod markdown;
|
||||||
mod server;
|
mod server;
|
||||||
mod window_customizer;
|
mod window_customizer;
|
||||||
@@ -16,7 +17,6 @@ use futures::{
|
|||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use job_object::*;
|
use job_object::*;
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
|
||||||
env,
|
env,
|
||||||
net::TcpListener,
|
net::TcpListener,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
@@ -85,14 +85,11 @@ impl ServerState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct LogState(Arc<Mutex<VecDeque<String>>>);
|
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
#[specta::specta]
|
#[specta::specta]
|
||||||
fn kill_sidecar(app: AppHandle) {
|
fn kill_sidecar(app: AppHandle) {
|
||||||
let Some(server_state) = app.try_state::<ServerState>() else {
|
let Some(server_state) = app.try_state::<ServerState>() else {
|
||||||
println!("Server not running");
|
tracing::info!("Server not running");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -102,24 +99,17 @@ fn kill_sidecar(app: AppHandle) {
|
|||||||
.expect("Failed to acquire mutex lock")
|
.expect("Failed to acquire mutex lock")
|
||||||
.take()
|
.take()
|
||||||
else {
|
else {
|
||||||
println!("Server state missing");
|
tracing::info!("Server state missing");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = server_state.kill();
|
let _ = server_state.kill();
|
||||||
|
|
||||||
println!("Killed server");
|
tracing::info!("Killed server");
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_logs(app: AppHandle) -> Result<String, String> {
|
fn get_logs() -> String {
|
||||||
let log_state = app.try_state::<LogState>().ok_or("Log state not found")?;
|
logging::tail()
|
||||||
|
|
||||||
let logs = log_state
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.map_err(|_| "Failed to acquire log lock")?;
|
|
||||||
|
|
||||||
Ok(logs.iter().cloned().collect::<Vec<_>>().join(""))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -715,10 +705,18 @@ pub fn run() {
|
|||||||
.plugin(tauri_plugin_decorum::init())
|
.plugin(tauri_plugin_decorum::init())
|
||||||
.invoke_handler(builder.invoke_handler())
|
.invoke_handler(builder.invoke_handler())
|
||||||
.setup(move |app| {
|
.setup(move |app| {
|
||||||
let app = app.handle().clone();
|
let handle = app.handle().clone();
|
||||||
|
|
||||||
builder.mount_events(&app);
|
let log_dir = app
|
||||||
tauri::async_runtime::spawn(initialize(app));
|
.path()
|
||||||
|
.app_log_dir()
|
||||||
|
.expect("failed to resolve app log dir");
|
||||||
|
// Hold the guard in managed state so it lives for the app's lifetime,
|
||||||
|
// ensuring all buffered logs are flushed on shutdown.
|
||||||
|
handle.manage(logging::init(&log_dir));
|
||||||
|
|
||||||
|
builder.mount_events(&handle);
|
||||||
|
tauri::async_runtime::spawn(initialize(handle));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
@@ -732,7 +730,7 @@ pub fn run() {
|
|||||||
.expect("error while running tauri application")
|
.expect("error while running tauri application")
|
||||||
.run(|app, event| {
|
.run(|app, event| {
|
||||||
if let RunEvent::Exit = event {
|
if let RunEvent::Exit = event {
|
||||||
println!("Received Exit");
|
tracing::info!("Received Exit");
|
||||||
|
|
||||||
kill_sidecar(app.clone());
|
kill_sidecar(app.clone());
|
||||||
}
|
}
|
||||||
@@ -780,9 +778,8 @@ fn test_export_types() {
|
|||||||
#[derive(tauri_specta::Event, serde::Deserialize, specta::Type)]
|
#[derive(tauri_specta::Event, serde::Deserialize, specta::Type)]
|
||||||
struct LoadingWindowComplete;
|
struct LoadingWindowComplete;
|
||||||
|
|
||||||
// #[tracing::instrument(skip_all)]
|
|
||||||
async fn initialize(app: AppHandle) {
|
async fn initialize(app: AppHandle) {
|
||||||
println!("Initializing app");
|
tracing::info!("Initializing app");
|
||||||
|
|
||||||
let (init_tx, init_rx) = watch::channel(InitStep::ServerWaiting);
|
let (init_tx, init_rx) = watch::channel(InitStep::ServerWaiting);
|
||||||
|
|
||||||
@@ -795,7 +792,7 @@ async fn initialize(app: AppHandle) {
|
|||||||
|
|
||||||
let loading_window_complete = event_once_fut::<LoadingWindowComplete>(&app);
|
let loading_window_complete = event_once_fut::<LoadingWindowComplete>(&app);
|
||||||
|
|
||||||
println!("Main and loading windows created");
|
tracing::info!("Main and loading windows created");
|
||||||
|
|
||||||
let sqlite_enabled = option_env!("OPENCODE_SQLITE").is_some();
|
let sqlite_enabled = option_env!("OPENCODE_SQLITE").is_some();
|
||||||
|
|
||||||
@@ -806,7 +803,7 @@ async fn initialize(app: AppHandle) {
|
|||||||
async move {
|
async move {
|
||||||
let mut sqlite_exists = sqlite_file_exists();
|
let mut sqlite_exists = sqlite_file_exists();
|
||||||
|
|
||||||
println!("Setting up server connection");
|
tracing::info!("Setting up server connection");
|
||||||
let server_connection = setup_server_connection(app.clone()).await;
|
let server_connection = setup_server_connection(app.clone()).await;
|
||||||
|
|
||||||
// we delay spawning this future so that the timeout is created lazily
|
// we delay spawning this future so that the timeout is created lazily
|
||||||
@@ -831,16 +828,13 @@ async fn initialize(app: AppHandle) {
|
|||||||
if let Some(err) = err {
|
if let Some(err) = err {
|
||||||
let _ = child.kill();
|
let _ = child.kill();
|
||||||
|
|
||||||
let logs = get_logs(app.clone())
|
|
||||||
.await
|
|
||||||
.unwrap_or_else(|e| format!("[DESKTOP] Failed to read sidecar logs: {e}\n"));
|
|
||||||
|
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Failed to spawn OpenCode Server ({err}). Logs:\n{logs}"
|
"Failed to spawn OpenCode Server ({err}). Logs:\n{}",
|
||||||
|
get_logs()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("CLI health check OK");
|
tracing::info!("CLI health check OK");
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
@@ -868,11 +862,11 @@ async fn initialize(app: AppHandle) {
|
|||||||
|
|
||||||
if let Some(cli_health_check) = cli_health_check {
|
if let Some(cli_health_check) = cli_health_check {
|
||||||
if sqlite_enabled {
|
if sqlite_enabled {
|
||||||
println!("Does sqlite file exist: {sqlite_exists}");
|
tracing::debug!(sqlite_exists, "Checking sqlite file existence");
|
||||||
if !sqlite_exists {
|
if !sqlite_exists {
|
||||||
println!(
|
tracing::info!(
|
||||||
"Sqlite file not found at {}, waiting for it to be generated",
|
path = %opencode_db_path().expect("failed to get db path").display(),
|
||||||
opencode_db_path().expect("failed to get db path").display()
|
"Sqlite file not found, waiting for it to be generated"
|
||||||
);
|
);
|
||||||
let _ = init_tx.send(InitStep::SqliteWaiting);
|
let _ = init_tx.send(InitStep::SqliteWaiting);
|
||||||
|
|
||||||
@@ -897,7 +891,7 @@ async fn initialize(app: AppHandle) {
|
|||||||
.await
|
.await
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
println!("Loading task timed out, showing loading window");
|
tracing::debug!("Loading task timed out, showing loading window");
|
||||||
let app = app.clone();
|
let app = app.clone();
|
||||||
let loading_window = LoadingWindow::create(&app).expect("Failed to create loading window");
|
let loading_window = LoadingWindow::create(&app).expect("Failed to create loading window");
|
||||||
sleep(Duration::from_secs(1)).await;
|
sleep(Duration::from_secs(1)).await;
|
||||||
@@ -910,14 +904,14 @@ async fn initialize(app: AppHandle) {
|
|||||||
|
|
||||||
let _ = loading_task.await;
|
let _ = loading_task.await;
|
||||||
|
|
||||||
println!("Loading done, completing initialisation");
|
tracing::info!("Loading done, completing initialisation");
|
||||||
|
|
||||||
let _ = init_tx.send(InitStep::Done);
|
let _ = init_tx.send(InitStep::Done);
|
||||||
|
|
||||||
if loading_window.is_some() {
|
if loading_window.is_some() {
|
||||||
loading_window_complete.await;
|
loading_window_complete.await;
|
||||||
|
|
||||||
println!("Loading window completed");
|
tracing::info!("Loading window completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::create(&app).expect("Failed to create main window");
|
MainWindow::create(&app).expect("Failed to create main window");
|
||||||
@@ -931,9 +925,6 @@ fn setup_app(app: &tauri::AppHandle, init_rx: watch::Receiver<InitStep>) {
|
|||||||
#[cfg(any(target_os = "linux", all(debug_assertions, windows)))]
|
#[cfg(any(target_os = "linux", all(debug_assertions, windows)))]
|
||||||
app.deep_link().register_all().ok();
|
app.deep_link().register_all().ok();
|
||||||
|
|
||||||
// Initialize log state
|
|
||||||
app.manage(LogState(Arc::new(Mutex::new(VecDeque::new()))));
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
app.manage(JobObjectState::new());
|
app.manage(JobObjectState::new());
|
||||||
|
|
||||||
@@ -943,7 +934,7 @@ fn setup_app(app: &tauri::AppHandle, init_rx: watch::Receiver<InitStep>) {
|
|||||||
fn spawn_cli_sync_task(app: AppHandle) {
|
fn spawn_cli_sync_task(app: AppHandle) {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Err(e) = sync_cli(app) {
|
if let Err(e) = sync_cli(app) {
|
||||||
eprintln!("Failed to sync CLI: {e}");
|
tracing::error!("Failed to sync CLI: {e}");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -963,12 +954,12 @@ enum ServerConnection {
|
|||||||
async fn setup_server_connection(app: AppHandle) -> ServerConnection {
|
async fn setup_server_connection(app: AppHandle) -> ServerConnection {
|
||||||
let custom_url = get_saved_server_url(&app).await;
|
let custom_url = get_saved_server_url(&app).await;
|
||||||
|
|
||||||
println!("Attempting server connection to custom url: {custom_url:?}");
|
tracing::info!(?custom_url, "Attempting server connection");
|
||||||
|
|
||||||
if let Some(url) = custom_url
|
if let Some(url) = custom_url
|
||||||
&& server::check_health_or_ask_retry(&app, &url).await
|
&& server::check_health_or_ask_retry(&app, &url).await
|
||||||
{
|
{
|
||||||
println!("Connected to custom server: {}", url);
|
tracing::info!(%url, "Connected to custom server");
|
||||||
return ServerConnection::Existing { url: url.clone() };
|
return ServerConnection::Existing { url: url.clone() };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -976,15 +967,15 @@ async fn setup_server_connection(app: AppHandle) -> ServerConnection {
|
|||||||
let hostname = "127.0.0.1";
|
let hostname = "127.0.0.1";
|
||||||
let local_url = format!("http://{hostname}:{local_port}");
|
let local_url = format!("http://{hostname}:{local_port}");
|
||||||
|
|
||||||
println!("Checking health of server '{}'", local_url);
|
tracing::debug!(url = %local_url, "Checking health of local server");
|
||||||
if server::check_health(&local_url, None).await {
|
if server::check_health(&local_url, None).await {
|
||||||
println!("Health check OK, using existing server");
|
tracing::info!(url = %local_url, "Health check OK, using existing server");
|
||||||
return ServerConnection::Existing { url: local_url };
|
return ServerConnection::Existing { url: local_url };
|
||||||
}
|
}
|
||||||
|
|
||||||
let password = uuid::Uuid::new_v4().to_string();
|
let password = uuid::Uuid::new_v4().to_string();
|
||||||
|
|
||||||
println!("Spawning new local server");
|
tracing::info!("Spawning new local server");
|
||||||
let (child, health_check) =
|
let (child, health_check) =
|
||||||
server::spawn_local_server(app, hostname.to_string(), local_port, password.clone());
|
server::spawn_local_server(app, hostname.to_string(), local_port, password.clone());
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,11 @@ struct DisplayConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn dir() -> Option<PathBuf> {
|
fn dir() -> Option<PathBuf> {
|
||||||
Some(dirs::data_dir()?.join(if cfg!(debug_assertions) { "ai.opencode.desktop.dev" } else { "ai.opencode.desktop" }))
|
Some(dirs::data_dir()?.join(if cfg!(debug_assertions) {
|
||||||
|
"ai.opencode.desktop.dev"
|
||||||
|
} else {
|
||||||
|
"ai.opencode.desktop"
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path() -> Option<PathBuf> {
|
fn path() -> Option<PathBuf> {
|
||||||
@@ -22,13 +26,12 @@ fn path() -> Option<PathBuf> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_wayland() -> Option<bool> {
|
pub fn read_wayland() -> Option<bool> {
|
||||||
let raw = std::fs::read_to_string(dbg!(path()?)).ok()?;
|
let raw = std::fs::read_to_string(path()?).ok()?;
|
||||||
let root = serde_json::from_str::<serde_json::Value>(&raw)
|
let root = serde_json::from_str::<serde_json::Value>(&raw)
|
||||||
.ok()?
|
.ok()?
|
||||||
.get(LINUX_DISPLAY_CONFIG_KEY).cloned()?;
|
.get(LINUX_DISPLAY_CONFIG_KEY)
|
||||||
serde_json::from_value::<DisplayConfig>(root)
|
.cloned()?;
|
||||||
.ok()?
|
serde_json::from_value::<DisplayConfig>(root).ok()?.wayland
|
||||||
.wayland
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_wayland(app: &AppHandle, value: bool) -> Result<(), String> {
|
pub fn write_wayland(app: &AppHandle, value: bool) -> Result<(), String> {
|
||||||
|
|||||||
83
packages/desktop/src-tauri/src/logging.rs
Normal file
83
packages/desktop/src-tauri/src/logging.rs
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
use std::fs::File;
|
||||||
|
use std::io::{BufRead, BufReader};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use tracing_appender::non_blocking::WorkerGuard;
|
||||||
|
use tracing_subscriber::{EnvFilter, fmt, layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
|
const MAX_LOG_AGE_DAYS: u64 = 7;
|
||||||
|
const TAIL_LINES: usize = 1000;
|
||||||
|
|
||||||
|
static LOG_PATH: std::sync::OnceLock<PathBuf> = std::sync::OnceLock::new();
|
||||||
|
|
||||||
|
pub fn init(log_dir: &Path) -> WorkerGuard {
|
||||||
|
std::fs::create_dir_all(log_dir).expect("failed to create log directory");
|
||||||
|
|
||||||
|
cleanup(log_dir);
|
||||||
|
|
||||||
|
let timestamp = chrono::Local::now().format("%Y-%m-%d_%H-%M-%S");
|
||||||
|
let filename = format!("opencode-desktop_{timestamp}.log");
|
||||||
|
let log_path = log_dir.join(&filename);
|
||||||
|
|
||||||
|
LOG_PATH
|
||||||
|
.set(log_path.clone())
|
||||||
|
.expect("logging already initialized");
|
||||||
|
|
||||||
|
let file = File::create(&log_path).expect("failed to create log file");
|
||||||
|
let (non_blocking, guard) = tracing_appender::non_blocking(file);
|
||||||
|
|
||||||
|
let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
EnvFilter::new("opencode_lib=debug,opencode_desktop=debug,sidecar=debug")
|
||||||
|
} else {
|
||||||
|
EnvFilter::new("opencode_lib=info,opencode_desktop=info,sidecar=info")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(filter)
|
||||||
|
.with(fmt::layer().with_writer(std::io::stderr))
|
||||||
|
.with(
|
||||||
|
fmt::layer()
|
||||||
|
.with_writer(non_blocking)
|
||||||
|
.with_ansi(false),
|
||||||
|
)
|
||||||
|
.init();
|
||||||
|
|
||||||
|
guard
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tail() -> String {
|
||||||
|
let Some(path) = LOG_PATH.get() else {
|
||||||
|
return String::new();
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(file) = File::open(path) else {
|
||||||
|
return String::new();
|
||||||
|
};
|
||||||
|
|
||||||
|
let lines: Vec<String> = BufReader::new(file)
|
||||||
|
.lines()
|
||||||
|
.map_while(Result::ok)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let start = lines.len().saturating_sub(TAIL_LINES);
|
||||||
|
lines[start..].join("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cleanup(log_dir: &Path) {
|
||||||
|
let cutoff = std::time::SystemTime::now()
|
||||||
|
- std::time::Duration::from_secs(MAX_LOG_AGE_DAYS * 24 * 60 * 60);
|
||||||
|
|
||||||
|
let Ok(entries) = std::fs::read_dir(log_dir) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
for entry in entries.flatten() {
|
||||||
|
if let Ok(meta) = entry.metadata()
|
||||||
|
&& let Ok(modified) = meta.modified()
|
||||||
|
&& modified < cutoff
|
||||||
|
{
|
||||||
|
let _ = std::fs::remove_file(entry.path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,7 +43,7 @@ fn configure_display_backend() -> Option<String> {
|
|||||||
set_env_if_absent("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
|
set_env_if_absent("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
|
||||||
return Some(
|
return Some(
|
||||||
"Wayland session detected; forcing X11 backend to avoid compositor protocol errors. \
|
"Wayland session detected; forcing X11 backend to avoid compositor protocol errors. \
|
||||||
Set OC_ALLOW_WAYLAND=1 to keep native Wayland."
|
Set OC_ALLOW_WAYLAND=1 to keep native Wayland."
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ fn main() {
|
|||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
{
|
{
|
||||||
if let Some(backend_note) = configure_display_backend() {
|
if let Some(backend_note) = configure_display_backend() {
|
||||||
eprintln!("{backend_note:?}");
|
eprintln!("{backend_note}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,14 +93,14 @@ pub fn set_wsl_config(app: AppHandle, config: WslConfig) -> Result<(), String> {
|
|||||||
|
|
||||||
pub async fn get_saved_server_url(app: &tauri::AppHandle) -> Option<String> {
|
pub async fn get_saved_server_url(app: &tauri::AppHandle) -> Option<String> {
|
||||||
if let Some(url) = get_default_server_url(app.clone()).ok().flatten() {
|
if let Some(url) = get_default_server_url(app.clone()).ok().flatten() {
|
||||||
println!("Using desktop-specific custom URL: {url}");
|
tracing::info!(%url, "Using desktop-specific custom URL");
|
||||||
return Some(url);
|
return Some(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(cli_config) = cli::get_config(app).await
|
if let Some(cli_config) = cli::get_config(app).await
|
||||||
&& let Some(url) = get_server_url_from_config(&cli_config)
|
&& let Some(url) = get_server_url_from_config(&cli_config)
|
||||||
{
|
{
|
||||||
println!("Using custom server URL from config: {url}");
|
tracing::info!(%url, "Using custom server URL from config");
|
||||||
return Some(url);
|
return Some(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ pub fn spawn_local_server(
|
|||||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||||
|
|
||||||
if check_health(&url, Some(&password)).await {
|
if check_health(&url, Some(&password)).await {
|
||||||
println!("Server ready after {:?}", timestamp.elapsed());
|
tracing::info!(elapsed = ?timestamp.elapsed(), "Server ready");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ fn normalize_hostname_for_url(hostname: &str) -> String {
|
|||||||
fn get_server_url_from_config(config: &cli::Config) -> Option<String> {
|
fn get_server_url_from_config(config: &cli::Config) -> Option<String> {
|
||||||
let server = config.server.as_ref()?;
|
let server = config.server.as_ref()?;
|
||||||
let port = server.port?;
|
let port = server.port?;
|
||||||
println!("server.port found in OC config: {port}");
|
tracing::debug!(port, "server.port found in OC config");
|
||||||
let hostname = server
|
let hostname = server
|
||||||
.hostname
|
.hostname
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -227,7 +227,7 @@ fn get_server_url_from_config(config: &cli::Config) -> Option<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn check_health_or_ask_retry(app: &AppHandle, url: &str) -> bool {
|
pub async fn check_health_or_ask_retry(app: &AppHandle, url: &str) -> bool {
|
||||||
println!("Checking health for {url}");
|
tracing::debug!(%url, "Checking health");
|
||||||
loop {
|
loop {
|
||||||
if check_health(url, None).await {
|
if check_health(url, None).await {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user