Skip to content

Commit a6800f4

Browse files
authored
Include widget ids in tracing spans (#729)
New tracy image: ![image](https://github.com/user-attachments/assets/94e54c89-8159-4dd4-a521-4a7122f64375) New log tracing file: <details><summary>An overview of the new logs</summary> <p> ``` 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}: masonry::passes::update: RootWidget received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}: masonry::passes::update: Flex received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#8}: masonry::passes::update: Flex received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#8}:SizedBox{id=#7}: masonry::passes::update: SizedBox received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#8}:SizedBox{id=#7}:Flex{id=#6}: masonry::passes::update: Flex received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#8}:SizedBox{id=#7}:Flex{id=#6}:Flex{id=#3}: masonry::passes::update: Flex received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#8}:SizedBox{id=#7}:Flex{id=#6}:Flex{id=#3}:Prose{id=#1}: masonry::passes::update: Prose received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#8}:SizedBox{id=#7}:Flex{id=#6}:Flex{id=#3}:Label{id=#2}: masonry::passes::update: Label received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#8}:SizedBox{id=#7}:Flex{id=#6}:Flex{id=#5}: masonry::passes::update: Flex received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#8}:SizedBox{id=#7}:Flex{id=#6}:Flex{id=#5}:VariableLabel{id=#4}: masonry::passes::update: VariableLabel received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#17}: masonry::passes::update: Flex received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#17}:Button{id=#10}: masonry::passes::update: Button received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#17}:Button{id=#10}:Label{id=#9}: masonry::passes::update: Label received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#17}:Button{id=#12}: masonry::passes::update: Button received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#17}:Button{id=#12}:Label{id=#11}: masonry::passes::update: Label received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#17}:Button{id=#14}: masonry::passes::update: Button received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#17}:Button{id=#14}:Label{id=#13}: masonry::passes::update: Label received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#17}:Button{id=#16}: masonry::passes::update: Button received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Flex{id=#17}:Button{id=#16}:Label{id=#15}: masonry::passes::update: Label received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Portal{id=#163}: masonry::passes::update: Portal received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Portal{id=#163}:Flex{id=#160}: masonry::passes::update: Flex received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Portal{id=#163}:Flex{id=#160}:SizedBox{id=#24}: masonry::passes::update: SizedBox received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Portal{id=#163}:Flex{id=#160}:SizedBox{id=#24}:Flex{id=#23}: masonry::passes::update: Flex received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Portal{id=#163}:Flex{id=#160}:SizedBox{id=#24}:Flex{id=#23}:Flex{id=#20}: masonry::passes::update: Flex received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Portal{id=#163}:Flex{id=#160}:SizedBox{id=#24}:Flex{id=#23}:Flex{id=#20}:Prose{id=#18}: masonry::passes::update: Prose received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Portal{id=#163}:Flex{id=#160}:SizedBox{id=#24}:Flex{id=#23}:Flex{id=#20}:Label{id=#19}: masonry::passes::update: Label received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Portal{id=#163}:Flex{id=#160}:SizedBox{id=#24}:Flex{id=#23}:Flex{id=#22}: masonry::passes::update: Flex received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Portal{id=#163}:Flex{id=#160}:SizedBox{id=#24}:Flex{id=#23}:Flex{id=#22}:VariableLabel{id=#21}: masonry::passes::update: VariableLabel received Update::WidgetAdded 14:37:40.365Z TRACE update_new_widgets:RootWidget{id=#165}:Flex{id=#164}:Portal{id=#163}:Flex{id=#160}:SizedBox{id=#31}: masonry::passes::update: SizedBox received Update::WidgetAdded ``` </p> </details> This was originally an experiment into caching spans, but I determined that was non-viable due to the pass names.
1 parent 6258856 commit a6800f4

30 files changed

+189
-115
lines changed

masonry/examples/calc_masonry.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use masonry::dpi::LogicalSize;
1717
use masonry::widget::{Align, CrossAxisAlignment, Flex, Label, RootWidget, SizedBox};
1818
use masonry::{
1919
AccessCtx, AccessEvent, Action, AppDriver, BoxConstraints, Color, DriverCtx, EventCtx,
20-
LayoutCtx, PaintCtx, Point, PointerEvent, RegisterCtx, Size, TextEvent, Update, UpdateCtx,
21-
Widget, WidgetId, WidgetPod,
20+
LayoutCtx, PaintCtx, Point, PointerEvent, QueryCtx, RegisterCtx, Size, TextEvent, Update,
21+
UpdateCtx, Widget, WidgetId, WidgetPod,
2222
};
2323
use smallvec::{smallvec, SmallVec};
2424
use tracing::{trace, trace_span, Span};
@@ -244,8 +244,8 @@ impl Widget for CalcButton {
244244
smallvec![self.inner.id()]
245245
}
246246

247-
fn make_trace_span(&self) -> Span {
248-
trace_span!("CalcButton")
247+
fn make_trace_span(&self, ctx: &QueryCtx<'_>) -> Span {
248+
trace_span!("CalcButton", id = ctx.widget_id().trace())
249249
}
250250
}
251251

masonry/examples/custom_widget.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use masonry::kurbo::{BezPath, Stroke};
1515
use masonry::widget::{ObjectFit, RootWidget};
1616
use masonry::{
1717
AccessCtx, AccessEvent, Action, Affine, AppDriver, BoxConstraints, Color, DriverCtx, EventCtx,
18-
LayoutCtx, PaintCtx, Point, PointerEvent, Rect, RegisterCtx, Size, TextEvent, Widget, WidgetId,
18+
LayoutCtx, PaintCtx, Point, PointerEvent, QueryCtx, Rect, RegisterCtx, Size, TextEvent, Widget,
19+
WidgetId,
1920
};
2021
use parley::layout::Alignment;
2122
use parley::style::{FontFamily, FontStack, StyleProperty};
@@ -139,8 +140,8 @@ impl Widget for CustomWidget {
139140
SmallVec::new()
140141
}
141142

142-
fn make_trace_span(&self) -> Span {
143-
trace_span!("CustomWidget")
143+
fn make_trace_span(&self, ctx: &QueryCtx<'_>) -> Span {
144+
trace_span!("CustomWidget", id = ctx.widget_id().trace())
144145
}
145146
}
146147

masonry/src/passes/accessibility.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use crate::render_root::{RenderRoot, RenderRootState};
1010
use crate::tree_arena::ArenaMut;
1111
use crate::{AccessCtx, Widget, WidgetState};
1212

13+
use super::enter_span_if;
14+
1315
// --- MARK: BUILD TREE ---
1416
fn build_accessibility_tree(
1517
global_state: &mut RenderRootState,
@@ -19,10 +21,12 @@ fn build_accessibility_tree(
1921
rebuild_all: bool,
2022
scale_factor: f64,
2123
) {
22-
let _span = global_state
23-
.trace
24-
.access
25-
.then(|| widget.item.make_trace_span().entered());
24+
let _span = enter_span_if(
25+
global_state.trace.access,
26+
global_state,
27+
widget.reborrow(),
28+
state.reborrow(),
29+
);
2630
let id = state.item.id;
2731

2832
if !rebuild_all && !state.item.needs_accessibility {

masonry/src/passes/anim.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use tracing::info_span;
55

6-
use crate::passes::recurse_on_children;
6+
use crate::passes::{enter_span_if, recurse_on_children};
77
use crate::render_root::{RenderRoot, RenderRootState};
88
use crate::tree_arena::ArenaMut;
99
use crate::{UpdateCtx, Widget, WidgetState};
@@ -15,11 +15,12 @@ fn update_anim_for_widget(
1515
mut state: ArenaMut<'_, WidgetState>,
1616
elapsed_ns: u64,
1717
) {
18-
let _span = global_state
19-
.trace
20-
.anim
21-
.then(|| widget.item.make_trace_span().entered());
22-
18+
let _span = enter_span_if(
19+
global_state.trace.anim,
20+
global_state,
21+
widget.reborrow(),
22+
state.reborrow(),
23+
);
2324
if !state.item.needs_anim {
2425
return;
2526
}

masonry/src/passes/compose.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use tracing::info_span;
55
use vello::kurbo::Vec2;
66

7-
use crate::passes::recurse_on_children;
7+
use crate::passes::{enter_span_if, recurse_on_children};
88
use crate::render_root::{RenderRoot, RenderRootSignal, RenderRootState};
99
use crate::tree_arena::ArenaMut;
1010
use crate::{ComposeCtx, Widget, WidgetState};
@@ -17,10 +17,12 @@ fn compose_widget(
1717
parent_moved: bool,
1818
parent_translation: Vec2,
1919
) {
20-
let _span = global_state
21-
.trace
22-
.compose
23-
.then(|| widget.item.make_trace_span().entered());
20+
let _span = enter_span_if(
21+
global_state.trace.compose,
22+
global_state,
23+
widget.reborrow(),
24+
state.reborrow(),
25+
);
2426

2527
let moved = parent_moved || state.item.translation_changed;
2628
let translation = parent_translation + state.item.translation + state.item.origin.to_vec2();

masonry/src/passes/event.rs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use tracing::{debug, info_span, trace};
66
use winit::event::ElementState;
77
use winit::keyboard::{KeyCode, PhysicalKey};
88

9-
use crate::passes::merge_state_up;
9+
use crate::passes::{enter_span, merge_state_up};
1010
use crate::render_root::RenderRoot;
1111
use crate::{AccessEvent, EventCtx, Handled, PointerEvent, TextEvent, Widget, WidgetId};
1212

@@ -46,21 +46,24 @@ fn run_event_pass<E>(
4646
let mut is_handled = false;
4747
while let Some(widget_id) = target_widget_id {
4848
let parent_id = root.widget_arena.parent_of(widget_id);
49-
let (widget_mut, state_mut) = root.widget_arena.get_pair_mut(widget_id);
50-
51-
let mut ctx = EventCtx {
52-
global_state: &mut root.global_state,
53-
widget_state: state_mut.item,
54-
widget_state_children: state_mut.children,
55-
widget_children: widget_mut.children,
56-
target: original_target.unwrap(),
57-
allow_pointer_capture,
58-
is_handled: false,
59-
};
60-
let widget = widget_mut.item;
49+
let (mut widget_mut, mut state_mut) = root.widget_arena.get_pair_mut(widget_id);
6150

6251
if !is_handled {
63-
let _span = widget.make_trace_span().entered();
52+
let _span = enter_span(
53+
&root.global_state,
54+
widget_mut.reborrow(),
55+
state_mut.reborrow(),
56+
);
57+
let mut ctx = EventCtx {
58+
global_state: &mut root.global_state,
59+
widget_state: state_mut.item,
60+
widget_state_children: state_mut.children,
61+
widget_children: widget_mut.children,
62+
target: original_target.unwrap(),
63+
allow_pointer_capture,
64+
is_handled: false,
65+
};
66+
let widget = widget_mut.item;
6467
if trace {
6568
trace!(
6669
"Widget '{}' {} visited",

masonry/src/passes/layout.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use smallvec::SmallVec;
1010
use tracing::{info_span, trace};
1111
use vello::kurbo::{Point, Rect, Size};
1212

13-
use crate::passes::recurse_on_children;
13+
use crate::passes::{enter_span_if, recurse_on_children};
1414
use crate::render_root::{RenderRoot, RenderRootSignal, WindowSizePolicy};
1515
use crate::widget::WidgetState;
1616
use crate::{BoxConstraints, LayoutCtx, Widget, WidgetPod};
@@ -28,7 +28,12 @@ pub(crate) fn run_layout_on<W: Widget>(
2828
let mut state = parent_ctx.widget_state_children.get_child_mut(id).unwrap();
2929

3030
let trace = parent_ctx.global_state.trace.layout;
31-
let _span = trace.then(|| widget.item.make_trace_span().entered());
31+
let _span = enter_span_if(
32+
trace,
33+
parent_ctx.global_state,
34+
widget.reborrow(),
35+
state.reborrow(),
36+
);
3237

3338
let mut children_ids = SmallVec::new();
3439
if cfg!(debug_assertions) {

masonry/src/passes/mod.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
// Copyright 2024 the Xilem Authors
22
// SPDX-License-Identifier: Apache-2.0
33

4-
use crate::tree_arena::{ArenaMut, ArenaMutChildren};
4+
use tracing::span::EnteredSpan;
5+
6+
use crate::render_root::RenderRootState;
7+
use crate::tree_arena::{ArenaMut, ArenaMutChildren, ArenaRef};
58
use crate::widget::WidgetArena;
6-
use crate::{Widget, WidgetId, WidgetState};
9+
use crate::{QueryCtx, Widget, WidgetId, WidgetState};
710

811
pub(crate) mod accessibility;
912
pub(crate) mod anim;
@@ -14,6 +17,35 @@ pub(crate) mod mutate;
1417
pub(crate) mod paint;
1518
pub(crate) mod update;
1619

20+
#[must_use = "Span will be immediately closed if dropped"]
21+
pub(crate) fn enter_span_if(
22+
enabled: bool,
23+
global_state: &RenderRootState,
24+
widget: ArenaRef<'_, Box<dyn Widget>>,
25+
state: ArenaRef<'_, WidgetState>,
26+
) -> Option<EnteredSpan> {
27+
if enabled {
28+
Some(enter_span(global_state, widget, state))
29+
} else {
30+
None
31+
}
32+
}
33+
34+
#[must_use = "Span will be immediately closed if dropped"]
35+
pub(crate) fn enter_span(
36+
global_state: &RenderRootState,
37+
widget: ArenaRef<'_, Box<dyn Widget>>,
38+
state: ArenaRef<'_, WidgetState>,
39+
) -> EnteredSpan {
40+
let ctx = QueryCtx {
41+
global_state,
42+
widget_state: state.item,
43+
widget_state_children: state.children,
44+
widget_children: widget.children,
45+
};
46+
widget.item.make_trace_span(&ctx).entered()
47+
}
48+
1749
pub(crate) fn recurse_on_children(
1850
id: WidgetId,
1951
mut widget: ArenaMut<'_, Box<dyn Widget>>,
@@ -68,6 +100,12 @@ pub(crate) fn merge_state_up(arena: &mut WidgetArena, widget_id: WidgetId) {
68100
/// `MASONRY_TRACE_PASSES` environment variable.
69101
///
70102
/// Note that passes which are bounded by depth (rather than absolute size) are never filtered out here.
103+
///
104+
/// Ideally, we'd cache the spans, which would make a lot (but not all) of this unnecessary.
105+
/// However, each pass uses a different parent span (with the individual pass's name), so it's
106+
/// (at best) non-trivial to make that work.
107+
///
108+
/// We could *maybe* use a global parent span called "Pass", with a name field, but that's extremely ugly.
71109
pub(crate) struct PassTracing {
72110
pub(crate) update_tree: bool,
73111
pub(crate) anim: bool,

masonry/src/passes/paint.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use vello::kurbo::{Affine, Stroke};
88
use vello::peniko::Mix;
99
use vello::Scene;
1010

11-
use crate::passes::recurse_on_children;
11+
use crate::passes::{enter_span_if, recurse_on_children};
1212
use crate::render_root::{RenderRoot, RenderRootState};
1313
use crate::theme::get_debug_color;
1414
use crate::tree_arena::ArenaMut;
@@ -24,7 +24,8 @@ fn paint_widget(
2424
debug_paint: bool,
2525
) {
2626
let trace = global_state.trace.paint;
27-
let _span = trace.then(|| widget.item.make_trace_span().entered());
27+
let _span = enter_span_if(trace, global_state, widget.reborrow(), state.reborrow());
28+
2829
let id = state.item.id;
2930

3031
// TODO - Handle invalidation regions

masonry/src/passes/update.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use cursor_icon::CursorIcon;
77
use tracing::{info_span, trace};
88

99
use crate::passes::event::run_on_pointer_event_pass;
10-
use crate::passes::{merge_state_up, recurse_on_children};
10+
use crate::passes::{enter_span, enter_span_if, merge_state_up, recurse_on_children};
1111
use crate::render_root::{RenderRoot, RenderRootSignal, RenderRootState};
1212
use crate::tree_arena::ArenaMut;
1313
use crate::{
@@ -82,7 +82,7 @@ fn update_widget_tree(
8282
mut state: ArenaMut<'_, WidgetState>,
8383
) {
8484
let trace = global_state.trace.update_tree;
85-
let _span = trace.then(|| widget.item.make_trace_span().entered());
85+
let _span = enter_span_if(trace, global_state, widget.reborrow(), state.reborrow());
8686
let id = state.item.id;
8787

8888
if !state.item.children_changed {
@@ -196,7 +196,7 @@ fn update_disabled_for_widget(
196196
mut state: ArenaMut<'_, WidgetState>,
197197
parent_disabled: bool,
198198
) {
199-
let _span = widget.item.make_trace_span().entered();
199+
let _span = enter_span(global_state, widget.reborrow(), state.reborrow());
200200
let id = state.item.id;
201201

202202
let disabled = state.item.is_explicitly_disabled || parent_disabled;
@@ -260,7 +260,7 @@ fn update_stashed_for_widget(
260260
mut state: ArenaMut<'_, WidgetState>,
261261
parent_stashed: bool,
262262
) {
263-
let _span = widget.item.make_trace_span().entered();
263+
let _span = enter_span(global_state, widget.reborrow(), state.reborrow());
264264
let id = state.item.id;
265265

266266
let stashed = state.item.is_explicitly_stashed || parent_stashed;
@@ -327,10 +327,10 @@ pub(crate) fn run_update_stashed_pass(root: &mut RenderRoot) {
327327
fn update_focus_chain_for_widget(
328328
global_state: &mut RenderRootState,
329329
mut widget: ArenaMut<'_, Box<dyn Widget>>,
330-
state: ArenaMut<'_, WidgetState>,
330+
mut state: ArenaMut<'_, WidgetState>,
331331
parent_focus_chain: &mut Vec<WidgetId>,
332332
) {
333-
let _span = widget.item.make_trace_span().entered();
333+
let _span = enter_span(global_state, widget.reborrow(), state.reborrow());
334334
let id = state.item.id;
335335

336336
if !state.item.update_focus_chain {

0 commit comments

Comments
 (0)