allow logs in interactive mode if desired

This commit is contained in:
Christien Rioux 2024-03-12 10:52:41 -04:00
parent 8bc3e7f9ef
commit f00e89114b
4 changed files with 125 additions and 15 deletions

View File

@ -1,10 +1,12 @@
use std::io::Write; use std::io::Write;
use crate::command_processor::*; use crate::command_processor::*;
use crate::cursive_ui::CursiveUI;
use crate::settings::*; use crate::settings::*;
use crate::tools::*; use crate::tools::*;
use crate::ui::*; use crate::ui::*;
use console::{style, Term};
use flexi_logger::writers::LogWriter; use flexi_logger::writers::LogWriter;
use rustyline_async::SharedWriter; use rustyline_async::SharedWriter;
use rustyline_async::{Readline, ReadlineError, ReadlineEvent}; use rustyline_async::{Readline, ReadlineError, ReadlineEvent};
@ -19,6 +21,8 @@ pub struct InteractiveUIInner {
error: Option<String>, error: Option<String>,
done: Option<StopSource>, done: Option<StopSource>,
connection_state_receiver: flume::Receiver<ConnectionState>, connection_state_receiver: flume::Receiver<ConnectionState>,
log_enabled: bool,
enable_color: bool,
} }
#[derive(Clone)] #[derive(Clone)]
@ -30,6 +34,9 @@ impl InteractiveUI {
pub fn new(_settings: &Settings) -> (Self, InteractiveUISender) { pub fn new(_settings: &Settings) -> (Self, InteractiveUISender) {
let (cssender, csreceiver) = flume::unbounded::<ConnectionState>(); let (cssender, csreceiver) = flume::unbounded::<ConnectionState>();
let term = Term::stdout();
let enable_color = console::colors_enabled() && term.features().colors_supported();
// Create the UI object // Create the UI object
let this = Self { let this = Self {
inner: Arc::new(Mutex::new(InteractiveUIInner { inner: Arc::new(Mutex::new(InteractiveUIInner {
@ -38,6 +45,8 @@ impl InteractiveUI {
error: None, error: None,
done: Some(StopSource::new()), done: Some(StopSource::new()),
connection_state_receiver: csreceiver, connection_state_receiver: csreceiver,
log_enabled: false,
enable_color,
})), })),
}; };
@ -99,6 +108,78 @@ impl InteractiveUI {
if let Err(e) = readline.clear() { if let Err(e) = readline.clear() {
println!("Error: {:?}", e); 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() { } else if !line.is_empty() {
readline.add_history_entry(line.to_string()); readline.add_history_entry(line.to_string());
let cmdproc = self.inner.lock().cmdproc.clone(); let cmdproc = self.inner.lock().cmdproc.clone();
@ -230,5 +311,38 @@ impl UISender for InteractiveUISender {
self.inner.lock().error = Some(e.to_string()); 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);
}
}
} }

View File

@ -103,7 +103,7 @@ impl LogViewerUI {
'e' | 'E' => { 'e' | 'E' => {
if let Err(e) = cmdproc.run_command( if let Err(e) = cmdproc.run_command(
"change_log_level api error", "change_log_level api error",
UICallback::LogViewerUI(Box::new(|| {})), UICallback::LogViewer(Box::new(|| {})),
) { ) {
eprintln!("Error: {:?}", e); eprintln!("Error: {:?}", e);
self.inner.lock().done.take(); self.inner.lock().done.take();
@ -112,7 +112,7 @@ impl LogViewerUI {
'w' | 'W' => { 'w' | 'W' => {
if let Err(e) = cmdproc.run_command( if let Err(e) = cmdproc.run_command(
"change_log_level api warn", "change_log_level api warn",
UICallback::LogViewerUI(Box::new(|| {})), UICallback::LogViewer(Box::new(|| {})),
) { ) {
eprintln!("Error: {:?}", e); eprintln!("Error: {:?}", e);
self.inner.lock().done.take(); self.inner.lock().done.take();
@ -121,7 +121,7 @@ impl LogViewerUI {
'i' | 'I' => { 'i' | 'I' => {
if let Err(e) = cmdproc.run_command( if let Err(e) = cmdproc.run_command(
"change_log_level api info", "change_log_level api info",
UICallback::LogViewerUI(Box::new(|| {})), UICallback::LogViewer(Box::new(|| {})),
) { ) {
eprintln!("Error: {:?}", e); eprintln!("Error: {:?}", e);
self.inner.lock().done.take(); self.inner.lock().done.take();
@ -130,7 +130,7 @@ impl LogViewerUI {
'd' | 'D' => { 'd' | 'D' => {
if let Err(e) = cmdproc.run_command( if let Err(e) = cmdproc.run_command(
"change_log_level api debug", "change_log_level api debug",
UICallback::LogViewerUI(Box::new(|| {})), UICallback::LogViewer(Box::new(|| {})),
) { ) {
eprintln!("Error: {:?}", e); eprintln!("Error: {:?}", e);
self.inner.lock().done.take(); self.inner.lock().done.take();
@ -139,7 +139,7 @@ impl LogViewerUI {
't' | 'T' => { 't' | 'T' => {
if let Err(e) = cmdproc.run_command( if let Err(e) = cmdproc.run_command(
"change_log_level api trace", "change_log_level api trace",
UICallback::LogViewerUI(Box::new(|| {})), UICallback::LogViewer(Box::new(|| {})),
) { ) {
eprintln!("Error: {:?}", e); eprintln!("Error: {:?}", e);
self.inner.lock().done.take(); self.inner.lock().done.take();

View File

@ -56,9 +56,9 @@ struct CmdlineArgs {
/// evaluate /// evaluate
#[arg(long, short = 'e', group = "execution_mode")] #[arg(long, short = 'e', group = "execution_mode")]
evaluate: Option<String>, evaluate: Option<String>,
/// show log /// show log only
#[arg(long, short = 'l', group = "execution_mode")] #[arg(long, short = 'l', group = "execution_mode")]
show_log: bool, log: bool,
/// read commands from file /// read commands from file
#[arg( #[arg(
long, long,
@ -104,11 +104,7 @@ fn main() -> Result<(), String> {
// If we are running in interactive mode disable some things // If we are running in interactive mode disable some things
let mut enable_cursive = true; let mut enable_cursive = true;
if args.interactive if args.interactive || args.log || args.command_file.is_some() || args.evaluate.is_some() {
|| args.show_log
|| args.command_file.is_some()
|| args.evaluate.is_some()
{
settings.logging.terminal.enabled = false; settings.logging.terminal.enabled = false;
enable_cursive = false; enable_cursive = false;
} }
@ -184,7 +180,7 @@ fn main() -> Result<(), String> {
Box::new(ui) as Box<dyn UI>, Box::new(ui) as Box<dyn UI>,
Box::new(uisender) as Box<dyn UISender>, Box::new(uisender) as Box<dyn UISender>,
) )
} else if args.show_log { } else if args.log {
let (ui, uisender) = log_viewer_ui::LogViewerUI::new(&settings); let (ui, uisender) = log_viewer_ui::LogViewerUI::new(&settings);
( (
Box::new(ui) as Box<dyn UI>, Box::new(ui) as Box<dyn UI>,

View File

@ -11,7 +11,7 @@ pub enum UICallback {
Cursive(CursiveUICallback), Cursive(CursiveUICallback),
Interactive(InteractiveUICallback), Interactive(InteractiveUICallback),
IOReadWrite(IOReadWriteUICallback), IOReadWrite(IOReadWriteUICallback),
LogViewerUI(LogViewerUICallback), LogViewer(LogViewerUICallback),
} }
pub trait UISender: Send { pub trait UISender: Send {