diff --git a/src/app_data/container_state.rs b/src/app_data/container_state.rs index bc334c2..3734b34 100644 --- a/src/app_data/container_state.rs +++ b/src/app_data/container_state.rs @@ -182,7 +182,7 @@ impl DockerControls { } } - /// Docker commands available depending on the containers state + /// Docker commands available depending on the containers state pub fn gen_vec(state: State) -> Vec { match state { State::Dead | State::Exited => vec![Self::Start, Self::Restart], @@ -318,7 +318,6 @@ impl fmt::Display for ByteStats { } } - pub type MemTuple = (Vec<(f64, f64)>, ByteStats, State); pub type CpuTuple = (Vec<(f64, f64)>, CpuStats, State); @@ -398,20 +397,12 @@ impl ContainerItem { /// Get all cpu chart data fn get_cpu_chart_data(&self) -> CpuTuple { - ( - self.get_cpu_dataset(), - self.max_cpu_stats(), - self.state, - ) + (self.get_cpu_dataset(), self.max_cpu_stats(), self.state) } /// Get all mem chart data fn get_mem_chart_data(&self) -> MemTuple { - ( - self.get_mem_dataset(), - self.max_mem_stats(), - self.state, - ) + (self.get_mem_dataset(), self.max_mem_stats(), self.state) } /// Get chart info for cpu & memory in one function @@ -451,4 +442,4 @@ impl Columns { net_tx: (Header::Tx, 5), } } -} \ No newline at end of file +} diff --git a/src/docker_data/message.rs b/src/docker_data/message.rs index a2c51cc..a730830 100644 --- a/src/docker_data/message.rs +++ b/src/docker_data/message.rs @@ -7,4 +7,4 @@ pub enum DockerMessage { Unpause(String), Stop(String), Quit, -} \ No newline at end of file +} diff --git a/src/docker_data/mod.rs b/src/docker_data/mod.rs index 4547f11..c0fcd41 100644 --- a/src/docker_data/mod.rs +++ b/src/docker_data/mod.rs @@ -33,6 +33,7 @@ enum SpawnId { /// Cpu & Mem stats take twice as long as the update interval to get a value, so will have two being executed at the same time /// SpawnId::Stats takes container_id and binate value to enable both cycles of the same container_id to be inserted into the hashmap /// Binate value is toggled when all join handles have been spawned off +/// Also effectively means that if the docker_update interval minimum will be 1000ms #[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)] enum Binate { One, @@ -113,22 +114,20 @@ impl DockerData { let mem_stat = stats.memory_stats.usage.unwrap_or(0); let mem_limit = stats.memory_stats.limit.unwrap_or(0); - let some_key = stats + let op_key = stats .networks .as_ref() .and_then(|networks| networks.keys().next().cloned()); let cpu_stats = Self::calculate_usage(&stats); - let no_bytes = || (0, 0); - - let (rx, tx) = if let Some(key) = some_key { + let (rx, tx) = if let Some(key) = op_key { match stats.networks.unwrap_or_default().get(&key) { Some(data) => (data.rx_bytes, data.tx_bytes), - None => no_bytes(), + None => (0, 0), } } else { - no_bytes() + (0, 0) }; if is_running { @@ -155,8 +154,6 @@ impl DockerData { let docker = Arc::clone(&self.docker); let app_data = Arc::clone(&self.app_data); let spawns = Arc::clone(&self.spawns); - let id = id.clone(); - let key = SpawnId::Stats((id.clone(), self.binate)); let spawn_key = key.clone(); @@ -228,19 +225,18 @@ impl DockerData { docker: Arc, id: String, timestamps: bool, - since: i64, + since: u64, app_data: Arc>, spawns: Arc>>>, ) { let options = Some(LogsOptions:: { stdout: true, timestamps, - since, + since: since as i64, ..Default::default() }); let mut logs = docker.logs(&id, options); - let mut output = vec![]; while let Some(value) = logs.next().await { @@ -259,15 +255,18 @@ impl DockerData { fn init_all_logs(&mut self, all_ids: &[(bool, String)]) { for (_, id) in all_ids.iter() { let docker = Arc::clone(&self.docker); - let timestamps = self.timestamps; - let id = id.clone(); let app_data = Arc::clone(&self.app_data); let spawns = Arc::clone(&self.spawns); let key = SpawnId::Log(id.clone()); self.spawns.lock().insert( key, tokio::spawn(Self::update_log( - docker, id, timestamps, 0, app_data, spawns, + docker, + id.clone(), + self.timestamps, + 0, + app_data, + spawns, )), ); } @@ -278,20 +277,24 @@ impl DockerData { let all_ids = self.update_all_containers().await; let optional_index = self.app_data.lock().get_selected_log_index(); if let Some(index) = optional_index { - // this could be neater - let id = self.app_data.lock().containers.items[index].id.clone(); - let key = SpawnId::Log(id.clone()); - - self.spawns.lock().entry(key).or_insert_with(|| { - let since = self.app_data.lock().containers.items[index].last_updated as i64; - let docker = Arc::clone(&self.docker); - let timestamps = self.timestamps; - let app_data = Arc::clone(&self.app_data); - let spawns = Arc::clone(&self.spawns); - tokio::spawn(Self::update_log( - docker, id, timestamps, since, app_data, spawns, - )) - }); + if let Some(container) = self.app_data.lock().containers.items.get(index) { + self.spawns + .lock() + .entry(SpawnId::Log(container.id.clone())) + .or_insert_with(|| { + let docker = Arc::clone(&self.docker); + let app_data = Arc::clone(&self.app_data); + let spawns = Arc::clone(&self.spawns); + tokio::spawn(Self::update_log( + docker, + container.id.clone(), + self.timestamps, + container.last_updated, + app_data, + spawns, + )) + }); + } }; self.update_all_container_stats(&all_ids); } @@ -391,8 +394,6 @@ impl DockerData { .lock() .set_error(AppError::DockerCommand(DockerControls::Unpause)); }; - // loading sping take uuid to remove - // stop_loading_sping(uuid) self.stop_loading_spin(&loading_spin, loading_uuid); self.update_everything().await; } diff --git a/src/main.rs b/src/main.rs index b39db48..ae69b15 100644 --- a/src/main.rs +++ b/src/main.rs @@ -46,23 +46,21 @@ async fn main() { // Create docker daemon handler, and only spawn up the docker data handler if ping returns non-error match Docker::connect_with_socket_defaults() { - Ok(docker) => { - match docker.ping().await { - Ok(_) => { - let docker = Arc::new(docker); - let is_running = Arc::clone(&is_running); - tokio::spawn(DockerData::init( - args, - docker_app_data, - docker, - docker_gui_state, - docker_rx, - is_running, - )); - } - Err(_) => app_data.lock().set_error(AppError::DockerConnect), + Ok(docker) => match docker.ping().await { + Ok(_) => { + let docker = Arc::new(docker); + let is_running = Arc::clone(&is_running); + tokio::spawn(DockerData::init( + args, + docker_app_data, + docker, + docker_gui_state, + docker_rx, + is_running, + )); } - } + Err(_) => app_data.lock().set_error(AppError::DockerConnect), + }, Err(_) => app_data.lock().set_error(AppError::DockerConnect), } let input_app_data = Arc::clone(&app_data); @@ -82,7 +80,6 @@ async fn main() { input_is_running, )); - if args.gui { let update_duration = std::time::Duration::from_millis(u64::from(args.docker_interval)); create_ui( @@ -96,8 +93,8 @@ async fn main() { .await .unwrap_or(()); } else { - // Debug mode for testing, mostly pointless, doesn't take terminal nor draw gui - // TODO this needs to be improved to display something actually useful + // Debug mode for testing, mostly pointless, doesn't take terminal nor draw gui + // TODO this needs to be improved to display something actually useful loop { info!("in debug mode"); tokio::time::sleep(std::time::Duration::from_millis(5000)).await; diff --git a/src/parse_args/mod.rs b/src/parse_args/mod.rs index b7ece6b..6a4e13f 100644 --- a/src/parse_args/mod.rs +++ b/src/parse_args/mod.rs @@ -7,7 +7,7 @@ use tracing::error; // #[command(help_template = FULL_TEMPLATE)] #[command(version, about)] pub struct CliArgs { - /// Docker update interval in ms, minimum 1, reccomended 500+ + /// Docker update interval in ms, minimum effectively 1000 #[clap(short = 'd', value_name = "ms", default_value_t = 1000)] pub docker_interval: u32, diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs index 26e56ac..2f1a847 100644 --- a/src/ui/draw_blocks.rs +++ b/src/ui/draw_blocks.rs @@ -40,7 +40,7 @@ const DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION"); const ORANGE: Color = Color::Rgb(255, 178, 36); const MARGIN: &str = " "; const ARROW: &str = "▶ "; -const CIRCLE: &str ="⚪ "; +const CIRCLE: &str = "⚪ "; /// Generate block, add a border if is the selected panel, /// add custom title based on state of each panel @@ -471,7 +471,7 @@ pub fn heading_bar( .block(block()) .alignment(Alignment::Right); - // If no containers, don't display the headers, could maybe do this first? + // If no containers, don't display the headers, could maybe do this first? let index = if has_containers { 1 } else { 0 }; f.render_widget(paragraph, split_bar[index]); } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 35a8b28..e2dc511 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -104,11 +104,11 @@ async fn run_app( } else { let mut now = Instant::now(); loop { - if terminal.draw(|f| ui(f, &app_data, &gui_state)).is_err() { - return Err(AppError::Terminal); + if terminal.draw(|f| ui(f, &app_data, &gui_state)).is_err() { + return Err(AppError::Terminal); } - // TODO could only draw if in gui mode, that way all inputs & docker commands will run, and can just trace!("{event"}) all over the place - // refactor this into own function, so can be called without drawing to the terminal + // TODO could only draw if in gui mode, that way all inputs & docker commands will run, and can just trace!("{event"}) all over the place + // refactor this into own function, so can be called without drawing to the terminal if crossterm::event::poll(input_poll_rate).unwrap_or(false) { if let Ok(event) = event::read() { if let Event::Key(key) = event {