From 85c7c89c28ae0426d3972278f2c6e33ba7252e69 Mon Sep 17 00:00:00 2001 From: filipriec Date: Fri, 12 Sep 2025 15:46:14 +0200 Subject: [PATCH] space2 is now debugging better --- Cargo.lock | 38 +++++- client/Cargo.toml | 2 +- client/config.toml | 2 +- client/src/main.rs | 29 +++-- client/src/utils/debug_logger.rs | 34 +++++- client/ui_debug.log | 193 +++++++++++++++++++++++++++++++ 6 files changed, 275 insertions(+), 23 deletions(-) create mode 100644 client/ui_debug.log diff --git a/Cargo.lock b/Cargo.lock index 61f2e65..c538685 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1955,6 +1955,15 @@ version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "matchit" version = "0.8.4" @@ -2747,8 +2756,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] @@ -2759,9 +2777,15 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.5", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.8.5" @@ -3751,7 +3775,7 @@ dependencies = [ "fnv", "once_cell", "plist", - "regex-syntax", + "regex-syntax 0.8.5", "serde", "serde_derive", "serde_json", @@ -3857,7 +3881,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d60769b80ad7953d8a7b2c70cdfe722bbcdcac6bccc8ac934c40c034d866fc18" dependencies = [ "byteorder", - "regex-syntax", + "regex-syntax 0.8.5", "utf8-ranges", ] @@ -4287,10 +4311,14 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ + "matchers", "nu-ansi-term", + "once_cell", + "regex", "sharded-slab", "smallvec", "thread_local", + "tracing", "tracing-core", "tracing-log", ] diff --git a/client/Cargo.toml b/client/Cargo.toml index 5d28c14..7196dd6 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -24,7 +24,7 @@ tokio = { version = "1.44.2", features = ["full", "macros"] } toml = { workspace = true } tonic = "0.13.0" tracing = "0.1.41" -tracing-subscriber = "0.3.19" +tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } tui-textarea = { version = "0.7.0", features = ["crossterm", "ratatui", "search"] } unicode-segmentation = "1.12.0" unicode-width.workspace = true diff --git a/client/config.toml b/client/config.toml index 764dd4b..b51ce0d 100644 --- a/client/config.toml +++ b/client/config.toml @@ -50,7 +50,7 @@ move_down = ["j", "Down"] move_line_end = ["$"] move_word_next = ["w"] next_field = ["Tab"] -move_word_prev = ["b"] +# move_word_prev = ["b"] move_word_end = ["e"] move_last_line = ["shift+g"] move_word_end_prev = ["ge"] diff --git a/client/src/main.rs b/client/src/main.rs index fd5e5b3..a3c762b 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -4,26 +4,35 @@ use client::run_ui; use client::utils::debug_logger::UiDebugWriter; use dotenvy::dotenv; use anyhow::Result; -use tracing_subscriber; +use tracing_subscriber::EnvFilter; use std::env; #[tokio::main] async fn main() -> Result<()> { #[cfg(feature = "ui-debug")] { - // If ui-debug is on, set up our custom writer. - let writer = UiDebugWriter::new(); - tracing_subscriber::fmt() - .with_level(false) // Don't show INFO, ERROR, etc. - .with_target(false) // Don't show the module path. - .without_time() // This is the correct and simpler method. - .with_writer(move || writer.clone()) - .init(); + use std::sync::Once; + static INIT_LOGGER: Once = Once::new(); + + INIT_LOGGER.call_once(|| { + let writer = UiDebugWriter::new(); + let _ = tracing_subscriber::fmt() + .with_max_level(tracing::Level::DEBUG) + .with_target(false) + .without_time() + .with_writer(move || writer.clone()) + // Filter out noisy grpc/h2 internals + .with_env_filter("client=debug,tonic=info,h2=info,tower=info") + .try_init(); + + client::utils::debug_logger::spawn_file_logger(); + }); } + #[cfg(not(feature = "ui-debug"))] { if env::var("ENABLE_TRACING").is_ok() { - tracing_subscriber::fmt::init(); + let _ = tracing_subscriber::fmt::try_init(); } } diff --git a/client/src/utils/debug_logger.rs b/client/src/utils/debug_logger.rs index 6e733af..6757f5b 100644 --- a/client/src/utils/debug_logger.rs +++ b/client/src/utils/debug_logger.rs @@ -1,8 +1,11 @@ // client/src/utils/debug_logger.rs use lazy_static::lazy_static; use std::collections::VecDeque; // <-- FIX: Import VecDeque -use std::io; +use std::io::{self, Write}; use std::sync::{Arc, Mutex}; // <-- FIX: Import Mutex +use std::fs::OpenOptions; +use std::thread; +use std::time::Duration; lazy_static! { static ref UI_DEBUG_BUFFER: Arc>> = @@ -27,11 +30,11 @@ impl UiDebugWriter { impl io::Write for UiDebugWriter { fn write(&mut self, buf: &[u8]) -> io::Result { let mut buffer = UI_DEBUG_BUFFER.lock().unwrap(); - let message = String::from_utf8_lossy(buf); - let trimmed_message = message.trim().to_string(); - let is_error = trimmed_message.starts_with("ERROR"); - // Add the new message to the back of the queue - buffer.push_back((trimmed_message, is_error)); + let message = String::from_utf8_lossy(buf).trim().to_string(); + let is_error = message.starts_with("ERROR"); + + // Always keep in memory + buffer.push_back((message, is_error)); Ok(buf.len()) } @@ -44,3 +47,22 @@ impl io::Write for UiDebugWriter { pub fn pop_next_debug_message() -> Option<(String, bool)> { UI_DEBUG_BUFFER.lock().unwrap().pop_front() } + +/// spawn a background thread that keeps draining UI_DEBUG_BUFFER +/// and writes messages into ui_debug.log continuously +pub fn spawn_file_logger() { + thread::spawn(|| loop { + // pop one message if present + if let Some((msg, _)) = pop_next_debug_message() { + if let Ok(mut file) = OpenOptions::new() + .create(true) + .append(true) + .open("ui_debug.log") + { + let _ = writeln!(file, "{msg}"); + } + } + // small sleep to avoid burning CPU + thread::sleep(Duration::from_millis(50)); + }); +} diff --git a/client/ui_debug.log b/client/ui_debug.log new file mode 100644 index 0000000..d7dd3ef --- /dev/null +++ b/client/ui_debug.log @@ -0,0 +1,193 @@ +Logger initialized... + INFO Auth data loaded from file. User is auto-logged in. + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. +Logger initialized... + INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. +Logger initialized... + INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. +Logger initialized... + INFO Auth data loaded from file. User is auto-logged in. + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. +Logger initialized... + INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. +Logger initialized... + INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. + INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false +Logger initialized... + INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. +Logger initialized... + INFO Auth data loaded from file. User is auto-logged in. + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. + INFO RAW KEY: code=Char(':') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(EnterCommandMode) post_active_seq=false + INFO InputEngine.reset_sequence() leader_seq_before=[] + INFO KeySequenceTracker.reset() from [] + INFO KeySequenceTracker.reset() from [] + INFO RAW KEY: code=Char('w') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false + INFO KeySequenceTracker.reset() from [] + INFO ENGINE OUTCOME: PassThrough post_active_seq=false + INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false + INFO KeySequenceTracker.reset() from [] + INFO ENGINE OUTCOME: Action(ExitCommandMode) post_active_seq=false + INFO InputEngine.reset_sequence() leader_seq_before=[] + INFO KeySequenceTracker.reset() from [] + INFO KeySequenceTracker.reset() from [] + INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false + INFO RAW KEY: code=Char(':') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(EnterCommandMode) post_active_seq=false + INFO InputEngine.reset_sequence() leader_seq_before=[] + INFO KeySequenceTracker.reset() from [] + INFO KeySequenceTracker.reset() from [] + INFO RAW KEY: code=Char('w') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false + INFO KeySequenceTracker.reset() from [] + INFO ENGINE OUTCOME: PassThrough post_active_seq=false + INFO RAW KEY: code=Enter mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false + INFO KeySequenceTracker.reset() from [] + INFO ENGINE OUTCOME: Action(CommandExecute) post_active_seq=false + INFO InputEngine.reset_sequence() leader_seq_before=[] + INFO KeySequenceTracker.reset() from [] + INFO KeySequenceTracker.reset() from [] + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false + INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false +Logger initialized... + INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. +Logger initialized... + INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. + INFO RAW KEY: code=Char(':') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(EnterCommandMode) post_active_seq=false + INFO InputEngine.reset_sequence() leader_seq_before=[] + INFO KeySequenceTracker.reset() from [] + INFO KeySequenceTracker.reset() from [] + INFO RAW KEY: code=Char('w') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false + INFO KeySequenceTracker.reset() from [] + INFO ENGINE OUTCOME: PassThrough post_active_seq=false + INFO RAW KEY: code=Enter mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false + INFO KeySequenceTracker.reset() from [] + INFO ENGINE OUTCOME: Action(CommandExecute) post_active_seq=false + INFO InputEngine.reset_sequence() leader_seq_before=[] + INFO KeySequenceTracker.reset() from [] + INFO KeySequenceTracker.reset() from [] +Logger initialized... + INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. +Logger initialized... + INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. + INFO RAW KEY: code=Char(':') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(EnterCommandMode) post_active_seq=false + INFO InputEngine.reset_sequence() leader_seq_before=[] + INFO KeySequenceTracker.reset() from [] + INFO KeySequenceTracker.reset() from [] + INFO RAW KEY: code=Char('w') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false + INFO KeySequenceTracker.reset() from [] + INFO ENGINE OUTCOME: PassThrough post_active_seq=false + INFO RAW KEY: code=Enter mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false + INFO KeySequenceTracker.reset() from [] + INFO ENGINE OUTCOME: Action(CommandExecute) post_active_seq=false + INFO InputEngine.reset_sequence() leader_seq_before=[] + INFO KeySequenceTracker.reset() from [] + INFO KeySequenceTracker.reset() from [] + INFO RAW KEY: code=Char(':') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(EnterCommandMode) post_active_seq=false + INFO InputEngine.reset_sequence() leader_seq_before=[] + INFO KeySequenceTracker.reset() from [] + INFO KeySequenceTracker.reset() from [] + INFO RAW KEY: code=Char('w') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false + INFO KeySequenceTracker.reset() from [] + INFO ENGINE OUTCOME: PassThrough post_active_seq=false + INFO RAW KEY: code=Enter mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false + INFO KeySequenceTracker.reset() from [] + INFO ENGINE OUTCOME: Action(CommandExecute) post_active_seq=false + INFO InputEngine.reset_sequence() leader_seq_before=[] + INFO KeySequenceTracker.reset() from [] + INFO KeySequenceTracker.reset() from [] + INFO RAW KEY: code=Enter mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false +Logger initialized... + INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. +Logger initialized... + INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" + INFO Auth data loaded from file. User is auto-logged in. + INFO Initial view set to Form due to auto-login. + INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false + INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false + INFO RAW KEY: code=Esc mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(Navigate(Esc)) post_active_seq=false + INFO RAW KEY: code=Char(':') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: Action(EnterCommandMode) post_active_seq=false + INFO InputEngine.reset_sequence() leader_seq_before=[] + INFO KeySequenceTracker.reset() from [] + INFO KeySequenceTracker.reset() from [] + INFO RAW KEY: code=Char('q') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false + INFO KeySequenceTracker.reset() from [] + INFO ENGINE OUTCOME: PassThrough post_active_seq=false + INFO RAW KEY: code=Char('!') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=Command, overlay_active=true, in_form_edit_mode=false, allow_nav=false, has_active_seq=false + INFO KeySequenceTracker.reset() from [] + INFO ENGINE OUTCOME: PassThrough post_active_seq=false +Logger initialized... + INFO Auth data loaded from "/home/priec/.local/state/komp_ac_client/auth.token" + INFO Schema for 'default.customers' cached. + INFO Initial view set to Form due to auto-login. + INFO RAW KEY: code=Char('c') mods=KeyModifiers(CONTROL) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: PassThrough post_active_seq=false + INFO RAW KEY: code=Char('c') mods=KeyModifiers(0x0) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: PassThrough post_active_seq=false + INFO RAW KEY: code=Char('c') mods=KeyModifiers(CONTROL) pre_active_seq=false + INFO InputContext: app_mode=General, overlay_active=false, in_form_edit_mode=false, allow_nav=true, has_active_seq=false + INFO ENGINE OUTCOME: PassThrough post_active_seq=false