From 3a130d6a8b298e3dc861b8ac4be419c271089ad6 Mon Sep 17 00:00:00 2001 From: Edmo Vamerlatti Costa <11836452+edmocosta@users.noreply.github.com> Date: Wed, 21 Jun 2023 19:24:06 +0200 Subject: [PATCH] Add error panel, panic hook, and updated dependencies (#1) --- Cargo.lock | 68 ++++++++++++++++++------------------ Cargo.toml | 8 ++--- src/cli/commands/view/app.rs | 14 +++++--- src/cli/commands/view/ui.rs | 32 +++++++++++++++-- src/cli/main.rs | 27 ++++++++++++++ 5 files changed, 104 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf2f47e..3f6ff52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -65,12 +71,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.0" @@ -115,13 +115,13 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.23" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", "time", "wasm-bindgen", @@ -583,14 +583,24 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.8" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f" dependencies = [ "log", "ring", + "rustls-webpki", "sct", - "webpki", +] + +[[package]] +name = "rustls-webpki" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +dependencies = [ + "ring", + "untrusted", ] [[package]] @@ -637,9 +647,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.93" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +checksum = "bdf3bf93142acad5821c99197022e170842cdbc1c30482b98750c688c640842a" dependencies = [ "itoa", "ryu", @@ -648,9 +658,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "2.3.3" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" +checksum = "9f02d8aa6e3c385bf084924f660ce2a3a6bd333ba55b35e8590b321f35d88513" dependencies = [ "serde", ] @@ -793,7 +803,7 @@ dependencies = [ name = "tuistash" version = "0.1.0" dependencies = [ - "base64 0.21.0", + "base64", "chrono", "clap", "colored_json", @@ -855,18 +865,18 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "ureq" -version = "2.6.2" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "338b31dd1314f68f3aabf3ed57ab922df95ffcd902476ca7ba3c4ce7b908c46d" +checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9" dependencies = [ - "base64 0.13.1", + "base64", "log", "once_cell", "rustls", + "rustls-webpki", "serde", "serde_json", "url", - "webpki", "webpki-roots", ] @@ -999,23 +1009,13 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "webpki-roots" -version = "0.22.6" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" dependencies = [ - "webpki", + "rustls-webpki", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 94c1224..f3813df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,17 +12,17 @@ edition = "2021" [dependencies] clap = { version = "4.3.0", features = ["std", "derive", "help", "usage", "suggestions"], default-features = false } -ureq = { version = "2.6.2", features = ["json", "tls"], default-features = false } +ureq = { version = "2.7.1", features = ["json", "tls"], default-features = false } serde = { version = "1.0", features = ["derive"], default-features = false } -serde_with = { version = "2.2.0", default-features = false } +serde_with = { version = "3.0.0", default-features = false } serde_json = { version = "1.0", default-features = false } tabled = { version = "0.10", features = ["color"], default-features = false } owo-colors = { version = "3.5.0", default-features = false } json_to_table = { version = "*", default-features = false } base64 = { version = "0.21.0", features = ["std"], default-features = false } -rustls = { version = "0.20.8", features = ["dangerous_configuration"], default-features = false } +rustls = { version = "0.21.2", features = ["dangerous_configuration"], default-features = false } colored_json = { version = "3", default-features = false } -chrono = { version = "0.4.23", features = ["std", "default"], default-features = false } +chrono = { version = "0.4.26", features = ["std", "default"], default-features = false } humansize = { version = "2.1.3", default-features = false } humantime = { version = "2.1.0" } tui = { version = "0.19.0", features = ["crossterm"] } diff --git a/src/cli/commands/view/app.rs b/src/cli/commands/view/app.rs index b08d4b6..a891d14 100644 --- a/src/cli/commands/view/app.rs +++ b/src/cli/commands/view/app.rs @@ -280,6 +280,7 @@ pub(crate) struct App<'a> { pub should_quit: bool, pub connected: bool, pub show_help: bool, + pub show_error: Option, pub tabs: TabsState, pub pipelines: StatefulTable, pub selected_pipeline_vertex: StatefulTable, @@ -319,6 +320,7 @@ impl<'a> App<'a> { show_selected_pipeline_charts: false, show_selected_vertex_details: false, show_help: false, + show_error: None, should_quit: false, connected: false, tabs: TabsState::new(), @@ -433,13 +435,15 @@ impl<'a> App<'a> { pub fn on_tick(&mut self) { match self.data_fetcher.fetch_info() { - Ok(stats) => { - self.state.node_info = Some(stats); + Ok(info) => { + self.state.node_info = Some(info); self.connected = true; + self.show_error = None; } - Err(_) => { + Err(err) => { self.state.node_info = None; self.connected = false; + self.show_error = Some(err.to_string()); } }; @@ -447,10 +451,12 @@ impl<'a> App<'a> { Ok(stats) => { self.state.node_stats = Some(stats); self.connected = true; + self.show_error = None; } - Err(_) => { + Err(err) => { self.state.node_stats = None; self.connected = false; + self.show_error = Some(err.to_string()); } }; diff --git a/src/cli/commands/view/ui.rs b/src/cli/commands/view/ui.rs index 00ac65a..bdb5c78 100644 --- a/src/cli/commands/view/ui.rs +++ b/src/cli/commands/view/ui.rs @@ -17,7 +17,7 @@ use crate::commands::view::node_charts::render_node_charts; use crate::commands::view::pipeline_view; pub(crate) fn draw(f: &mut Frame, app: &mut App) { - let constraints = if app.show_help { + let constraints = if app.show_help || app.show_error.is_some() { vec![ Constraint::Length(3), Constraint::Min(0), @@ -109,7 +109,7 @@ pub(crate) fn draw(f: &mut Frame, app: &mut App) { Span::styled(" @ ", Style::default().fg(Color::Gray)), Span::from(app.host), Span::styled( - format!(" | Sampling every {}ms", app.refresh_interval.as_millis()), + format!(" | Sampling every {}s", app.refresh_interval.as_secs()), Style::default().fg(Color::Gray), ), ])]; @@ -128,11 +128,37 @@ pub(crate) fn draw(f: &mut Frame, app: &mut App) { }; } - if app.show_help { + if app.show_error.is_some() { + draw_error_panel(f, app, chunks[2]); + } else if app.show_help { draw_help_panel(f, chunks[2]); } } +fn draw_error_panel(f: &mut Frame, app: &mut App, area: Rect) +where + B: Backend, +{ + if let Some(error) = &app.show_error { + f.render_widget(Block::default().borders(Borders::ALL), area); + + let footer_chunks = Layout::default() + .constraints([Constraint::Percentage(100)]) + .direction(Direction::Horizontal) + .margin(1) + .split(area); + + let w = Paragraph::new(vec![Spans::from(vec![ + Span::styled("Error: ", Style::default().fg(Color::Red)), + Span::styled(error, Style::default().fg(Color::DarkGray)), + ])]) + .alignment(Alignment::Left) + .wrap(Wrap { trim: true }); + + f.render_widget(w, footer_chunks[0]); + } +} + fn draw_help_panel(f: &mut Frame, area: Rect) where B: Backend, diff --git a/src/cli/main.rs b/src/cli/main.rs index aec6753..9518231 100644 --- a/src/cli/main.rs +++ b/src/cli/main.rs @@ -1,3 +1,6 @@ +use std::backtrace::Backtrace; +use std::panic; + use crate::config::Config; use crate::errors::AnyError; use crate::output::Output; @@ -27,6 +30,8 @@ fn run() -> Result { } fn main() { + setup_panic_hook(); + let result = run(); match result { Err(err) => { @@ -38,3 +43,25 @@ fn main() { } } } + +fn setup_panic_hook() { + panic::set_hook(Box::new(move |panic_info| { + let backtrace = Backtrace::force_capture().to_string(); + let loc = if let Some(location) = panic_info.location() { + format!(" in file {} at line {}", location.file(), location.line()) + } else { + String::new() + }; + + let message = if let Some(value) = panic_info.payload().downcast_ref::<&str>() { + value + } else if let Some(value) = panic_info.payload().downcast_ref::() { + value + } else { + "Payload not captured as it is not a string." + }; + + println!("Panic occurred{} with the message: {}", loc, message); + println!("Panic backtrace: \n{}", backtrace); + })); +}