From f00e89114b30030a5da05d528a07a580eb814eeb Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Tue, 12 Mar 2024 10:52:41 -0400 Subject: [PATCH] allow logs in interactive mode if desired --- veilid-cli/src/interactive_ui.rs | 116 ++++++++++++++++++++++++++++++- veilid-cli/src/log_viewer_ui.rs | 10 +-- veilid-cli/src/main.rs | 12 ++-- veilid-cli/src/ui.rs | 2 +- 4 files changed, 125 insertions(+), 15 deletions(-) diff --git a/veilid-cli/src/interactive_ui.rs b/veilid-cli/src/interactive_ui.rs index 4a1efe79..ec2cd01b 100644 --- a/veilid-cli/src/interactive_ui.rs +++ b/veilid-cli/src/interactive_ui.rs @@ -1,10 +1,12 @@ use std::io::Write; use crate::command_processor::*; +use crate::cursive_ui::CursiveUI; use crate::settings::*; use crate::tools::*; use crate::ui::*; +use console::{style, Term}; use flexi_logger::writers::LogWriter; use rustyline_async::SharedWriter; use rustyline_async::{Readline, ReadlineError, ReadlineEvent}; @@ -19,6 +21,8 @@ pub struct InteractiveUIInner { error: Option, done: Option, connection_state_receiver: flume::Receiver, + log_enabled: bool, + enable_color: bool, } #[derive(Clone)] @@ -30,6 +34,9 @@ impl InteractiveUI { pub fn new(_settings: &Settings) -> (Self, InteractiveUISender) { let (cssender, csreceiver) = flume::unbounded::(); + let term = Term::stdout(); + let enable_color = console::colors_enabled() && term.features().colors_supported(); + // Create the UI object let this = Self { inner: Arc::new(Mutex::new(InteractiveUIInner { @@ -38,6 +45,8 @@ impl InteractiveUI { error: None, done: Some(StopSource::new()), connection_state_receiver: csreceiver, + log_enabled: false, + enable_color, })), }; @@ -99,6 +108,78 @@ impl InteractiveUI { if let Err(e) = readline.clear() { println!("Error: {:?}", e); } + } else if line == "log error" { + let opt_cmdproc = self.inner.lock().cmdproc.clone(); + if let Some(cmdproc) = opt_cmdproc { + if let Err(e) = cmdproc.run_command( + "change_log_level api error", + UICallback::Interactive(Box::new(|| {})), + ) { + eprintln!("Error: {:?}", e); + self.inner.lock().done.take(); + } + self.inner.lock().log_enabled = true; + } + } else if line == "log warn" { + let opt_cmdproc = self.inner.lock().cmdproc.clone(); + if let Some(cmdproc) = opt_cmdproc { + if let Err(e) = cmdproc.run_command( + "change_log_level api warn", + UICallback::Interactive(Box::new(|| {})), + ) { + eprintln!("Error: {:?}", e); + self.inner.lock().done.take(); + } + self.inner.lock().log_enabled = true; + } + } else if line == "log info" { + let opt_cmdproc = self.inner.lock().cmdproc.clone(); + if let Some(cmdproc) = opt_cmdproc { + if let Err(e) = cmdproc.run_command( + "change_log_level api info", + UICallback::Interactive(Box::new(|| {})), + ) { + eprintln!("Error: {:?}", e); + self.inner.lock().done.take(); + } + self.inner.lock().log_enabled = true; + } + } else if line == "log debug" || line == "log" { + let opt_cmdproc = self.inner.lock().cmdproc.clone(); + if let Some(cmdproc) = opt_cmdproc { + if let Err(e) = cmdproc.run_command( + "change_log_level api debug", + UICallback::Interactive(Box::new(|| {})), + ) { + eprintln!("Error: {:?}", e); + self.inner.lock().done.take(); + } + self.inner.lock().log_enabled = true; + } + } else if line == "log trace" { + let opt_cmdproc = self.inner.lock().cmdproc.clone(); + if let Some(cmdproc) = opt_cmdproc { + if let Err(e) = cmdproc.run_command( + "change_log_level api trace", + UICallback::Interactive(Box::new(|| {})), + ) { + eprintln!("Error: {:?}", e); + self.inner.lock().done.take(); + } + self.inner.lock().log_enabled = true; + } + } else if line == "log off" { + let opt_cmdproc = self.inner.lock().cmdproc.clone(); + if let Some(cmdproc) = opt_cmdproc { + if let Err(e) = cmdproc.run_command( + "change_log_level api off", + UICallback::Interactive(Box::new(|| {})), + ) { + eprintln!("Error: {:?}", e); + self.inner.lock().done.take(); + } + self.inner.lock().log_enabled = false; + } } else if !line.is_empty() { readline.add_history_entry(line.to_string()); let cmdproc = self.inner.lock().cmdproc.clone(); @@ -230,5 +311,38 @@ impl UISender for InteractiveUISender { self.inner.lock().error = Some(e.to_string()); } } - fn add_log_event(&self, _log_color: Level, _event: &str) {} + fn add_log_event(&self, log_color: Level, event: &str) { + let (enable_color, mut stdout) = { + let inner = self.inner.lock(); + if !inner.log_enabled { + return; + } + let Some(stdout) = inner.stdout.clone() else { + return; + }; + + (inner.enable_color, stdout) + }; + + let log_line = format!( + "{}: {}", + CursiveUI::cli_ts(CursiveUI::get_start_time()), + event + ); + if enable_color { + let log_line = match log_color { + Level::Error => style(log_line).red().bright().to_string(), + Level::Warn => style(log_line).yellow().bright().to_string(), + Level::Info => log_line, + Level::Debug => style(log_line).green().bright().to_string(), + Level::Trace => style(log_line).blue().bright().to_string(), + }; + if let Err(e) = writeln!(stdout, "{}", log_line) { + eprintln!("Error: {:?}", e); + self.inner.lock().done.take(); + } + } else { + println!("{}", log_line); + } + } } diff --git a/veilid-cli/src/log_viewer_ui.rs b/veilid-cli/src/log_viewer_ui.rs index 8c07c9a7..bf02f451 100644 --- a/veilid-cli/src/log_viewer_ui.rs +++ b/veilid-cli/src/log_viewer_ui.rs @@ -103,7 +103,7 @@ impl LogViewerUI { 'e' | 'E' => { if let Err(e) = cmdproc.run_command( "change_log_level api error", - UICallback::LogViewerUI(Box::new(|| {})), + UICallback::LogViewer(Box::new(|| {})), ) { eprintln!("Error: {:?}", e); self.inner.lock().done.take(); @@ -112,7 +112,7 @@ impl LogViewerUI { 'w' | 'W' => { if let Err(e) = cmdproc.run_command( "change_log_level api warn", - UICallback::LogViewerUI(Box::new(|| {})), + UICallback::LogViewer(Box::new(|| {})), ) { eprintln!("Error: {:?}", e); self.inner.lock().done.take(); @@ -121,7 +121,7 @@ impl LogViewerUI { 'i' | 'I' => { if let Err(e) = cmdproc.run_command( "change_log_level api info", - UICallback::LogViewerUI(Box::new(|| {})), + UICallback::LogViewer(Box::new(|| {})), ) { eprintln!("Error: {:?}", e); self.inner.lock().done.take(); @@ -130,7 +130,7 @@ impl LogViewerUI { 'd' | 'D' => { if let Err(e) = cmdproc.run_command( "change_log_level api debug", - UICallback::LogViewerUI(Box::new(|| {})), + UICallback::LogViewer(Box::new(|| {})), ) { eprintln!("Error: {:?}", e); self.inner.lock().done.take(); @@ -139,7 +139,7 @@ impl LogViewerUI { 't' | 'T' => { if let Err(e) = cmdproc.run_command( "change_log_level api trace", - UICallback::LogViewerUI(Box::new(|| {})), + UICallback::LogViewer(Box::new(|| {})), ) { eprintln!("Error: {:?}", e); self.inner.lock().done.take(); diff --git a/veilid-cli/src/main.rs b/veilid-cli/src/main.rs index 2cab8882..f3b0e5c4 100644 --- a/veilid-cli/src/main.rs +++ b/veilid-cli/src/main.rs @@ -56,9 +56,9 @@ struct CmdlineArgs { /// evaluate #[arg(long, short = 'e', group = "execution_mode")] evaluate: Option, - /// show log + /// show log only #[arg(long, short = 'l', group = "execution_mode")] - show_log: bool, + log: bool, /// read commands from file #[arg( long, @@ -104,11 +104,7 @@ fn main() -> Result<(), String> { // If we are running in interactive mode disable some things let mut enable_cursive = true; - if args.interactive - || args.show_log - || args.command_file.is_some() - || args.evaluate.is_some() - { + if args.interactive || args.log || args.command_file.is_some() || args.evaluate.is_some() { settings.logging.terminal.enabled = false; enable_cursive = false; } @@ -184,7 +180,7 @@ fn main() -> Result<(), String> { Box::new(ui) as Box, Box::new(uisender) as Box, ) - } else if args.show_log { + } else if args.log { let (ui, uisender) = log_viewer_ui::LogViewerUI::new(&settings); ( Box::new(ui) as Box, diff --git a/veilid-cli/src/ui.rs b/veilid-cli/src/ui.rs index 9171601a..8ca14085 100644 --- a/veilid-cli/src/ui.rs +++ b/veilid-cli/src/ui.rs @@ -11,7 +11,7 @@ pub enum UICallback { Cursive(CursiveUICallback), Interactive(InteractiveUICallback), IOReadWrite(IOReadWriteUICallback), - LogViewerUI(LogViewerUICallback), + LogViewer(LogViewerUICallback), } pub trait UISender: Send {