From 10f2a3079996fdc4439c05d40dc6276db0b6ef40 Mon Sep 17 00:00:00 2001
From: Zahari Dichev <zaharidichev@gmail.com>
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 <zaharidichev@gmail.com>
---
 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<proto::Location>) -> 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(|| "<unknown location>".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<InternedStr>,
     /// Currently active warnings for this task.
     warnings: Vec<Linter<Task>>,
+    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<proto::tasks::Stats> 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<B: tui::backend::Backend>(
@@ -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 <zaharidichev@gmail.com>
Date: Wed, 22 Sep 2021 20:16:26 +0000
Subject: [PATCH 2/3] feedback

Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
---
 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<usize> 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 <zaharidichev@gmail.com>
Date: Wed, 22 Sep 2021 20:24:19 +0000
Subject: [PATCH 3/3] patch

Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
---
 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"