Skip to content

Commit e0c4789

Browse files
authored
feat(console): show task spawn location as a column (#166)
This PR extracts the spawn location of a task into a separate column, in the case where structured location information is present. This depends on: tokio-rs/tokio#4128 <img width="1393" alt="Screenshot 2021-09-22 at 22 56 50" src="https://user-images.githubusercontent.com/4391506/134412983-cae97ed9-c832-48b0-9584-f15dd25032e2.png"> Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
1 parent 5072fe4 commit e0c4789

File tree

7 files changed

+62
-30
lines changed

7 files changed

+62
-30
lines changed

Cargo.lock

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+8-2
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,11 @@ members = [
66
]
77
resolver = "2"
88

9-
[patch.crates-io]
10-
tokio = { git = 'https://github.com/zaharidichev/tokio', branch = 'zd/instrument-sleep' }
9+
# Patch the dependency on tokio to get Sleep resource instrumentation and
10+
# structured spawn location. This can be un-patched when the following
11+
# commits are released:
12+
# - https://github.com/tokio-rs/tokio/commit/b9b59e4f15ad80775315ac1615a127c29725cb77
13+
# - https://github.com/tokio-rs/tokio/commit/b9834f6d8b3563e6907456d19fe418cfe19983c3
14+
[patch.crates-io.tokio]
15+
git = "https://github.com/tokio-rs/tokio"
16+
rev = "b9b59e4f15ad80775315ac1615a127c29725cb77"

console/src/state/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -415,3 +415,14 @@ fn truncate_registry_path(s: String) -> String {
415415
Cow::Borrowed(_) => s.to_string(),
416416
};
417417
}
418+
419+
fn format_location(loc: Option<proto::Location>) -> String {
420+
loc.map(|mut l| {
421+
if let Some(file) = l.file.take() {
422+
let truncated = truncate_registry_path(file);
423+
l.file = Some(truncated);
424+
}
425+
format!("{} ", l)
426+
})
427+
.unwrap_or_else(|| "<unknown location>".to_string())
428+
}

console/src/state/resources.rs

