From 10f2a3079996fdc4439c05d40dc6276db0b6ef40 Mon Sep 17 00:00:00 2001 From: Zahari Dichev Date: Wed, 22 Sep 2021 19:52:42 +0000 Subject: [PATCH 1/3] console: show spawn location as a column Signed-off-by: Zahari Dichev --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- console/src/state/mod.rs | 11 +++++++++++ console/src/state/resources.rs | 18 +++--------------- console/src/state/tasks.rs | 10 +++++++++- console/src/view/task.rs | 21 +++++++++++++-------- console/src/view/tasks.rs | 7 ++++++- 7 files changed, 46 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f0d74470c..dc1b3d126 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1312,8 +1312,8 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.11.0" -source = "git+https://github.com/zaharidichev/tokio?branch=zd/instrument-sleep#e404e9b1596d746997078f130f279356e65b61c0" +version = "1.12.0" +source = "git+https://github.com/zaharidichev/tokio?branch=zd/structured-task-location#65bdd7be19ec8fab15c0c117dbb2d8e78fcd0df8" dependencies = [ "autocfg", "bytes", @@ -1368,7 +1368,7 @@ dependencies = [ [[package]] name = "tokio-macros" version = "1.3.0" -source = "git+https://github.com/zaharidichev/tokio?branch=zd/instrument-sleep#e404e9b1596d746997078f130f279356e65b61c0" +source = "git+https://github.com/zaharidichev/tokio?branch=zd/structured-task-location#65bdd7be19ec8fab15c0c117dbb2d8e78fcd0df8" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 5df4399b1..f250d55ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,4 @@ members = [ resolver = "2" [patch.crates-io] -tokio = { git = 'https://github.com/zaharidichev/tokio', branch = 'zd/instrument-sleep' } +tokio = { git = 'https://github.com/zaharidichev/tokio', branch = 'zd/structured-task-location' } diff --git a/console/src/state/mod.rs b/console/src/state/mod.rs index 8b2c02787..cbb7ed975 100644 --- a/console/src/state/mod.rs +++ b/console/src/state/mod.rs @@ -415,3 +415,14 @@ fn truncate_registry_path(s: String) -> String { Cow::Borrowed(_) => s.to_string(), }; } + +fn format_location(loc: Option) -> String { + loc.map(|mut l| { + if let Some(file) = l.file.take() { + let truncated = truncate_registry_path(file); + l.file = Some(truncated); + } + format!("{} ", l) + }) + .unwrap_or_else(|| "".to_string()) +} diff --git a/console/src/state/resources.rs b/console/src/state/resources.rs index 0af999e79..892cede41 100644 --- a/console/src/state/resources.rs +++ b/console/src/state/resources.rs @@ -1,5 +1,5 @@ use crate::intern::{self, InternedStr}; -use crate::state::{truncate_registry_path, Field, Metadata, Visibility}; +use crate::state::{format_location, Field, Metadata, Visibility}; use crate::view; use console_api as proto; use std::{ @@ -130,7 +130,7 @@ impl ResourcesState { new_list.clear(); } - let new_resources = update.new_resources.into_iter().filter_map(|mut resource| { + let new_resources = update.new_resources.into_iter().filter_map(|resource| { if resource.id.is_none() { tracing::warn!(?resource, "skipping resource with no id"); } @@ -159,19 +159,7 @@ impl ResourcesState { let id = resource.id?.id; let stats = ResourceStats::from_proto(stats_update.remove(&id)?, meta, styles, strings); - - // remove cargo part of the file path - let location = resource - .location - .take() - .map(|mut l| { - if let Some(file) = l.file.take() { - let truncated = truncate_registry_path(file); - l.file = Some(truncated); - } - format!("{} ", l) - }) - .unwrap_or_else(|| "unknown location".to_string()); + let location = format_location(resource.location); let resource = Resource { id, diff --git a/console/src/state/tasks.rs b/console/src/state/tasks.rs index afb134ee7..639c93a09 100644 --- a/console/src/state/tasks.rs +++ b/console/src/state/tasks.rs @@ -1,6 +1,6 @@ use crate::{ intern::{self, InternedStr}, - state::{Field, Metadata, Visibility}, + state::{format_location, Field, Metadata, Visibility}, util::Percentage, view, warnings::Linter, @@ -62,6 +62,7 @@ pub(crate) struct Task { name: Option, /// Currently active warnings for this task. warnings: Vec>, + location: String, } #[derive(Debug)] @@ -149,6 +150,8 @@ impl TasksState { let formatted_fields = Field::make_formatted(styles, &mut fields); let id = task.id?.id; let stats = stats_update.remove(&id)?.into(); + let location = format_location(task.location); + let mut task = Task { name, id, @@ -157,6 +160,7 @@ impl TasksState { stats, target: meta.target.clone(), warnings: Vec::new(), + location, }; task.lint(linters); let task = Rc::new(RefCell::new(task)); @@ -336,6 +340,10 @@ impl Task { } } } + + pub(crate) fn location(&self) -> &str { + &self.location + } } impl From for TaskStats { diff --git a/console/src/view/task.rs b/console/src/view/task.rs index 7bfda8a3e..479c838cb 100644 --- a/console/src/view/task.rs +++ b/console/src/view/task.rs @@ -148,22 +148,27 @@ impl TaskView { ]); // Just preallocate capacity for ID, name, target, total, busy, and idle. - let mut metrics = Vec::with_capacity(6); - metrics.push(Spans::from(vec![ + let mut overview = Vec::with_capacity(6); + overview.push(Spans::from(vec![ bold("ID: "), Span::raw(format!("{} ", task.id())), task.state().render(styles), ])); if let Some(name) = task.name() { - metrics.push(Spans::from(vec![bold("Name: "), Span::raw(name)])); + overview.push(Spans::from(vec![bold("Name: "), Span::raw(name)])); } - metrics.push(Spans::from(vec![ + overview.push(Spans::from(vec![ bold("Target: "), Span::raw(task.target()), ])); + overview.push(Spans::from(vec![ + bold("Location: "), + Span::raw(task.location()), + ])); + let total = task.total(now); let dur_percent = |name: &'static str, amt: Duration| -> Spans { @@ -175,9 +180,9 @@ impl TaskView { ]) }; - metrics.push(Spans::from(vec![bold("Total Time: "), dur(styles, total)])); - metrics.push(dur_percent("Busy: ", task.busy(now))); - metrics.push(dur_percent("Idle: ", task.idle(now))); + overview.push(Spans::from(vec![bold("Total Time: "), dur(styles, total)])); + overview.push(dur_percent("Busy: ", task.busy(now))); + overview.push(dur_percent("Idle: ", task.idle(now))); let mut waker_stats = vec![Spans::from(vec![ bold("Current wakers: "), @@ -246,7 +251,7 @@ impl TaskView { frame.render_widget(warnings, warnings_area); } - let task_widget = Paragraph::new(metrics).block(styles.border_block().title("Task")); + let task_widget = Paragraph::new(overview).block(styles.border_block().title("Task")); let wakers_widget = Paragraph::new(waker_stats).block(styles.border_block().title("Waker")); let fields_widget = Paragraph::new(fields).block(styles.border_block().title("Fields")); let percentiles_widget = Paragraph::new( diff --git a/console/src/view/tasks.rs b/console/src/view/tasks.rs index 08ef47bc2..bb49c590a 100644 --- a/console/src/view/tasks.rs +++ b/console/src/view/tasks.rs @@ -24,7 +24,8 @@ impl TableList for TasksTable { type Sort = SortBy; const HEADER: &'static [&'static str] = &[ - "Warn", "ID", "State", "Name", "Total", "Busy", "Idle", "Polls", "Target", "Fields", + "Warn", "ID", "State", "Name", "Total", "Busy", "Idle", "Polls", "Target", "Location", + "Fields", ]; fn render( @@ -65,12 +66,14 @@ impl TableList for TasksTable { let mut name_width = view::Width::new(Self::HEADER[3].len() as u16); let mut polls_width = view::Width::new(Self::HEADER[7].len() as u16); let mut target_width = view::Width::new(Self::HEADER[8].len() as u16); + let mut location_width = view::Width::new(Self::HEADER[9].len() as u16); let mut num_idle = 0; let mut num_running = 0; let rows = { let id_width = &mut id_width; let target_width = &mut target_width; + let location_width = &mut location_width; let name_width = &mut name_width; let polls_width = &mut polls_width; let warn_width = &mut warn_width; @@ -117,6 +120,7 @@ impl TableList for TasksTable { dur_cell(task.idle(now)), Cell::from(polls_width.update_str(task.total_polls().to_string())), Cell::from(target_width.update_str(task.target()).to_owned()), + Cell::from(location_width.update_str(task.location().to_owned())), Cell::from(Spans::from( task.formatted_fields() .iter() @@ -236,6 +240,7 @@ impl TableList for TasksTable { layout::Constraint::Length(DUR_LEN as u16), polls_width.constraint(), target_width.constraint(), + location_width.constraint(), fields_width, ]; From 63389a1ef9c16d725317e7b40d316c4b3a7b1ee3 Mon Sep 17 00:00:00 2001 From: Zahari Dichev Date: Wed, 22 Sep 2021 20:16:26 +0000 Subject: [PATCH 2/3] feedback Signed-off-by: Zahari Dichev --- console/src/state/tasks.rs | 9 +++++++++ console/src/view/task.rs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/console/src/state/tasks.rs b/console/src/state/tasks.rs index 639c93a09..001ef9592 100644 --- a/console/src/state/tasks.rs +++ b/console/src/state/tasks.rs @@ -41,6 +41,8 @@ pub(crate) enum SortBy { Busy = 5, Idle = 6, Polls = 7, + Target = 8, + Location = 9, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] @@ -416,6 +418,11 @@ impl SortBy { Self::Polls => { tasks.sort_unstable_by_key(|task| task.upgrade().map(|t| t.borrow().stats.polls)) } + Self::Target => { + tasks.sort_unstable_by_key(|task| task.upgrade().map(|t| t.borrow().target.clone())) + } + Self::Location => tasks + .sort_unstable_by_key(|task| task.upgrade().map(|t| t.borrow().location.clone())), } } } @@ -438,6 +445,8 @@ impl TryFrom for SortBy { idx if idx == Self::Busy as usize => Ok(Self::Busy), idx if idx == Self::Idle as usize => Ok(Self::Idle), idx if idx == Self::Polls as usize => Ok(Self::Polls), + idx if idx == Self::Target as usize => Ok(Self::Target), + idx if idx == Self::Location as usize => Ok(Self::Location), _ => Err(()), } } diff --git a/console/src/view/task.rs b/console/src/view/task.rs index 479c838cb..d445db797 100644 --- a/console/src/view/task.rs +++ b/console/src/view/task.rs @@ -148,7 +148,7 @@ impl TaskView { ]); // Just preallocate capacity for ID, name, target, total, busy, and idle. - let mut overview = Vec::with_capacity(6); + let mut overview = Vec::with_capacity(7); overview.push(Spans::from(vec![ bold("ID: "), Span::raw(format!("{} ", task.id())), From 4f59f34d2794a511d0523b87c279e9f6e598233b Mon Sep 17 00:00:00 2001 From: Zahari Dichev Date: Wed, 22 Sep 2021 20:24:19 +0000 Subject: [PATCH 3/3] patch Signed-off-by: Zahari Dichev --- Cargo.lock | 4 ++-- Cargo.toml | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc1b3d126..3476ecad2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1313,7 +1313,7 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" version = "1.12.0" -source = "git+https://github.com/zaharidichev/tokio?branch=zd/structured-task-location#65bdd7be19ec8fab15c0c117dbb2d8e78fcd0df8" +source = "git+https://github.com/tokio-rs/tokio?rev=b9b59e4f15ad80775315ac1615a127c29725cb77#b9b59e4f15ad80775315ac1615a127c29725cb77" dependencies = [ "autocfg", "bytes", @@ -1368,7 +1368,7 @@ dependencies = [ [[package]] name = "tokio-macros" version = "1.3.0" -source = "git+https://github.com/zaharidichev/tokio?branch=zd/structured-task-location#65bdd7be19ec8fab15c0c117dbb2d8e78fcd0df8" +source = "git+https://github.com/tokio-rs/tokio?rev=b9b59e4f15ad80775315ac1615a127c29725cb77#b9b59e4f15ad80775315ac1615a127c29725cb77" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index f250d55ce..3eda6d06a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,5 +6,11 @@ members = [ ] resolver = "2" -[patch.crates-io] -tokio = { git = 'https://github.com/zaharidichev/tokio', branch = 'zd/structured-task-location' } +# Patch the dependency on tokio to get Sleep resource instrumentation and +# structured spawn location. This can be un-patched when the following +# commits are released: +# - https://github.com/tokio-rs/tokio/commit/b9b59e4f15ad80775315ac1615a127c29725cb77 +# - https://github.com/tokio-rs/tokio/commit/b9834f6d8b3563e6907456d19fe418cfe19983c3 +[patch.crates-io.tokio] +git = "https://github.com/tokio-rs/tokio" +rev = "b9b59e4f15ad80775315ac1615a127c29725cb77"