+3-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::intern::{self, InternedStr};
2-
use crate::state::{truncate_registry_path, Field, Metadata, Visibility};
2+
use crate::state::{format_location, Field, Metadata, Visibility};
33
use crate::view;
44
use console_api as proto;
55
use std::{
@@ -130,7 +130,7 @@ impl ResourcesState {
130130
new_list.clear();
131131
}
132132

133-
let new_resources = update.new_resources.into_iter().filter_map(|mut resource| {
133+
let new_resources = update.new_resources.into_iter().filter_map(|resource| {
134134
if resource.id.is_none() {
135135
tracing::warn!(?resource, "skipping resource with no id");
136136
}
@@ -159,19 +159,7 @@ impl ResourcesState {
159159

160160
let id = resource.id?.id;
161161
let stats = ResourceStats::from_proto(stats_update.remove(&id)?, meta, styles, strings);
162-
163-
// remove cargo part of the file path
164-
let location = resource
165-
.location
166-
.take()
167-
.map(|mut l| {
168-
if let Some(file) = l.file.take() {
169-
let truncated = truncate_registry_path(file);
170-
l.file = Some(truncated);
171-
}
172-
format!("{} ", l)
173-
})
174-
.unwrap_or_else(|| "unknown location".to_string());
162+
let location = format_location(resource.location);
175163

176164
let resource = Resource {
177165
id,

console/src/state/tasks.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
intern::{self, InternedStr},
3-
state::{Field, Metadata, Visibility},
3+
state::{format_location, Field, Metadata, Visibility},
44
util::Percentage,
55
view,
66
warnings::Linter,
@@ -41,6 +41,8 @@ pub(crate) enum SortBy {
4141
Busy = 5,
4242
Idle = 6,
4343
Polls = 7,
44+
Target = 8,
45+
Location = 9,
4446
}
4547

4648
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
@@ -62,6 +64,7 @@ pub(crate) struct Task {
6264
name: Option<InternedStr>,
6365
/// Currently active warnings for this task.
6466
warnings: Vec<Linter<Task>>,
67+
location: String,
6568
}
6669

6770
#[derive(Debug)]
@@ -149,6 +152,8 @@ impl TasksState {
149152
let formatted_fields = Field::make_formatted(styles, &mut fields);
150153
let id = task.id?.id;
151154
let stats = stats_update.remove(&id)?.into();
155+
let location = format_location(task.location);
156+
152157
let mut task = Task {
153158
name,
154159
id,
@@ -157,6 +162,7 @@ impl TasksState {
157162
stats,
158163
target: meta.target.clone(),
159164
warnings: Vec::new(),
165+
location,
160166
};
161167
task.lint(linters);
162168
let task = Rc::new(RefCell::new(task));
@@ -336,6 +342,10 @@ impl Task {
336342
}
337343
}
338344
}
345+
346+
pub(crate) fn location(&self) -> &str {
347+
&self.location
348+
}
339349
}
340350

341351
impl From<proto::tasks::Stats> for TaskStats {
@@ -408,6 +418,11 @@ impl SortBy {
408418
Self::Polls => {
409419
tasks.sort_unstable_by_key(|task| task.upgrade().map(|t| t.borrow().stats.polls))
410420
}
421+
Self::Target => {
422+
tasks.sort_unstable_by_key(|task| task.upgrade().map(|t| t.borrow().target.clone()))
423+
}
424+
Self::Location => tasks
425+
.sort_unstable_by_key(|task| task.upgrade().map(|t| t.borrow().location.clone())),
411426
}
412427
}
413428
}
@@ -430,6 +445,8 @@ impl TryFrom<usize> for SortBy {
430445
idx if idx == Self::Busy as usize => Ok(Self::Busy),
431446
idx if idx == Self::Idle as usize => Ok(Self::Idle),
432447
idx if idx == Self::Polls as usize => Ok(Self::Polls),
448+
idx if idx == Self::Target as usize => Ok(Self::Target),
449+
idx if idx == Self::Location as usize => Ok(Self::Location),
433450
_ => Err(()),
434451
}
435452
}

console/src/view/task.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -148,22 +148,27 @@ impl TaskView {
148148
]);
149149

150150
// Just preallocate capacity for ID, name, target, total, busy, and idle.
151-
let mut metrics = Vec::with_capacity(6);
152-
metrics.push(Spans::from(vec![
151+
let mut overview = Vec::with_capacity(7);
152+
overview.push(Spans::from(vec![
153153
bold("ID: "),
154154
Span::raw(format!("{} ", task.id())),
155155
task.state().render(styles),
156156
]));
157157

158158
if let Some(name) = task.name() {
159-
metrics.push(Spans::from(vec![bold("Name: "), Span::raw(name)]));
159+
overview.push(Spans::from(vec![bold("Name: "), Span::raw(name)]));
160160
}
161161

162-
metrics.push(Spans::from(vec![
162+
overview.push(Spans::from(vec![
163163
bold("Target: "),
164164
Span::raw(task.target()),
165165
]));
166166

167+
overview.push(Spans::from(vec![
168+
bold("Location: "),
169+
Span::raw(task.location()),
170+
]));
171+
167172
let total = task.total(now);
168173

169174
let dur_percent = |name: &'static str, amt: Duration| -> Spans {
@@ -175,9 +180,9 @@ impl TaskView {
175180
])
176181
};
177182

178-
metrics.push(Spans::from(vec![bold("Total Time: "), dur(styles, total)]));
179-
metrics.push(dur_percent("Busy: ", task.busy(now)));
180-
metrics.push(dur_percent("Idle: ", task.idle(now)));
183+
overview.push(Spans::from(vec![bold("Total Time: "), dur(styles, total)]));
184+
overview.push(dur_percent("Busy: ", task.busy(now)));
185+
overview.push(dur_percent("Idle: ", task.idle(now)));
181186

182187
let mut waker_stats = vec![Spans::from(vec![
183188
bold("Current wakers: "),
@@ -246,7 +251,7 @@ impl TaskView {
246251
frame.render_widget(warnings, warnings_area);
247252
}
248253

249-
let task_widget = Paragraph::new(metrics).block(styles.border_block().title("Task"));
254+
let task_widget = Paragraph::new(overview).block(styles.border_block().title("Task"));
250255
let wakers_widget = Paragraph::new(waker_stats).block(styles.border_block().title("Waker"));
251256
let fields_widget = Paragraph::new(fields).block(styles.border_block().title("Fields"));
252257
let percentiles_widget = Paragraph::new(

console/src/view/tasks.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ impl TableList for TasksTable {
2424
type Sort = SortBy;
2525

2626
const HEADER: &'static [&'static str] = &[
27-
"Warn", "ID", "State", "Name", "Total", "Busy", "Idle", "Polls", "Target", "Fields",
27+
"Warn", "ID", "State", "Name", "Total", "Busy", "Idle", "Polls", "Target", "Location",
28+
"Fields",
2829
];
2930

3031
fn render<B: tui::backend::Backend>(
@@ -65,12 +66,14 @@ impl TableList for TasksTable {
6566
let mut name_width = view::Width::new(Self::HEADER[3].len() as u16);
6667
let mut polls_width = view::Width::new(Self::HEADER[7].len() as u16);
6768
let mut target_width = view::Width::new(Self::HEADER[8].len() as u16);
69+
let mut location_width = view::Width::new(Self::HEADER[9].len() as u16);
6870

6971
let mut num_idle = 0;
7072
let mut num_running = 0;
7173
let rows = {
7274
let id_width = &mut id_width;
7375
let target_width = &mut target_width;
76+
let location_width = &mut location_width;
7477
let name_width = &mut name_width;
7578
let polls_width = &mut polls_width;
7679
let warn_width = &mut warn_width;
@@ -117,6 +120,7 @@ impl TableList for TasksTable {
117120
dur_cell(task.idle(now)),
118121
Cell::from(polls_width.update_str(task.total_polls().to_string())),
119122
Cell::from(target_width.update_str(task.target()).to_owned()),
123+
Cell::from(location_width.update_str(task.location().to_owned())),
120124
Cell::from(Spans::from(
121125
task.formatted_fields()
122126
.iter()
@@ -236,6 +240,7 @@ impl TableList for TasksTable {
236240
layout::Constraint::Length(DUR_LEN as u16),
237241
polls_width.constraint(),
238242
target_width.constraint(),
243+
location_width.constraint(),
239244
fields_width,
240245
];
241246

0 commit comments

Comments
 (0)